Skip to content

Commit

Permalink
Merge branch 'master' of github.com:gyunaev/birdtray
Browse files Browse the repository at this point in the history
  • Loading branch information
gyunaev committed Oct 29, 2020
2 parents 5eb499d + adbee18 commit 9ff57bb
Show file tree
Hide file tree
Showing 41 changed files with 2,286 additions and 1,890 deletions.
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
* text=auto
src/translations/main_*.ts text eol=lf
src/translations/dynamic_*.ts text eol=lf
src/translations/installer_*.ts text eol=crlf
17 changes: 17 additions & 0 deletions .github/problem-matchers/translations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"problemMatcher": [
{
"owner": "checkTranslation",
"pattern": [
{
"regexp": "^\\[(.*)\\]\\s+(.*):(\\d+):(\\d+):\\s+(.*)$",
"severity": 1,
"file": 2,
"line": 3,
"column": 4,
"message": 5
}
]
}
]
}
147 changes: 72 additions & 75 deletions .github/scripts/checkTranslation.py

Large diffs are not rendered by default.

130 changes: 89 additions & 41 deletions .github/workflows/translations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ name: Check the translations
on:
push:
paths:
- 'src/translations/**.ts'
- 'src/translations/*'
pull_request:
paths:
- 'src/translations/**.ts'
- 'src/translations/*'

