def from_dict(dictionary): """Create a patch from json dictionary.""" owner = dictionary.get('owner') if 'owner' not in dictionary: raise ValueError('Invalid patch dictionary: %s' % dictionary) pkg = spack.repo.get(owner) if 'url' in dictionary: return UrlPatch(pkg, dictionary['url'], dictionary['level'], dictionary['working_dir'], sha256=dictionary['sha256'], archive_sha256=dictionary.get('archive_sha256')) elif 'relative_path' in dictionary: patch = FilePatch(pkg, dictionary['relative_path'], dictionary['level'], dictionary['working_dir']) # If the patch in the repo changes, we cannot get it back, so we # just check it and fail here. # TODO: handle this more gracefully. sha256 = dictionary['sha256'] checker = Checker(sha256) if not checker.check(patch.path): raise fs.ChecksumError( "sha256 checksum failed for %s" % patch.path, "Expected %s but got %s" % (sha256, checker.sum), "Patch may have changed since concretization.") return patch else: raise ValueError("Invalid patch dictionary: %s" % dictionary)
def fetch(self, stage): """Retrieve the patch in a temporary stage and compute self.path Args: stage: stage for the package that needs to be patched """ # use archive digest for compressed archives fetch_digest = self.sha256 if self.archive_sha256: fetch_digest = self.archive_sha256 fetcher = fs.URLFetchStrategy(self.url, fetch_digest, expand=bool(self.archive_sha256)) per_package_ref = os.path.join( self.owner.split('.')[-1], os.path.basename(self.url)) # Reference starting with "spack." is required to avoid cyclic imports mirror_ref = spack.mirror.mirror_archive_paths(fetcher, per_package_ref) self.stage = spack.stage.Stage(fetcher, mirror_paths=mirror_ref) self.stage.create() self.stage.fetch() self.stage.check() root = self.stage.path if self.archive_sha256: self.stage.expand_archive() root = self.stage.source_path files = os.listdir(root) if not files: if self.archive_sha256: raise NoSuchPatchError("Archive was empty: %s" % self.url) else: raise NoSuchPatchError("Patch failed to download: %s" % self.url) self.path = os.path.join(root, files.pop()) if not os.path.isfile(self.path): raise NoSuchPatchError("Archive %s contains no patch file!" % self.url) # for a compressed archive, Need to check the patch sha256 again # and the patch is in a directory, not in the same place if self.archive_sha256 and spack.config.get('config:checksum'): checker = Checker(self.sha256) if not checker.check(self.path): raise fs.ChecksumError( "sha256 checksum failed for %s" % self.path, "Expected %s but got %s" % (self.sha256, checker.sum))
def apply(self, stage): """Retrieve the patch in a temporary stage, computes self.path and calls `super().apply(stage)` Args: stage: stage for the package that needs to be patched """ # use archive digest for compressed archives fetch_digest = self.sha256 if self.archive_sha256: fetch_digest = self.archive_sha256 fetcher = fs.URLFetchStrategy(self.url, fetch_digest) mirror = os.path.join( os.path.dirname(stage.mirror_path), os.path.basename(self.url)) with spack.stage.Stage(fetcher, mirror_path=mirror) as patch_stage: patch_stage.fetch() patch_stage.check() patch_stage.cache_local() root = patch_stage.path if self.archive_sha256: patch_stage.expand_archive() root = patch_stage.source_path files = os.listdir(root) if not files: if self.archive_sha256: raise NoSuchPatchError( "Archive was empty: %s" % self.url) else: raise NoSuchPatchError( "Patch failed to download: %s" % self.url) self.path = os.path.join(root, files.pop()) if not os.path.isfile(self.path): raise NoSuchPatchError( "Archive %s contains no patch file!" % self.url) # for a compressed archive, Need to check the patch sha256 again # and the patch is in a directory, not in the same place if self.archive_sha256: checker = Checker(self.sha256) if not checker.check(self.path): raise fs.ChecksumError( "sha256 checksum failed for %s" % self.path, "Expected %s but got %s" % (self.sha256, checker.sum)) super(UrlPatch, self).apply(stage)
def fetch(self): """Retrieve the patch in a temporary stage and compute self.path Args: stage: stage for the package that needs to be patched """ self.stage.create() self.stage.fetch() self.stage.check() root = self.stage.path if self.archive_sha256: self.stage.expand_archive() root = self.stage.source_path files = os.listdir(root) if not files: if self.archive_sha256: raise NoSuchPatchError( "Archive was empty: %s" % self.url) else: raise NoSuchPatchError( "Patch failed to download: %s" % self.url) self.path = os.path.join(root, files.pop()) if not os.path.isfile(self.path): raise NoSuchPatchError( "Archive %s contains no patch file!" % self.url) # for a compressed archive, Need to check the patch sha256 again # and the patch is in a directory, not in the same place if self.archive_sha256 and spack.config.get('config:checksum'): checker = Checker(self.sha256) if not checker.check(self.path): raise fs.ChecksumError( "sha256 checksum failed for %s" % self.path, "Expected %s but got %s" % (self.sha256, checker.sum))