예제 #1
0
    def checkDigest(self, downloadRetriesLeft=3):
        CraftCore.log.debug("ArchiveSource.checkDigest called")
        filenames = self.localFileNames()

        if self.subinfo.hasTargetDigestUrls():
            CraftCore.log.debug("check digests urls")
            if not CraftHash.checkFilesDigests(self.__downloadDir, filenames):
                CraftCore.log.error("invalid digest file")
                redownload = downloadRetriesLeft and CraftChoicePrompt.promptForChoice(
                    "Do you want to delete the files and redownload them?",
                    [("Yes", True), ("No", False)],
                    default="Yes")
                if redownload:
                    for filename in filenames:
                        CraftCore.log.info(
                            f"Deleting downloaded file: {filename}")
                        utils.deleteFile(
                            os.path.join(self.__downloadDir, filename))
                        for digestAlgorithm, digestFileEnding in CraftHash.HashAlgorithm.fileEndings(
                        ).items():
                            digestFileName = filename + digestFileEnding
                            if os.path.exists(
                                    os.path.join(self.__downloadDir,
                                                 digestFileName)):
                                CraftCore.log.info(
                                    f"Deleting downloaded file: {digestFileName}"
                                )
                                utils.deleteFile(
                                    os.path.join(self.__downloadDir,
                                                 digestFileName))
                    return self.fetch() and self.checkDigest(
                        downloadRetriesLeft - 1)
                return False
        elif self.subinfo.hasTargetDigests():
            CraftCore.log.debug("check digests")
            digests, algorithm = self.subinfo.targetDigest()
            if not CraftHash.checkFilesDigests(self.__downloadDir, filenames,
                                               digests, algorithm):
                CraftCore.log.error("invalid digest file")
                redownload = downloadRetriesLeft and CraftChoicePrompt.promptForChoice(
                    "Do you want to delete the files and redownload them?",
                    [("Yes", True), ("No", False)],
                    default="Yes")
                if redownload:
                    for filename in filenames:
                        CraftCore.log.info(
                            f"Deleting downloaded file: {filename}")
                        utils.deleteFile(
                            os.path.join(self.__downloadDir, filename))
                    return self.fetch() and self.checkDigest(
                        downloadRetriesLeft - 1)
                return False
        else:
            CraftCore.log.debug("print source file digests")
            CraftHash.printFilesDigests(
                self.__downloadDir,
                filenames,
                self.subinfo.buildTarget,
                algorithm=CraftHash.HashAlgorithm.SHA256)
        return True
예제 #2
0
    def checkDigest(self):
        craftDebug.log.debug("ArchiveSource.checkDigest called")
        filenames = self.localFileNames()

        if self.subinfo.hasTargetDigestUrls():
            craftDebug.log.debug("check digests urls")
            if not CraftHash.checkFilesDigests(CraftStandardDirs.downloadDir(),
                                               filenames):
                craftDebug.log.error("invalid digest file")
                return False
        elif self.subinfo.hasTargetDigests():
            craftDebug.log.debug("check digests")
            digests, algorithm = self.subinfo.targetDigest()
            if not CraftHash.checkFilesDigests(CraftStandardDirs.downloadDir(),
                                               filenames, digests, algorithm):
                craftDebug.log.error("invalid digest file")
                return False
        else:
            craftDebug.log.debug("print source file digests")
            CraftHash.printFilesDigests(
                CraftStandardDirs.downloadDir(),
                filenames,
                self.subinfo.buildTarget,
                algorithm=CraftHash.HashAlgorithm.SHA256)
        return True
예제 #3
0
    def createPackage(self):
        """ create a package """
        CraftCore.log.debug("packaging using the MacDMGPackager")

        defines = self.setDefaults(self.defines)
        # TODO: provide an image with dbg files
        if not self.internalCreatePackage(defines):
            return False
        appPath = self.getMacAppPath(defines)
        if not appPath:
            return False
        archive = os.path.normpath(self.archiveDir())

        CraftCore.log.info(f"Packaging {appPath}")

        dmgDest = defines["setupname"]
        if os.path.exists(dmgDest):
            utils.deleteFile(dmgDest)
        appName = defines['appname'] + ".app"
        if not utils.system(["create-dmg", "--volname", os.path.basename(dmgDest),
                                # Add a drop link to /Applications:
                                "--icon", appName, "140", "150", "--app-drop-link", "350", "150",
                                dmgDest, appPath]):
            return False

        if not CodeSign.signMacPackage(dmgDest):
                return False
        CraftHash.createDigestFiles(dmgDest)

        return True
