in lib/ramble/spack/package.py [0:0]
def do_patch(self):
"""Applies patches if they haven't been applied already."""
if not self.spec.concrete:
raise ValueError("Can only patch concrete packages.")
# Kick off the stage first. This creates the stage.
self.do_stage()
# Package can add its own patch function.
has_patch_fun = hasattr(self, 'patch') and callable(self.patch)
# Get the patches from the spec (this is a shortcut for the MV-variant)
patches = self.spec.patches
# If there are no patches, note it.
if not patches and not has_patch_fun:
tty.msg('No patches needed for {0}'.format(self.name))
return
# Construct paths to special files in the archive dir used to
# keep track of whether patches were successfully applied.
archive_dir = self.stage.source_path
good_file = os.path.join(archive_dir, '.spack_patched')
no_patches_file = os.path.join(archive_dir, '.spack_no_patches')
bad_file = os.path.join(archive_dir, '.spack_patch_failed')
# If we encounter an archive that failed to patch, restage it
# so that we can apply all the patches again.
if os.path.isfile(bad_file):
tty.debug('Patching failed last time. Restaging.')
self.stage.restage()
# If this file exists, then we already applied all the patches.
if os.path.isfile(good_file):
tty.msg('Already patched {0}'.format(self.name))
return
elif os.path.isfile(no_patches_file):
tty.msg('No patches needed for {0}'.format(self.name))
return
# Apply all the patches for specs that match this one
patched = False
for patch in patches:
try:
with fsys.working_dir(self.stage.source_path):
patch.apply(self.stage)
tty.msg('Applied patch {0}'.format(patch.path_or_url))
patched = True
except spack.error.SpackError as e:
tty.debug(e)
# Touch bad file if anything goes wrong.
tty.msg('Patch %s failed.' % patch.path_or_url)
fsys.touch(bad_file)
raise
if has_patch_fun:
try:
with fsys.working_dir(self.stage.source_path):
self.patch()
tty.msg('Ran patch() for {0}'.format(self.name))
patched = True
except spack.multimethod.NoSuchMethodError:
# We are running a multimethod without a default case.
# If there's no default it means we don't need to patch.
if not patched:
# if we didn't apply a patch from a patch()
# directive, AND the patch function didn't apply, say
# no patches are needed. Otherwise, we already
# printed a message for each patch.
tty.msg('No patches needed for {0}'.format(self.name))
except spack.error.SpackError as e:
tty.debug(e)
# Touch bad file if anything goes wrong.
tty.msg('patch() function failed for {0}'.format(self.name))
fsys.touch(bad_file)
raise
# Get rid of any old failed file -- patches have either succeeded
# or are not needed. This is mostly defensive -- it's needed
# if the restage() method doesn't clean *everything* (e.g., for a repo)
if os.path.isfile(bad_file):
os.remove(bad_file)
# touch good or no patches file so that we skip next time.
if patched:
fsys.touch(good_file)
else:
fsys.touch(no_patches_file)