diff --git a/bin/Packager/Nsis/NullsoftInstaller.nsi b/bin/Packager/Nsis/NullsoftInstaller.nsi index 81e9ffee5..508c3ecc7 100644 --- a/bin/Packager/Nsis/NullsoftInstaller.nsi +++ b/bin/Packager/Nsis/NullsoftInstaller.nsi @@ -1,194 +1,187 @@ ; Copyright 2010 Patrick Spendrin ; Copyright 2016 Kevin Funk ; Copyright Hannah von Reth ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions ; are met: ; 1. Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; 2. Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in the ; documentation and/or other materials provided with the distribution. ; ; THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ; ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ; SUCH DAMAGE. ; registry stuff !define regkey "Software\@{company}\@{productname}" !define uninstkey "Software\Microsoft\Windows\CurrentVersion\Uninstall\@{productname}" !define uninstaller "uninstall.exe" BrandingText "Generated by Craft https://community.kde.org/Craft" ;-------------------------------- XPStyle on ManifestDPIAware true Name "@{productname}" Caption "@{productname} @{version}" OutFile "@{setupname}" !define MULTIUSER_EXECUTIONLEVEL Highest !define MULTIUSER_MUI !define MULTIUSER_INSTALLMODE_COMMANDLINE !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY "${regkey}" !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME "Install_Mode" !define MULTIUSER_INSTALLMODE_INSTDIR "@{productname}" !define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY "${regkey}" !define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME "Install_Dir" ;Start Menu Folder Page Configuration Var StartMenuFolder !define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX" !define MUI_STARTMENUPAGE_REGISTRY_KEY "${regkey}" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" ;!define MULTIUSER_USE_PROGRAMFILES64 @{multiuser_use_programfiles64} ;!define MULTIUSER_USE_PROGRAMFILES64 @{nsis_include_internal} @{nsis_include} !include "MultiUser.nsh" !include "MUI2.nsh" !include "LogicLib.nsh" !include "x64.nsh" !include "process.nsh" ;!define MUI_ICON @{installerIcon} ;!define MUI_ICON !insertmacro MUI_PAGE_WELCOME ;!insertmacro MUI_PAGE_LICENSE @{license} ;!insertmacro MUI_PAGE_LICENSE !insertmacro MULTIUSER_PAGE_INSTALLMODE !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder !define MUI_COMPONENTSPAGE_NODESC ;!insertmacro MUI_PAGE_COMPONENTS @{sections_page} ;!insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES !define MUI_FINISHPAGE_LINK "Visit project homepage" !define MUI_FINISHPAGE_LINK_LOCATION "@{website}" !insertmacro MUI_PAGE_FINISH !insertmacro MUI_LANGUAGE "English" SetDateSave on SetDatablockOptimize on CRCCheck on SilentInstall normal Function .onInit !insertmacro MULTIUSER_INIT !if @{architecture} == "x64" ${IfNot} ${RunningX64} MessageBox MB_OK|MB_ICONEXCLAMATION "This installer can only be run on 64-bit Windows." Abort ${EndIf} !endif FunctionEnd Function un.onInit !insertmacro MULTIUSER_UNINIT FunctionEnd ;-------------------------------- AutoCloseWindow false ; beginning (invisible) section Section !insertmacro EndProcessWithDialog ExecWait '"$MultiUser.InstDir\${uninstaller}" /S _?=$MultiUser.InstDir' @{preInstallHook} WriteRegStr SHCTX "${regkey}" "Install_Dir" "$INSTDIR" WriteRegStr SHCTX "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}" "$MultiUser.InstallMode" ; write uninstall strings WriteRegStr SHCTX "${uninstkey}" "DisplayName" "@{productname}" WriteRegStr SHCTX "${uninstkey}" "UninstallString" '"$INSTDIR\${uninstaller}"' WriteRegStr SHCTX "${uninstkey}" "DisplayIcon" "$INSTDIR\@{iconname}" WriteRegStr SHCTX "${uninstkey}" "URLInfoAbout" "@{website}" WriteRegStr SHCTX "${uninstkey}" "Publisher" "@{company}" WriteRegStr SHCTX "${uninstkey}" "DisplayVersion" "@{version}" @{registy_hook} SetOutPath $INSTDIR ; package all files, recursively, preserving attributes ; assume files are in the correct places File /a "@{dataPath}" File /a "@{7za}" File /a "@{icon}" nsExec::ExecToLog '"$INSTDIR\7za.exe" x -r -y "$INSTDIR\@{dataName}" -o"$INSTDIR"' Delete "$INSTDIR\7za.exe" Delete "$INSTDIR\@{dataName}" AddSize @{installSize} WriteUninstaller "${uninstaller}" SectionEnd ; create shortcuts -Section -!insertmacro MUI_STARTMENU_WRITE_BEGIN Application -CreateDirectory "$SMPROGRAMS\$StartMenuFolder" -SetOutPath $INSTDIR ; for working directory @{shortcuts} -CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\uninstall.exe" -!insertmacro MUI_STARTMENU_WRITE_END -SectionEnd ; allow to define additional sections @{sections} ; Uninstaller ; All section names prefixed by "Un" will be in the uninstaller UninstallText "This will uninstall @{productname}." Section "Uninstall" !insertmacro EndProcessWithDialog DeleteRegKey SHCTX "${uninstkey}" DeleteRegKey SHCTX "${regkey}" !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder RMDir /r "$SMPROGRAMS\$StartMenuFolder" RMDir /r "$INSTDIR" SectionEnd ; allow to define additional Un.sections @{un_sections} \ No newline at end of file diff --git a/bin/Packager/NullsoftInstallerPackager.py b/bin/Packager/NullsoftInstallerPackager.py index 7ec27a959..4a5d515f9 100644 --- a/bin/Packager/NullsoftInstallerPackager.py +++ b/bin/Packager/NullsoftInstallerPackager.py @@ -1,184 +1,196 @@ # -*- coding: utf-8 -*- # Copyright (c) 2010 Patrick Spendrin # Copyright (c) 2010 Andre Heinecke (code taken from the kdepim-ce-package.py) # Copyright Hannah von Reth # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. import os from Utils import CraftHash from Packager.CollectionPackagerBase import * from Packager.PortablePackager import * from Blueprints.CraftVersion import CraftVersion class NullsoftInstallerPackager(PortablePackager): """ Packager for Nullsoft scriptable install system This Packager generates a nsis installer (an executable which contains all files) from the image directories of craft. This way you can be sure to have a clean installer. In your package, you can add regexp whitelists and blacklists (see example files for the fileformat). The files for both white- and blacklists, must be given already in the constructor. You can override the .nsi default script and you will get the following defines given into the nsis generator via commandline if you do not override the attributes of the same name in the dictionary self.defines: setupname: PACKAGENAME-setup-BUILDTARGET.exe PACKAGENAME is the name of the package srcdir: is set to the image directory, where all files from the image directories of all dependencies are gathered. You shouldn't normally have to set this. company: sets the company name used for the registry key of the installer. Default value is "KDE". productname: contains the capitalized PACKAGENAME and the buildTarget of the current package executable: executable is defined empty by default, but it is used to add a link into the start menu. You can add your own defines into self.defines as well. """ + SHORTCUT_SECTION = \ +""" + Section + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + CreateDirectory "$SMPROGRAMS\$StartMenuFolder" + SetOutPath $INSTDIR ; for working directory + {shortcuts} + !insertmacro MUI_STARTMENU_WRITE_END + SectionEnd +""" + @InitGuard.init_once def __init__(self, whitelists=None, blacklists=None): PortablePackager.__init__(self, whitelists, blacklists) self.nsisExe = None self._isInstalled = False def setDefaults(self, defines) -> {}: defines = super().setDefaults(defines) defines.setdefault("defaultinstdir", "$PROGRAMFILES64" if CraftCore.compiler.isX64() else "$PROGRAMFILES") defines.setdefault("multiuser_use_programfiles64", "!define MULTIUSER_USE_PROGRAMFILES64" if CraftCore.compiler.isX64() else "") defines.setdefault("setupname", self.binaryArchiveName(fileType="exe", includeRevision=True)) defines.setdefault("srcdir", self.archiveDir())# deprecated defines.setdefault("registy_hook", "") defines.setdefault("sections", "") defines.setdefault("un_sections", "") defines.setdefault("sections_page", "") defines.setdefault("preInstallHook", "") if not self.scriptname: self.scriptname = os.path.join(os.path.dirname(__file__), "Nsis", "NullsoftInstaller.nsi") return defines def isNsisInstalled(self): if not self._isInstalled: self._isInstalled = self.__isInstalled() if not self._isInstalled: CraftCore.log.critical("Craft requires Nsis to create a package, please install Nsis\n" "\t'craft nsis'") return False return True def __isInstalled(self): """ check if nsis (Nullsoft scriptable install system) is installed somewhere """ self.nsisExe = CraftCore.cache.findApplication("makensis") if not self.nsisExe: return False return CraftCore.cache.getVersion(self.nsisExe, versionCommand="/VERSION") >= CraftVersion("3.03") def _createShortcut(self, name, target, icon="", parameter="", description="") -> str: return f"""CreateShortCut "$SMPROGRAMS\$StartMenuFolder\\{name}.lnk" "$INSTDIR\\{OsUtils.toNativePath(target)}" "{parameter}" "{icon}" 0 SW_SHOWNORMAL "" "{description}"\n""" def folderSize(self, path): total = 0 for entry in os.scandir(path): if entry.is_file(): total += entry.stat().st_size elif entry.is_dir(): total += self.folderSize(entry.path) return total def generateNSISInstaller(self): """ runs makensis to generate the installer itself """ defines = self.setDefaults(self.defines) defines["dataPath"] = self.setupName defines["dataName"] = os.path.basename(self.setupName) defines["7za"] = CraftCore.cache.findApplication("7za") if CraftCore.compiler.isX64() else CraftCore.cache.findApplication("7za_32") # provide the actual installation size in kb, ignore the 7z size as it gets removed after the install defines["installSize"] = str(int((self.folderSize(self.archiveDir()) - os.path.getsize(self.setupName)) / 1000)) defines["installerIcon"] = f"""!define MUI_ICON "{defines["icon"]}" """ defines["iconname"] = os.path.basename(defines["icon"]) if not defines["license"] == "": defines["license"] = f"""!insertmacro MUI_PAGE_LICENSE "{defines["license"]}" """ shortcuts = [] if "executable" in defines: shortcuts.append(self._createShortcut(defines["productname"], defines["executable"])) del defines["executable"] - for short in self.shortcuts: + for short in defines["shortcuts"]: shortcuts.append(self._createShortcut(**short)) - defines["shortcuts"] = "".join(shortcuts) + if shortcuts: + defines["shortcuts"] = NullsoftInstallerPackager.SHORTCUT_SECTION.format(shortcuts = "".join(shortcuts)) if defines.get("sections", None): defines["sections_page"] = "!insertmacro MUI_PAGE_COMPONENTS" # make absolute path for output file if not os.path.isabs(defines["setupname"]): dstpath = self.packageDestinationDir() defines["setupname"] = os.path.join(dstpath, defines["setupname"]) self.setupName = defines["setupname"] CraftCore.debug.new_line() CraftCore.log.debug(f"generating installer {self.setupName}") verboseString = "/V4" if CraftCore.debug.verbose() > 0 else "/V3" defines.setdefault("nsis_include", f"!addincludedir {os.path.dirname(self.scriptname)}") defines["nsis_include_internal"] = f"!addincludedir {os.path.join(os.path.dirname(__file__), 'Nsis')}" cmdDefines = [] configuredScrip = os.path.join(self.workDir(), f"{self.package.name}.nsi") if not utils.configureFile(self.scriptname, configuredScrip, defines): configuredScrip = self.scriptname # this script uses the old behaviour, using defines for key, value in defines.items(): if value is not None: cmdDefines.append(f"/D{key}={value}") if not utils.systemWithoutShell([self.nsisExe, verboseString] + cmdDefines + [configuredScrip], cwd=os.path.abspath(self.packageDir())): CraftCore.log.critical("Error in makensis execution") return False return utils.sign([self.setupName]) def createPackage(self): """ create a package """ if not self.isNsisInstalled(): return False CraftCore.log.debug("packaging using the NullsoftInstallerPackager") if not super().createPackage(): return False if not self.generateNSISInstaller(): return False destDir, archiveName = os.path.split(self.setupName) self._generateManifest(destDir, archiveName) CraftHash.createDigestFiles(self.setupName) return True diff --git a/bin/Packager/PackagerBase.py b/bin/Packager/PackagerBase.py index 7177e5b5a..162fe1442 100644 --- a/bin/Packager/PackagerBase.py +++ b/bin/Packager/PackagerBase.py @@ -1,93 +1,84 @@ # # copyright (c) 2009 Ralf Habacker # # Packager base import datetime import json import glob from CraftBase import * from Utils import CraftHash from Utils.CraftManifest import * from CraftDebug import deprecated class PackagerBase(CraftBase): """ provides a generic interface for packagers and implements basic package creating stuff """ @InitGuard.init_once def __init__(self): CraftBase.__init__(self) self.whitelist_file = [] self.blacklist_file = [] self.defines = {} self.ignoredPackages = [] def setDefaults(self, defines: {str:str}) -> {str:str}: defines = dict(defines) + defines.setdefault("shortcuts", "") defines.setdefault("architecture", CraftCore.compiler.architecture) defines.setdefault("company", "KDE e.V.") defines.setdefault("productname", self.subinfo.displayName) defines.setdefault("display_name", self.subinfo.displayName) defines.setdefault("description", self.subinfo.description) defines.setdefault("icon", os.path.join(CraftCore.standardDirs.craftBin(), "data", "icons", "craft.ico")) defines.setdefault("icon_png", os.path.join(CraftCore.standardDirs.craftBin(), "data", "icons", "craftyBENDER.png")) defines.setdefault("icon_png_44", defines["icon_png"]) defines.setdefault("license", "") defines.setdefault("version", self.sourceRevision() if self.subinfo.hasSvnTarget() else self.version) defines.setdefault("website", self.subinfo.webpage if self.subinfo.webpage else "https://community.kde.org/Craft") # mac defines.setdefault("apppath", "") defines.setdefault("appname", self.package.name.lower()) return defines def getMacAppPath(self, defines, lookupPath = None): lookPath = os.path.normpath(lookupPath if lookupPath else self.archiveDir()) appPath = defines['apppath'] if not appPath: apps = glob.glob(os.path.join(lookPath, f"**/{defines['appname']}.app"), recursive=True) if len(apps) != 1: CraftCore.log.error(f"Failed to detect {defines['appname']}.app for {self}, please provide a correct self.defines['apppath'] or a relative path to the app as self.defines['apppath']") return False appPath = apps[0] appPath = os.path.join(lookPath, appPath) return os.path.normpath(appPath) def preArchive(self): utils.abstract() def archiveDir(self): return os.path.join(self.buildRoot(), "archive") # """ create a package """ def createPackage(self): utils.abstract() def _generateManifest(self, destDir, archiveName, manifestLocation=None, manifestUrls=None): if not manifestLocation: manifestLocation = destDir manifestLocation = os.path.join(manifestLocation, "manifest.json") archiveFile = os.path.join(destDir, archiveName) name = archiveName if not os.path.isabs(archiveName) else os.path.relpath(archiveName, destDir) manifest = CraftManifest.load(manifestLocation, urls=manifestUrls) entry = manifest.get(str(self)) entry.addFile(name, CraftHash.digestFile(archiveFile, CraftHash.HashAlgorithm.SHA256), version=self.version) - manifest.dump(manifestLocation) - - @property - def shortcuts(self) -> []: - """ Return a list of shortcuts we want installe""" - out = [] - if "shortcuts" in self.defines: - out += self.defines["shortcuts"] - return out - - + manifest.dump(manifestLocation) \ No newline at end of file diff --git a/bin/Packager/QtIFPackager.py b/bin/Packager/QtIFPackager.py index faa40d662..412c60f12 100644 --- a/bin/Packager/QtIFPackager.py +++ b/bin/Packager/QtIFPackager.py @@ -1,145 +1,146 @@ # -*- coding: utf-8 -*- # Copyright Hannah von Reth # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. import datetime import cgi from Blueprints.MetaInfo import MetaInfo from Blueprints.CraftDependencyPackage import * from Packager.SevenZipPackager import * from Utils import CraftHash from Blueprints.CraftVersion import * from Package.VirtualPackageBase import VirtualPackageBase from CraftOS.osutils import OsUtils class QtIFPackager(SevenZipPackager): # Generate packages that can be used by the qt installer framework # to generate a repo or offline installer call "craft --package qt-installer-framework" # To manage the packaged dependencies using [Packager]CacheDirectTargetsOnly = True and the use # of a package.list is recommended. # TODO: the root package is currently hardcoded in __rootPackage @InitGuard.init_once def __init__(self): self.__resources = os.path.join(os.path.dirname(__file__), "QtIF") SevenZipPackager.__init__(self) self.__packageDir = os.path.join(self.packageDestinationDir(), "qtif") self.__sdkMode = OsUtils.isWin() and CraftCore.settings.getboolean("QtSDK", "Enabled", False) if self.__sdkMode: win = "win32" if CraftCore.compiler.isX86() else "win64" self.__imagePrefix = os.path.join(CraftCore.settings.get("QtSDK", "Version"), CraftCore.settings.get("QtSDK", "Compiler")) self.__depPrefix = f"{self.__rootPackage}.{CraftCore.settings.get('QtSDK', 'Version').replace('.', '')}.{win}_{CraftCore.settings.get('QtSDK', 'Compiler')}" else: self.__depPrefix = self.__rootPackage self.__imagePrefix = "" @property def __rootPackage(self): #TODO: allow to specify the root node return "kdab" def __qtiFy(self, package): path = f"{self.__depPrefix}.{package.path}" return path.replace("/", ".").replace("-", "_") - def _shortCuts(self): + def _shortCuts(self, defines): out = [] def shortCut(name, target, icon="", parameter="", description=""): target = OsUtils.toUnixPath(os.path.join(self.__imagePrefix, target)) name = OsUtils.toUnixPath(name) if self.__sdkMode: name = f"{name} for Qt {CraftCore.settings.get('QtSDK', 'Version')} {CraftCore.settings.get('QtSDK', 'Compiler')}" return f'component.addOperation( "CreateShortcut", "@TargetDir@/{target}","@StartMenuDir@/{name}.lnk");' - if "executable" in self.defines: - out += [shortCut(self.subinfo.displayName, self.defines["executable"])] + if "executable" in defines: + out += [shortCut(self.subinfo.displayName, defines["executable"])] - for short in self.shortcuts: + for short in defines["shortcuts"]: out += [shortCut(**short)] return "\n".join(out) - def __createMeta(self, dstpath : str, name : str, version : str, description : str, webpage : str, deps : str=""): + def __createMeta(self, defines, *, dstpath : str, name : str, version : str, description : str, webpage : str, deps : str=""): data = {"VERSION" : str(CraftVersion(version).strictVersion), "NAME" : name, "DESCRIPTION" : cgi.escape(f"{name} {version}
{description}" + (f"
{webpage}" if webpage else "")), "DATE" : datetime.datetime.utcnow().strftime("%Y-%m-%d"), "DEPENDENCIES" : deps} if not utils.configureFile(os.path.join(self.__resources, "package.xml"), os.path.join(dstpath, "meta", "package.xml"), data): return False - data = {"SHORTCUTS" : self._shortCuts()} + data = {"SHORTCUTS" : self._shortCuts(defines=defines)} if not utils.configureFile(os.path.join(self.__resources, "installscript.qs"), os.path.join(dstpath, "meta", "installscript.qs"), data): return False return True def __resolveDeps(self): deps = [] for package in CraftDependencyPackage(self.package).getDependencies(DependencyType.Runtime): if isinstance(package.instance, VirtualPackageBase): continue if package == self.package: continue # in case we don't want to provide a full installer if CraftCore.settings.getboolean("Packager", "CacheDirectTargetsOnly") and package not in CraftCore.state.directTargets: continue deps += [self.__qtiFy(package)] return deps - def _addPackage(self) -> bool: + def _addPackage(self, defines) -> bool: dstpath = os.path.join(self.__packageDir, "image", self.__qtiFy(self.package)) if not os.path.exists(dstpath): if self.__sdkMode: # adept the prefix utils.cleanDirectory(self.archiveDir()) utils.copyDir(self.imageDir(), os.path.join(self.archiveDir(), self.__imagePrefix)) if not self._compress("data.7z", self.imageDir() if not self.__sdkMode else self.archiveDir(), os.path.join(dstpath, "data"), createDigests=False): return False info = MetaInfo(self.package) - return self.__createMeta(dstpath ,info.displayName, self.version, info.description, info.webpage, ", ".join(self.__resolveDeps())) + return self.__createMeta(defines, dstpath=dstpath , name=info.displayName, version=self.version, description=info.description, webpage=info.webpage, deps=", ".join(self.__resolveDeps())) - def __initPrefix(self): + def __initPrefix(self, defines): dest = os.path.join(self.__packageDir, "image", self.__depPrefix) if not os.path.exists(dest): p = CraftPackageObject.get(self.__rootPackage) info = MetaInfo(p) displayName = info.displayName if self.__sdkMode: displayName = f"{displayName} for Qt {CraftCore.settings.get('QtSDK', 'Version')} {CraftCore.settings.get('QtSDK', 'Compiler')}" - return self.__createMeta(dest, displayName, "0.0", info.description, info.webpage) + return self.__createMeta(defines, dstpath=dest, name=displayName, version="0.0", description=info.description, webpage=info.webpage) return True def createPackage(self): - if not self.__initPrefix(): + defines = self.setDefaults(self.defines) + if not self.__initPrefix(defines): return False - return self._addPackage() + return self._addPackage(defines)