예제 #4
0
    def _createArchive(self,
                       archiveName,
                       sourceDir,
                       destDir,
                       createDigests=True) -> bool:
        archiveName = str((Path(destDir) / archiveName))
        if not utils.compress(archiveName, sourceDir):
            return False

        if createDigests:
            if CraftCore.settings.getboolean(
                    "Packager", "CreateCache") and CraftCore.settings.get(
                        "Packager", "PackageType") == "SevenZipPackager":
                if CraftCore.settings.getboolean("ContinuousIntegration",
                                                 "UpdateRepository", False):
                    manifestUrls = [self.cacheRepositoryUrls()[0]]
                else:
                    CraftCore.log.warning(
                        f"Creating new cache, if you want to extend an existing cache, set \"[ContinuousIntegration]UpdateRepository = True\""
                    )
                    manifestUrls = None
                self._generateManifest(destDir,
                                       archiveName,
                                       manifestLocation=self.cacheLocation(),
                                       manifestUrls=manifestUrls)
            else:
                self._generateManifest(destDir, archiveName)
                CraftHash.createDigestFiles(archiveName)
        return True
예제 #5
0
 def _compress(self, archiveName, sourceDir, destDir):
     utils.deleteFile(archiveName)
     app = CraftCore.cache.findApplication("7za")
     kw = {}
     progressFlags = []
     if CraftCore.cache.checkCommandOutputFor(app, "-bs"):
         progressFlags = ["-bso2", "-bsp1"]
         kw["stderr"] = subprocess.PIPE
     archive = os.path.join(destDir, archiveName)
     if os.path.isfile(archive):
         utils.deleteFile(archive)
     cmd = [app, "a", "-r", archive,
            os.path.join(sourceDir, "*")] + progressFlags
     if not utils.system(cmd, displayProgress=True, **kw):
         CraftCore.log.critical(f"while packaging. cmd: {cmd}")
     if not CraftCore.settings.getboolean("Packager", "CreateCache"):
         self._generateManifest(destDir, archiveName)
         CraftHash.createDigestFiles(archive)
     else:
         if CraftCore.settings.getboolean("ContinuousIntegration",
                                          "UpdateRepository", False):
             manifestUrls = [self.cacheRepositoryUrls()[0]]
         else:
             manifestUrls = None
         self._generateManifest(destDir,
                                archiveName,
                                manifestLocation=self.cacheLocation(),
                                manifestUrls=manifestUrls)
예제 #6
0
    def _compress(self,
                  archiveName,
                  sourceDir,
                  destDir,
                  createDigests=True) -> bool:
        archive = os.path.join(destDir, archiveName)
        utils.createDir(os.path.dirname(archive))
        if os.path.isfile(archive):
            utils.deleteFile(archive)
        if OsUtils.isUnix():
            if not self.__xz(archive, sourceDir):
                return False
        else:
            if not self.__7z(archive, sourceDir):
                return False

        if createDigests:
            if not CraftCore.settings.getboolean("Packager", "CreateCache"):
                self._generateManifest(destDir, archiveName)
                CraftHash.createDigestFiles(archive)
            else:
                if CraftCore.settings.getboolean("ContinuousIntegration",
                                                 "UpdateRepository", False):
                    manifestUrls = [self.cacheRepositoryUrls()[0]]
                else:
                    manifestUrls = None
                self._generateManifest(destDir,
                                       archiveName,
                                       manifestLocation=self.cacheLocation(),
                                       manifestUrls=manifestUrls)
        return True
예제 #7
0
    def _createArchive(self,
                       archiveName,
                       sourceDir,
                       destDir,
                       createDigests=True,
                       extention=None) -> bool:
        if extention is None:
            extention = "." + CraftCore.settings.get("Packager",
                                                     "7ZipArchiveType", "7z")
            if extention == ".7z" and CraftCore.compiler.isUnix:
                if self.package.path == "dev-utils/7zip" or not CraftCore.cache.findApplication(
                        "7za"):
                    extention = ".tar.xz"
                else:
                    extention = ".tar.7z"

        archiveName = str((Path(destDir) / archiveName)) + extention
        if not utils.compress(archiveName, sourceDir):
            return False

        if createDigests:
            if not CraftCore.settings.getboolean("Packager", "CreateCache"):
                self._generateManifest(destDir, archiveName)
                CraftHash.createDigestFiles(archiveName)
            else:
                if CraftCore.settings.getboolean("ContinuousIntegration",
                                                 "UpdateRepository", False):
                    manifestUrls = [self.cacheRepositoryUrls()[0]]
                else:
                    manifestUrls = None
                self._generateManifest(destDir,
                                       archiveName,
                                       manifestLocation=self.cacheLocation(),
                                       manifestUrls=manifestUrls)
        return True