jobs:
check:
Expand All @@ -17,7 +17,75 @@ jobs:
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Installer translations special checks
- name: Check translation filenames
shell: python
run: |
import os
import sys
haveError = False
for fileName in os.listdir(os.path.join('src', 'translations')):
filePath = os.path.join('src', 'translations', fileName)
if not fileName.endswith('.ts'):
haveError = True
print(f'::error file={filePath},line=1,col=1::Invalid translation filename: ' +
f'Must end with the "ts" extension.')
if not any(fileName.startswith(prefix)
for prefix in ['main_', 'dynamic_', 'installer_']):
haveError = True
print(f'::error file={filePath},line=1,col=1::Invalid translation filename: ' +
f'Must start with "main_", "dynamic_" or "installer_".')
sys.exit(1 if haveError else 0)
- name: All translations are registered in CMakeLists.txt
shell: python
run: |
import os
import re
import sys
from glob import iglob
with open('CMakeLists.txt') as cMakeListsFile:
cMakeListsContent = cMakeListsFile.read()
def checkTranslations(cMakeVariable, translationFileNames):
match = re.search(
rf'set\(\s*{cMakeVariable}(?P<start>\s*)(?P<translation>(?:.+?\s+)+?)\s*\)',
cMakeListsContent)
if match is None:
print(f'::error file=CMakeLists.txt,line=1,col=1::' +
f'Unable to find {cMakeVariable} variable')
sys.exit(1)
mainTranslationFiles = [path.replace('/', os.path.sep)
for path in match.group('translation').split()]
line = cMakeListsContent[:match.start()].count('\n') \
+ 1 + match.group('start').count('\n')
TRANSLATION_LINE = re.compile(r'^(?P<start>\s*).*?(?P<end>\s*)$')
start = None
for i, translationLine in enumerate(match.group('translation').split('\n')):
match = TRANSLATION_LINE.match(translationLine)
if match:
lineStart = match.group('start')
lineEnd = match.group('end')
if start is None:
if i != 0 or lineStart != '':
start = lineStart
elif start != lineStart:
print(f'::warning file=CMakeLists.txt,line={line + i},col=1::' +
f'Invalid start indentation, expected {start!r}, got {lineStart!r}')
if len(lineEnd):
print(f'::warning file=CMakeLists.txt,line={line + i},col=1::' +
f'Trailing whitespaces')
errorFound = False
for translation in iglob(os.path.join('src', 'translations', translationFileNames)):
if translation not in mainTranslationFiles:
errorFound = True
print(f'::error file=CMakeLists.txt,line={line},col=1::' +
f'Translation file {translation} is not registered ' +
f'in the {cMakeVariable} list in CMakeList.txt')
return errorFound
haveError = checkTranslations('MAIN_TRANSLATION_FILES', 'main_*.ts')
haveError = checkTranslations('DYN_TRANSLATION_FILES', 'dynamic_*.ts') or haveError
sys.exit(1 if haveError else 0)
- name: Special checks for installer translations
shell: python
run: |
import os
Expand All @@ -35,6 +103,17 @@ jobs:
for installerTranslation in iglob(os.path.join('src', 'translations', 'installer_*.ts')):
language = os.path.splitext(os.path.basename(installerTranslation))[0][10:]
translations[language] = installerTranslation
baseTranslationFile = os.path.join('src', 'translations', 'installer_en.ts')
baseTranslation = ElementTree.parse(baseTranslationFile)
sourceKeys = [source.text for source in baseTranslation.findall('context/message/source')]
for language in translations:
languageNameId = 'Lang_' + language
languageNameElement = baseTranslation.find(
f'context/message/translation[.=\'{languageNameId}\']')
if languageNameElement is None:
haveError = True
print(f'::error file={baseTranslationFile},line=1,col=1::' +
f'Missing translation for language name "{languageNameId}"')
for translationFilePath in translations.values():
translation = ElementTree.parse(translationFilePath)
languageNameElement = translation.find(
Expand All @@ -57,48 +136,17 @@ jobs:
f'Invalid __LANGUAGE_NAME__: "{languageName}" is not in the list of ' +
f'possible language names: ["{languageNamesString}"]')
haveError = True
for language in translations:
languageNameSource = 'Lang_' + language
languageNameElement = translation.find(
f'context/message/source[.=\'{languageNameSource}\']')
if languageNameElement is None:
for sourceKey in sourceKeys:
if next((source for source in translation.iterfind(f'context/message/source')
if source.text == sourceKey), None) is None:
print(f'::warning file={translationFilePath},line=1,col=1::' +
f'Missing language name "{languageNameSource}"')
f'Missing translation for source "{sourceKey}"')
sys.exit(1 if haveError else 0)
- name: Prepare the installer translations for linting
shell: python
run: |
import os
import re
from glob import iglob
from xml.etree import ElementTree
SOURCE_PATTERN = re.compile(r'^\s+<source>(?P<name>.*)</source>$')
sourceXml = ElementTree.parse(os.path.join('src', 'translations', 'installer_en.ts'))
sourceMap = {message.find('source').text: message.find('translation').text
for message in sourceXml.findall('context/message')}
for translation in iglob(os.path.join('src', 'translations', 'installer_*[!e][!n].ts')):
originalTranslation = translation + '.tmp'
os.rename(translation, originalTranslation)
with open(originalTranslation, encoding='utf-8') as originalTranslationFile:
with open(translation, 'w', encoding='utf-8') as translationFile:
for line in originalTranslationFile:
match = SOURCE_PATTERN.match(line)
if not match:
translationFile.write(line)
continue
sourceId = match.group('name')
source = sourceMap.get(sourceId)
if source is None:
translationFile.write(line)
continue
translationFile.write(line.replace(sourceId, source))
os.remove(originalTranslation)
- name: Lint the translations
run: |
set +e
.github/scripts/checkTranslation.py src/translations/dynamic_*[!e][!n].ts src/translations/main_*[!e][!n].ts
echo "::add-matcher::.github/problem-matchers/translations.json"
.github/scripts/checkTranslation.py src/translations/dynamic_*.ts src/translations/main_*.ts -e src/translations/*_en.ts -i unfinished_translation
ret=$?
.github/scripts/checkTranslation.py src/translations/installer_*[!e][!n].ts -p '(?P<match>\d+)' '(?P<match>\$\{.*?\})' '(?P<match>\$\\[rn])' '(?P<match>\$\d+)'
.github/scripts/checkTranslation.py src/translations/installer_*.ts -e src/translations/*_en.ts -p '(?P<match>\d+)' '(?P<match>\$\{.*?\})' '(?P<match>\$\\[rn])' '(?P<match>\$\d+)'
exit $(( $ret + $? ))
42 changes: 42 additions & 0 deletions installer/Log.nsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
Var stdout

# Initialize the logging system.
!macro InitLog
Push $0
System::Call 'kernel32::GetStdHandle(i -11)i.r0'
System::Call 'kernel32::AttachConsole(i -1)'
StrCpy $stdout $0
Pop $0
!macroend
!define InitLog '!insertmacro InitLog'

# Print the message to stdout.
# $0 - MESSAGE: The message to print.
Function Print
Exch $0
DetailPrint "$0"
Push $1
StrCpy $1 "0"
IfErrors 0 +2
StrCpy $1 "1"
FileWrite $stdout `$0$\r$\n`
StrCmp $1 "1" 0 +2
SetErrors
Pop $1
Pop $0
FunctionEnd

!macro Print MESSAGE
Push "${MESSAGE}"
Call Print
!macroend
!define Print '!insertmacro Print'

# Displays an error message and aborts the script.
# MESSAGE: The message to display.
!macro Fatal MESSAGE
${Print} "${MESSAGE}"
setErrorLevel 2
Quit
!macroend
!define Fatal '!insertmacro Fatal'
43 changes: 0 additions & 43 deletions installer/StrUtils.nsh

This file was deleted.

7 changes: 4 additions & 3 deletions installer/Utils.nsh
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
!include LogicLib.nsh
!include x64.nsh
!include nsProcess.nsh
!include StrUtils.nsh
!include StrFunc.nsh
${StrLoc}

!define ERROR_ALREADY_EXISTS 0x000000b7
!define ERROR_ACCESS_DENIED 0x5
Expand Down Expand Up @@ -132,7 +133,7 @@ Function StrContainsAnyOf
StrCpy $R2 $STR_CAO_CHARACTERS 1 $R1
StrCmp $R2 '' end
IntOp $R1 $R1 + 1
${StrContains} $R0 $R2 $STR_CAO_STRING
${StrLoc} $R0 $STR_CAO_STRING $R2 ">"
${if} $R0 != ""
StrCpy $STR_CAO_RETURN_VAR 1
goto end
Expand Down Expand Up @@ -249,7 +250,6 @@ FunctionEnd
Call OpenURL
!macroend
!define OpenURL "!insertmacro OpenURL"
!endif # UNINSTALL_BUILDER

# === Macros === #

Expand Down Expand Up @@ -279,6 +279,7 @@ FunctionEnd
Quit
${endif}
!macroend
!endif # UNINSTALL_BUILDER

# Check if a registry key exists.
# ROOT: The registry root key.
Expand Down
40 changes: 19 additions & 21 deletions installer/buildInstaller.bat
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,6 @@ if errorLevel 1 (
echo to the deployment folder at "%dependencyFolder%\Include" 1>&2
exit /b %errorLevel%
)
xcopy "%TEMP%\NsProcess\nsProcess.dll" "%dependencyFolder%\Plugins\x86-ansi" /q /y 1>nul
if errorLevel 1 (
echo Failed to copy the NsProcess library from "%TEMP%\NsProcess\nsProcess.dll" 1>&2
echo to the deployment folder at "%dependencyFolder%\Plugins\x86-ansi" 1>&2
exit /b %errorLevel%
)
xcopy "%TEMP%\NsProcess\nsProcessW.dll" "%dependencyFolder%\Plugins\x86-unicode" /q /y 1>nul
if errorLevel 1 (
echo Failed to copy the NsProcess library from "%TEMP%\NsProcess\nsProcessW.dll" 1>&2
Expand All @@ -199,37 +193,41 @@ if errorLevel 1 (
echo to the deployment folder at "%dependencyFolder%\Plugins\x86-unicode" 1>&2
exit /b %errorLevel%
)
set "nsisXMLUrl=https://nsis.sourceforge.io/mediawiki/images/5/55/Xml.zip"
"%curlExe%" --silent --output "%TEMP%\nsisXML.zip" "%nsisXMLUrl%" 1>nul
set "nsArrayUrl=https://nsis.sourceforge.io/mediawiki/images/9/97/NsArray.zip"
"%curlExe%" --silent --output "%TEMP%\nsArray.zip" "%nsArrayUrl%" 1>nul
if errorLevel 1 (
echo Failed to download nsisXML 1>&2
echo Failed to download nsArray 1>&2
exit /b %errorLevel%
)
"%sevenZExe%" e -y -o"%TEMP%\nsisXML" "%TEMP%\nsisXML.zip" 1>nul
"%sevenZExe%" x -y -o"%TEMP%\nsArray" "%TEMP%\nsArray.zip" 1>nul
if errorLevel 1 (
echo Failed to extract nsisXML 1>&2
echo Failed to extract nsArray 1>&2
exit /b %errorLevel%
)
del "%TEMP%\nsisXML.zip" /F
xcopy "%TEMP%\nsisXML\XML.nsh" "%dependencyFolder%\Include" /q /y 1>nul
del "%TEMP%\nsArray.zip" /F
xcopy "%TEMP%\nsArray\Include\nsArray.nsh" "%dependencyFolder%\Include" /q /y 1>nul
if errorLevel 1 (
echo Failed to copy the nsisXML library from "%TEMP%\nsisXML\XML.nsh" 1>&2
echo Failed to copy the nsArray library from "%TEMP%\nsArray\Include\nsArray.nsh" 1>&2
echo to the deployment folder at "%dependencyFolder%\Include" 1>&2
exit /b %errorLevel%
)
xcopy "%TEMP%\nsisXML\xml.dll" "%dependencyFolder%\Plugins\x86-ansi" /q /y 1>nul
xcopy "%TEMP%\nsArray\Plugins\x86-unicode\nsArray.dll" ^
"%dependencyFolder%\Plugins\x86-unicode" /q /y 1>nul
if errorLevel 1 (
echo Failed to copy the nsisXML library from "%TEMP%\nsisXML\xml.dll" 1>&2
echo to the deployment folder at "%dependencyFolder%\Plugins\x86-ansi" 1>&2
echo Failed to copy the nsArray library from 1>&2
echo "%TEMP%\nsArray\Plugins\x86-unicode\nsArray.dll" 1>&2
echo to the deployment folder at "%dependencyFolder%\Plugins\x86-unicode" 1>&2
exit /b %errorLevel%
)
xcopy "%TEMP%\nsisXML\xml.dll" "%dependencyFolder%\Plugins\x86-unicode" /q /y 1>nul
rmdir /s /q "%TEMP%\nsArray" 1>nul
echo xcopy "%~dp0deps\nsisXML.dll" "%dependencyFolder%\Plugins\x86-unicode" /q /y 1>nul
"%sevenZExe%" e "%~dp0deps\nsisXML.zip" -y -o"%dependencyFolder%\Plugins\x86-unicode" ^
-i!"*.dll" 1>nul
if errorLevel 1 (
echo Failed to copy the nsisXML library from "%TEMP%\nsisXML\xml.dll" 1>&2
echo Failed to extract the nsisXML library from "%~dp0deps\nsisXML.zip:*.dll" 1>&2
echo to the deployment folder at "%dependencyFolder%\Plugins\x86-unicode" 1>&2
exit /b %errorLevel%
)
rmdir /s /q "%TEMP%\nsisXML" 1>nul

rem #### Create the actual installer ####
echo Creating the installer...
Expand Down Expand Up @@ -267,5 +265,5 @@ echo --install: Optional parameter. If specified, executes the generated ins
echo:
echo The following programs must be on the PATH: windeployqt, makensis, g++, git, curl and 7z.
echo The script also searches for translations in translations subdirectory
echo of the directory containing the birdtray executable.
echo of the directory containing the Birdtray executable.
goto :eof
Binary file added installer/deps/nsisXML.zip
Binary file not shown.
Loading

0 comments on commit 9ff57bb

Please sign in to comment.