예제 #8
0
 def checkDigest(self, downloadRetriesLeft=3):
     CraftCore.log.debug("ArchiveSource.checkDigest called")
     filenames = self.localFileNames()
     if self.subinfo.hasTargetDigestUrls():
         CraftCore.log.debug("check digests urls")
         if not CraftHash.checkFilesDigests(self.__downloadDir, filenames):
             CraftCore.log.error("invalid digest file")
             return self.__retry(downloadRetriesLeft,
                                 self.__redownload,
                                 filenames=filenames)
     elif self.subinfo.hasTargetDigests():
         CraftCore.log.debug("check digests")
         digests, algorithm = self.subinfo.targetDigest()
         if not CraftHash.checkFilesDigests(self.__downloadDir, filenames,
                                            digests, algorithm):
             CraftCore.log.error("invalid digest file")
             return self.__retry(downloadRetriesLeft,
                                 self.__redownload,
                                 filenames=filenames)
     else:
         CraftCore.log.debug("print source file digests")
         CraftHash.printFilesDigests(
             self.__downloadDir,
             filenames,
             self.subinfo.buildTarget,
             algorithm=CraftHash.HashAlgorithm.SHA256)
     return True
예제 #9
0
 def _compress(self, archiveName, sourceDir, destDir):
     utils.deleteFile(archiveName)
     app = utils.utilsCache.findApplication("7za")
     kw = {}
     progressFlags = ""
     if utils.utilsCache.checkCommandOutputFor(app, "-bs"):
         progressFlags = " -bso2 -bsp1"
         kw["stderr"] = subprocess.PIPE
     archive = os.path.join(destDir, archiveName)
     if os.path.isfile(archive):
         utils.deleteFile(archive)
     cmd = f"\"{app}\" a {progressFlags} -r \"{archive}\" \"{sourceDir}/*\""
     if not utils.system(cmd, displayProgress=True, **kw):
         craftDebug.log.critical(f"while packaging. cmd: {cmd}")
     if not craftSettings.getboolean("Packager", "CreateCache"):
         CraftHash.createDigestFiles(archive)
     else:
         cacheFilePath = os.path.join(self.cacheLocation(), "manifest.json")
         if os.path.exists(cacheFilePath):
             with open(cacheFilePath, "rt+") as cacheFile:
                 cache = json.load(cacheFile)
         else:
             cache = {}
         if not str(self) in cache:
             cache[str(self)] = {}
         cache[str(self)][archiveName] = {
             "checksum":
             CraftHash.digestFile(archive, CraftHash.HashAlgorithm.SHA256)
         }
         with open(cacheFilePath, "wt+") as cacheFile:
             json.dump(cache, cacheFile, sort_keys=True, indent=2)
예제 #10
0
 def test_printFilesDigests(self):
     path, name = os.path.split(self.tmpFile)
     log = io.StringIO()
     oldLog = CraftCore.debug._handler.stream
     CraftCore.debug._handler.stream = log
     CraftHash.printFilesDigests(path, [name], "test", CraftHash.HashAlgorithm.SHA256)
     self.assertEquals(
         "Digests for test: (['4fc1e96dc5ecf625efe228fce1b0964b6302cfa4d4fb2bb8d16c665d23f6ff30'], CraftHash.HashAlgorithm.SHA256)\n", log.getvalue())
     CraftCore.debug._handler.stream = oldLog
예제 #11
0
    def createPackage(self):
        """ create a package """
        if not self.isNsisInstalled():
            return False

        craftDebug.log.debug("packaging using the NullsoftInstallerPackager")

        self.internalCreatePackage()
        self.preArchive()
        self.generateNSISInstaller()
        CraftHash.createDigestFiles(self.defines["setupname"])
        return True
예제 #12
0
    def createPackage(self):
        """ create a package """
        CraftCore.log.debug("packaging using the MacDMGPackager")

        self.internalCreatePackage()
        self.preArchive()

        self._setDefaults()

        archive = self.archiveDir()
        appPath = os.path.join(archive, self.defines['apppath'],
                               f"{self.defines['appname']}.app")
        if os.path.exists(os.path.join(archive, "lib/plugins")):
            utils.mergeTree(os.path.join(archive, "lib/plugins"),
                            os.path.join(appPath, "Contents/PlugIns/"))
        targetLibdir = os.path.join(appPath, "Contents/Frameworks/")
        if not os.path.exists(targetLibdir):
            os.makedirs(targetLibdir)
        if os.path.exists(os.path.join(archive, "lib")):
            utils.mergeTree(os.path.join(archive, "lib"), targetLibdir)
        if os.path.exists(os.path.join(archive, "share")):
            utils.mergeTree(os.path.join(archive, "share"),
                            os.path.join(appPath, "Contents/Resources/"))
        utils.mergeTree(os.path.join(archive, "bin"),
                        os.path.join(appPath, "Contents/MacOS/"))

        env = os.environ
        env['DYLD_LIBRARY_PATH'] = os.path.join(CraftStandardDirs.craftRoot(),
                                                "lib")
        if not utils.systemWithoutShell([
                "dylibbundler", "-of", "-b", "-p",
                "@executable_path/../Frameworks", "-d", targetLibdir, "-x",
                f"{appPath}/Contents/MacOS/{self.defines['appname']}"
        ],
                                        env=env):
            CraftCore.log.warning("Failed to run dylibbundler")

        if not utils.systemWithoutShell([
                "macdeployqt", appPath, "-always-overwrite", "-dmg",
                "-verbose=2"
        ],
                                        env=env):
            CraftCore.log.warning("Failed to run macdeployqt!")

        dmgSrc = appPath.replace(".app", ".dmg")
        dmgDest = os.path.join(self.packageDestinationDir(),
                               os.path.basename(dmgSrc))
        utils.copyFile(dmgSrc, dmgDest, linkOnly=False)
        CraftHash.createDigestFiles(dmgDest)

        return True
    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
예제 #14
0
    def fetchBinary(self) -> bool:
        if self.subinfo.options.package.disableBinaryCache:
            return False

        archiveName = self.binaryArchiveName(includePackagePath=True)
        archvieFolder, localArchiveName = self.binaryArchiveName(includePackagePath=True).rsplit("/", 1)
        downloadFolder = os.path.join(self.cacheLocation(), archvieFolder)
        print(downloadFolder)

        if not os.path.exists(downloadFolder):
            os.makedirs(downloadFolder)

        for url in [self.cacheLocation()] + self.cacheRepositoryUrls():
            craftDebug.log.debug(f"Trying to restore {archiveName} from cache: {url}.")
            cache = utils.utilsCache.cacheJsonFromUrl(f"{url}/manifest.json")
            if not cache or not str(self) in cache or not archiveName in cache[str(self)]:
                continue
            if url != self.cacheLocation():
                if not os.path.exists(os.path.join(downloadFolder, localArchiveName)):
                    if not utils.getFile(f"{url}/{archiveName}", downloadFolder, localArchiveName):
                        return False
            return CraftHash.checkFilesDigests(downloadFolder, [localArchiveName],
                                               digests=cache[str(self)][archiveName]["checksum"],
                                               digestAlgorithm=CraftHash.HashAlgorithm.SHA256) and \
                   self.cleanImage() \
                   and utils.unpackFile(downloadFolder, localArchiveName, self.imageDir()) \
                   and self.qmerge()
        return False
예제 #15
0
    def fetchBinary(self) -> bool:
        if self.subinfo.options.package.disableBinaryCache:
            return False

        for url in [self.cacheLocation()] + self.cacheRepositoryUrls():
            CraftCore.log.debug(f"Trying to restore {self} from cache: {url}.")
            if url == self.cacheLocation():
                fileUrl = f"{url}/manifest.json"
                if os.path.exists(fileUrl):
                    with open(fileUrl, "rt", encoding="UTF-8") as f:
                        manifest = CraftManifest.fromJson(json.load(f))
                else:
                  continue
            else:
                manifest = CraftManifest.fromJson(CraftCore.cache.cacheJsonFromUrl(f"{url}/manifest.json"))
            fileEntry = manifest.get(str(self)).files
            files = []
            for f in fileEntry:
                if f.version == self.version:
                    files.append(f)
            latest = None
            if not files:
                CraftCore.log.debug(f"Could not find {self}={self.version} in {url}")
                continue
            latest = files[0]

            if url != self.cacheLocation():
                downloadFolder = self.cacheLocation(os.path.join(CraftCore.standardDirs.downloadDir(), "cache"))
            else:
                downloadFolder = self.cacheLocation()
            localArchiveAbsPath = OsUtils.toNativePath(os.path.join(downloadFolder, latest.fileName))
            localArchivePath, localArchiveName = os.path.split(localArchiveAbsPath)


            if url != self.cacheLocation():
                if not os.path.exists(localArchiveAbsPath):
                    os.makedirs(localArchivePath, exist_ok=True)
                    fUrl = f"{url}/{latest.fileName}"
                    if not utils.getFile(fUrl, localArchivePath, localArchiveName):
                        CraftCore.log.warning(f"Failed to fetch {fUrl}")
                        return False
            elif not os.path.isfile(localArchiveAbsPath):
                continue

            if not CraftHash.checkFilesDigests(localArchivePath, [localArchiveName],
                                               digests=latest.checksum,
                                               digestAlgorithm=CraftHash.HashAlgorithm.SHA256):
                CraftCore.log.warning(f"Hash did not match, {localArchiveName} might be corrupted")
                return False
            self.subinfo.buildPrefix = latest.buildPrefix
            if not (self.cleanImage()
                    and utils.unpackFile(localArchivePath, localArchiveName, self.imageDir())
                    and self.internalPostInstall()
                    and self.postInstall()
                    and self.qmerge()
                    and self.internalPostQmerge()
                    and self.postQmerge()):
                return False
            return True
        return False
예제 #16
0
    def createPackage(self):
        """ create a package """
        if not self.isNsisInstalled():
            return False

        CraftCore.log.debug("packaging using the NullsoftInstallerPackager")

        if CraftCore.compiler.isMSVC():
            # we use the redist installer
            self.ignoredPackages.append("libs/runtime")
        self.internalCreatePackage()
        self.generateNSISInstaller()
        destDir, archiveName = os.path.split(self.defines["setupname"])
        self._generateManifest(destDir, archiveName)
        CraftHash.createDigestFiles(self.defines["setupname"])
        return True
예제 #17
0
    def unmergeFileList(rootdir, fileList):
        """ delete files in the fileList if has matches """
        for filename, filehash in fileList:
            fullPath = os.path.join(rootdir, os.path.normcase(filename))
            if os.path.isfile(fullPath) or os.path.islink(fullPath):
                if filehash:
                    algorithm = CraftHash.HashAlgorithm.getAlgorithmFromPrefix(
                        filehash)
                    currentHash = algorithm.stringPrefix(
                    ) + CraftHash.digestFile(fullPath, algorithm)
                if not filehash or currentHash == filehash:
                    OsUtils.rm(fullPath, True)
                else:
                    CraftCore.log.warning(
                        f"We can't remove {fullPath} as its hash has changed,"
                        f" that usually implies that the file was modified or replaced"
                    )
            elif not os.path.isdir(fullPath) and os.path.lexists(fullPath):
                CraftCore.log.debug(f"Remove a dead symlink {fullPath}")
                OsUtils.rm(fullPath, True)
            elif not os.path.isdir(fullPath):
                CraftCore.log.warning("file %s does not exist" % fullPath)

            containingDir = os.path.dirname(fullPath)
            if os.path.exists(containingDir) and not os.listdir(containingDir):
                CraftCore.log.debug(f"Delete empty dir {containingDir}")
                utils.rmtree(containingDir)
예제 #18
0
    def createPackage(self):
        """ create a package """
        CraftCore.log.debug("packaging using the MacDMGPackager")
        if not CraftCore.cache.findApplication("packagesutil"):
            CraftCore.log.critical(
                "Craft requires dev-utils/packagesdev to create a package, please install dev-utils/packagesdev\n"
                "\t'craft dev-utils/packagesdev'")
            return False

        defines = self.setDefaults(self.defines)
        if not "pkgproj" in defines:
            CraftCore.log.error(
                "Cannot not create .pkg because no .pkgproj was defined.")
            return False
        if not self.internalCreatePackage(
                defines, seperateSymbolFiles=True, packageSymbols=True):
            return False

        packageDest = Path(defines["setupname"])
        if packageDest.exists():
            utils.deleteFile(packageDest)

        pkgprojPath = defines["pkgproj"]
        # set output file basename
        packagesutil = CraftCore.cache.findApplication("packagesutil")
        if not utils.system([
                packagesutil, '--file', pkgprojPath, 'set', 'project', 'name',
                packageDest.stem
        ]):
            return False

        packagesbuild = CraftCore.cache.findApplication("packagesbuild")
        if not utils.system([
                packagesbuild, "-v", '--reference-folder',
                os.path.dirname(self.getMacAppPath(defines)), '--build-folder',
                packageDest.parent, pkgprojPath
        ]):
            return False

        if not CodeSign.signMacPackage(packageDest):
            return False

        CraftHash.createDigestFiles(packageDest)

        return True
예제 #19
0
 def unmergeFileList(rootdir, fileList):
     """ delete files in the fileList if has matches """
     for filename, filehash in fileList:
         fullPath = os.path.join(rootdir, os.path.normcase(filename))
         if os.path.isfile(fullPath):
             algorithm = CraftHash.HashAlgorithm.getAlgorithmFromPrefix(filehash)
             if not algorithm:
                 currentHash = CraftHash.digestFile(fullPath, CraftHash.HashAlgorithm.MD5)
             else:
                 currentHash = algorithm.stringPrefix() + CraftHash.digestFile(fullPath, algorithm)
             if currentHash == filehash or filehash == "":
                 OsUtils.rm(fullPath, True)
             else:
                 craftDebug.log.warning(
                     f"We can't remove {fullPath} as its hash has changed,"
                     f" that usually implies that the fiel was modified or replaced")
         elif not os.path.isdir(fullPath):
             craftDebug.log.warning("file %s does not exist" % fullPath)
예제 #20
0
    def createPackage(self):
        """ create a package """
        if not self.isInnoInstalled():
            return False

        CraftCore.log.debug("packaging using the InnoSetupPackager")

        defines = self.setDefaults(self.defines)

        if not self.internalCreatePackage(defines, True):
            return False
        if not self.generateInnoInstaller(defines):
            return False

        destDir, archiveName = os.path.split(defines["setupname"])
        self._generateManifest(destDir, archiveName)
        CraftHash.createDigestFiles(defines["setupname"])
        return True
예제 #21
0
    def getFileListFromDirectory(imagedir, filePaths):
        """ create a file list containing hashes """
        ret = []

        algorithm = CraftHash.HashAlgorithm.SHA256
        for filePath in filePaths:
            relativeFilePath = os.path.relpath(filePath, imagedir)
            digest = algorithm.stringPrefix() + CraftHash.digestFile(filePath, algorithm)
            ret.append((relativeFilePath, digest))
        return ret
예제 #22
0
    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)
예제 #23
0
 def __fetchFromArchiveCache(self, downloadRetriesLeft : int=3):
     for url, files in self._getFileInfoFromArchiveCache():
         self.__downloadDir.mkdir(parents=True, exist_ok=True)
         for entry in files:
             if entry.version != self.buildTarget:
                 continue
             if not GetFiles.getFile(utils.urljoin(url, entry.fileName), self.__archiveDir, entry.fileName):
                 self.__retry(downloadRetriesLeft, self.__fetchFromArchiveCache)
             if not CraftHash.checkFilesDigests(self.__archiveDir, [entry.fileName],
                                 digests=entry.checksum,
                                 digestAlgorithm=CraftHash.HashAlgorithm.SHA256):
                 return self.__retry(downloadRetriesLeft,
                     lambda downloadRetriesLeft: utils.deleteFile(self.__archiveDir / entry.fileName) and self.__fetchFromArchiveCache(downloadRetriesLeft))
         if self.__checkFilesPresent(self.localFileNames()):
             return True
     return False
예제 #24
0
    def generateSrcManifest(self) -> bool:
        archiveNames = self.localFileNames()
        if self.subinfo.hasTargetDigestUrls():
            url, alg = self.subinfo.targetDigestUrl()
            archiveNames.append(self.subinfo.archiveName()[0] + CraftHash.HashAlgorithm.fileEndings().get(alg))
        manifestLocation = os.path.join(self.__archiveDir, "manifest.json")
        manifest = CraftManifest.load(manifestLocation, urls=CraftCore.settings.getList("Packager", "ArchiveRepositoryUrl"))
        entry = manifest.get(str(self), compiler="all")
        entry.files.clear()

        for archiveName in archiveNames:
            name = (Path(self.package.path) / archiveName).as_posix()
            archiveFile = self.__downloadDir / archiveName
            if not archiveFile.is_file():
                continue
            digests = CraftHash.digestFile(archiveFile, CraftHash.HashAlgorithm.SHA256)

            entry.addFile(name, digests, version=self.version)
        manifest.dump(manifestLocation)
        return True
예제 #25
0
 def hashTest(self, hash, algorithm):
     path, name = os.path.split(self.tmpFile)
     self.assertEquals(CraftHash.checkFilesDigests(path, [name], hash, algorithm), True)
예제 #26
0
    def createPackage(self):
        """ create a package """
        CraftCore.log.debug("packaging using the MacDMGPackager")

        if not self.internalCreatePackage():
            return False

        self._setDefaults()

        archive = os.path.normpath(self.archiveDir())
        appPath = self.defines['apppath']
        if not appPath:
            apps = glob.glob(os.path.join(archive,
                                          f"**/{self.defines['appname']}.app"),
                             recursive=True)
            if len(apps) != 1:
                CraftCore.log.error(
                    f"Failed to detect {self.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(archive, appPath)
        appPath = os.path.normpath(appPath)
        CraftCore.log.info(f"Packaging {appPath}")

        targetLibdir = os.path.join(appPath, "Contents", "Frameworks")
        utils.createDir(targetLibdir)

        moveTargets = [(os.path.join(archive, "lib", "plugins"),
                        os.path.join(appPath, "Contents", "PlugIns")),
                       (os.path.join(archive, "plugins"),
                        os.path.join(appPath, "Contents", "PlugIns")),
                       (os.path.join(archive, "lib"), targetLibdir),
                       (os.path.join(archive, "share"),
                        os.path.join(appPath, "Contents", "Resources"))]

        if not appPath.startswith(archive):
            moveTargets += [(os.path.join(archive, "bin"),
                             os.path.join(appPath, "Contents", "MacOS"))]

        for src, dest in moveTargets:
            if os.path.exists(src):
                if not utils.mergeTree(src, dest):
                    return False

        dylibbundler = MacDylibBundler(appPath)
        with utils.ScopedEnv({
                'DYLD_FALLBACK_LIBRARY_PATH':
                targetLibdir + ":" +
                os.path.join(CraftStandardDirs.craftRoot(), "lib")
        }):
            CraftCore.log.info("Bundling main binary dependencies...")
            mainBinary = Path(appPath, "Contents", "MacOS",
                              self.defines['appname'])
            if not dylibbundler.bundleLibraryDependencies(mainBinary):
                return False

            # Fix up the library dependencies of files in Contents/Frameworks/
            CraftCore.log.info("Bundling library dependencies...")
            if not dylibbundler.fixupAndBundleLibsRecursively(
                    "Contents/Frameworks"):
                return False
            CraftCore.log.info("Bundling plugin dependencies...")
            if not dylibbundler.fixupAndBundleLibsRecursively(
                    "Contents/PlugIns"):
                return False

            if not utils.system(
                ["macdeployqt", appPath, "-always-overwrite", "-verbose=1"]):
                return False

            # macdeployqt might just have added some explicitly blacklisted files
            blackList = Path(self.packageDir(), "mac_blacklist.txt")
            if blackList.exists():
                blackList = [self.read_blacklist(str(blackList))]
                # use it as whitelist as we want only matches, ignore all others
                matches = utils.filterDirectoryContent(
                    appPath,
                    whitelist=lambda x, root: self.blacklisted(x, blackList),
                    blacklist=lambda x, root: True)
                for f in matches:
                    CraftCore.log.info(f"Remove blacklisted file: {f}")
                    utils.deleteFile(f)

            # macdeployqt adds some more plugins so we fix the plugins after calling macdeployqt
            dylibbundler.checkedLibs = set(
            )  # ensure we check all libs again (but
            # we should not need to make any changes)
            CraftCore.log.info(
                "Fixing plugin dependencies after macdeployqt...")
            if not dylibbundler.fixupAndBundleLibsRecursively(
                    "Contents/PlugIns"):
                return False
            CraftCore.log.info(
                "Fixing library dependencies after macdeployqt...")
            if not dylibbundler.fixupAndBundleLibsRecursively(
                    "Contents/Frameworks"):
                return False

            # Finally sanity check that we don't depend on absolute paths from the builder
            CraftCore.log.info(
                "Checking for absolute library paths in package...")
            found_bad_dylib = False  # Don't exit immeditately so that we log all the bad libraries before failing:
            if not dylibbundler.areLibraryDepsOkay(mainBinary):
                found_bad_dylib = True
                CraftCore.log.error(
                    "Found bad library dependency in main binary %s",
                    mainBinary)
            if not dylibbundler.checkLibraryDepsRecursively(
                    "Contents/Frameworks"):
                CraftCore.log.error(
                    "Found bad library dependency in bundled libraries")
                found_bad_dylib = True
            if not dylibbundler.checkLibraryDepsRecursively(
                    "Contents/PlugIns"):
                CraftCore.log.error(
                    "Found bad library dependency in bundled plugins")
                found_bad_dylib = True
            if found_bad_dylib:
                CraftCore.log.error(
                    "Cannot not create .dmg since the .app contains a bad library depenency!"
                )
                return False

            name = self.binaryArchiveName(fileType="", includeRevision=True)
            dmgDest = os.path.join(self.packageDestinationDir(), f"{name}.dmg")
            if os.path.exists(dmgDest):
                utils.deleteFile(dmgDest)
            appName = self.defines['appname'] + ".app"
            if not utils.system([
                    "create-dmg",
                    "--volname",
                    name,
                    # Add a drop link to /Applications:
                    "--icon",
                    appName,
                    "140",
                    "150",
                    "--app-drop-link",
                    "350",
                    "150",
                    dmgDest,
                    appPath
            ]):
                return False

            CraftHash.createDigestFiles(dmgDest)

            return True
예제 #27
0
    def fetchBinary(self, downloadRetriesLeft=3) -> bool:
        if self.subinfo.options.package.disableBinaryCache:
            return False
        for url in [self.cacheLocation()] + self.cacheRepositoryUrls():
            CraftCore.log.debug(f"Trying to restore {self} from cache: {url}.")
            if url == self.cacheLocation():
                fileUrl = f"{url}/manifest.json"
                if os.path.exists(fileUrl):
                    with open(fileUrl, "rt", encoding="UTF-8") as f:
                        manifest = CraftManifest.fromJson(json.load(f))
                else:
                    continue
            else:
                manifest = CraftManifest.fromJson(
                    CraftCore.cache.cacheJsonFromUrl(f"{url}/manifest.json"))
            fileEntry = manifest.get(str(self)).files
            files = []
            for f in fileEntry:
                if f.version == self.version:
                    files.append(f)
            if not files:
                CraftCore.log.info(
                    f"Could not find {self}={self.version} in {url}")
                continue
            latest = files[0]

            if not self.subinfo.options.dynamic.compatible(
                    latest.config, latest.configHash):
                CraftCore.log.info(
                    "Failed to restore package, configuration missmatch")
                CraftCore.debug.debug_line()
                CraftCore.log.info("Cached config: {}".format(", ".join(
                    f"{k}={v}" for k, v in latest.config.items())))
                CraftCore.log.info(
                    f"Local config:  {self.subinfo.options.dynamic}")
                CraftCore.debug.debug_line()
                # try next cache
                continue

            # if we are creating the cache, a rebuild on a failed fetch would be suboptimal
            createingCache = CraftCore.settings.getboolean(
                "Packager", "CreateCache", False)

            if url != self.cacheLocation():
                downloadFolder = self.cacheLocation(
                    os.path.join(CraftCore.standardDirs.downloadDir(),
                                 "cache"))
            else:
                downloadFolder = self.cacheLocation()
            localArchiveAbsPath = OsUtils.toNativePath(
                os.path.join(downloadFolder, latest.fileName))
            localArchivePath, localArchiveName = os.path.split(
                localArchiveAbsPath)

            if url != self.cacheLocation():
                if not os.path.exists(localArchiveAbsPath):
                    os.makedirs(localArchivePath, exist_ok=True)
                    fileName = latest.fileName
                    if CraftCore.compiler.isWindows:
                        fileName = fileName.replace("\\", "/")
                    fUrl = f"{url}/{fileName}"
                    # try it up to 3 times
                    retries = 3
                    while True:
                        if GetFiles.getFile(fUrl, localArchivePath,
                                            localArchiveName):
                            break
                        msg = f"Failed to fetch {fUrl}"
                        retries -= 1
                        if not retries:
                            if createingCache:
                                raise BlueprintException(msg, self.package)
                            else:
                                CraftCore.log.warning(msg)
                            return False
            elif not os.path.isfile(localArchiveAbsPath):
                continue

            if not CraftHash.checkFilesDigests(
                    localArchivePath, [localArchiveName],
                    digests=latest.checksum,
                    digestAlgorithm=CraftHash.HashAlgorithm.SHA256):
                msg = f"Hash did not match, {localArchiveName} might be corrupted"
                CraftCore.log.warning(msg)
                if downloadRetriesLeft and CraftChoicePrompt.promptForChoice(
                        "Do you want to delete the files and redownload them?",
                    [("Yes", True), ("No", False)],
                        default="Yes"):
                    return utils.deleteFile(
                        localArchiveAbsPath) and self.fetchBinary(
                            downloadRetriesLeft=downloadRetriesLeft - 1)
                if createingCache:
                    raise BlueprintException(msg, self.package)
                return False
            self.subinfo.buildPrefix = latest.buildPrefix
            self.subinfo.isCachedBuild = True
            if not (self.cleanImage() and utils.unpackFile(
                    localArchivePath, localArchiveName, self.imageDir())
                    and self.internalPostInstall() and self.postInstall()
                    and self.qmerge() and self.internalPostQmerge()
                    and self.postQmerge()):
                return False
            return True
        return False
예제 #28
0
    def createPackage(self):
        """ create a package """
        CraftCore.log.debug("packaging using the MacDMGPackager")

        if not self.internalCreatePackage():
          return False

        self._setDefaults()


        archive = os.path.normpath(self.archiveDir())
        appPath = self.defines['apppath']
        if not appPath:
            apps = glob.glob(os.path.join(archive, f"**/{self.defines['appname']}.app"), recursive=True)
            if len(apps) != 1:
                CraftCore.log.error(f"Failed to detect {self.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(archive, appPath)
        appPath = os.path.normpath(appPath)
        CraftCore.log.info(f"Packaging {appPath}")

        targetLibdir = os.path.join(appPath, "Contents", "Frameworks")
        utils.createDir(targetLibdir)

        moveTargets = [
            (os.path.join(archive, "lib", "plugins"), os.path.join(appPath, "Contents", "PlugIns")),
            (os.path.join(archive, "plugins"), os.path.join(appPath, "Contents", "PlugIns")),
            (os.path.join(archive, "lib"), targetLibdir),
            (os.path.join(archive, "share"), os.path.join(appPath, "Contents", "Resources"))]

        if not appPath.startswith(archive):
            moveTargets += [(os.path.join(archive, "bin"), os.path.join(appPath, "Contents", "MacOS"))]

        for src, dest in moveTargets:
            if os.path.exists(src):
                if not utils.mergeTree(src, dest):
                    return False

        with utils.ScopedEnv({'DYLD_FALLBACK_LIBRARY_PATH' : os.path.join(CraftStandardDirs.craftRoot(), "lib")}):
            if not utils.system(["dylibbundler",
                                            "--overwrite-files",
                                            "--bundle-deps",
                                            "--install-path", "@executable_path/../Frameworks",
                                            "--dest-dir", targetLibdir,
                                            "--fix-file", os.path.join(appPath, "Contents", "MacOS", self.defines['appname'])]):
                return False

            if not utils.system(["macdeployqt", appPath,  "-always-overwrite", "-verbose=1"]):
                return False

            name = self.binaryArchiveName(fileType="", includeRevision=True)
            dmgDest = os.path.join(self.packageDestinationDir(), f"{name}.dmg")
            if os.path.exists(dmgDest):
                utils.deleteFile(dmgDest)
            if not utils.system(["create-dmg", "--volname", name, dmgDest, appPath]):
                return False

            CraftHash.createDigestFiles(dmgDest)

            return True
예제 #29
0
 def test_createDigestFiles(self):
     # TODO: check file content
     algorithms = CraftHash.HashAlgorithm.__members__.values()
     CraftHash.createDigestFiles(self.tmpFile, algorithms=algorithms)
     for algorithm in algorithms:
         self.assertEquals(os.path.exists(self.tmpFile + algorithm.fileEnding()), True)