Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix issues with applying PR patch in --from-pr #3414

Merged
merged 15 commits into from
Aug 18, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions easybuild/framework/easyblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -2029,8 +2029,7 @@ def patch_step(self, beginpath=None):
src = os.path.abspath(weld_paths(beginpath, srcpathsuffix))
self.log.debug("Applying patch %s in path %s", patch, src)

if not apply_patch(patch['path'], src, copy=copy_patch, level=level):
raise EasyBuildError("Applying patch %s failed", patch['name'])
apply_patch(patch['path'], src, copy=copy_patch, level=level)

def prepare_step(self, start_dir=True, load_tc_deps_modules=True):
"""
Expand Down
79 changes: 42 additions & 37 deletions easybuild/tools/filetools.py
Original file line number Diff line number Diff line change
Expand Up @@ -1186,12 +1186,18 @@ def guess_patch_level(patched_files, parent_dir):
return patch_level


def apply_patch(patch_file, dest, fn=None, copy=False, level=None, use_git_am=False):
def apply_patch(patch_file, dest, fn=None, copy=False, level=None, use_git_am=False, use_git=False):
"""
Apply a patch to source code in directory dest
- assume unified diff created with "diff -ru old new"

Raises EasyBuildError on any error and returns True on success
"""

if use_git_am:
_log.deprecated('5.0', "'use_git_am' named argument has been renamed to 'use_git'")
Flamefire marked this conversation as resolved.
Show resolved Hide resolved
use_git = True

if build_option('extended_dry_run'):
# skip checking of files in dry run mode
patch_filename = os.path.basename(patch_file)
Expand All @@ -1218,61 +1224,60 @@ def apply_patch(patch_file, dest, fn=None, copy=False, level=None, use_git_am=Fa
raise EasyBuildError("Can't patch directory %s: no such directory", dest)

# use absolute paths
apatch = os.path.abspath(patch_file)
adest = os.path.abspath(dest)
abs_patch_file = os.path.abspath(patch_file)
abs_dest = os.path.abspath(dest)

# Attempt extracting the patch if it ends in .patch.gz, .patch.bz2, .patch.xz
# split in name + extension
apatch_root, apatch_file = os.path.split(apatch)
apatch_name, apatch_extension = os.path.splitext(apatch_file)
patch_filestem, patch_extension = os.path.splitext(os.path.split(abs_patch_file)[1])
boegel marked this conversation as resolved.
Show resolved Hide resolved
# Supports only bz2, gz and xz. zip can be archives which are not supported.
if apatch_extension in ['.gz', '.bz2', '.xz']:
if patch_extension in ['.gz', '.bz2', '.xz']:
# split again to get the second extension
apatch_subname, apatch_subextension = os.path.splitext(apatch_name)
if apatch_subextension == ".patch":
patch_subextension = os.path.splitext(patch_filestem)[1]
if patch_subextension == ".patch":
workdir = tempfile.mkdtemp(prefix='eb-patch-')
_log.debug("Extracting the patch to: %s", workdir)
# extracting the patch
apatch_dir = extract_file(apatch, workdir, change_into_dir=False)
change_dir(apatch_dir)
apatch = os.path.join(apatch_dir, apatch_name)
extracted_dir = extract_file(abs_patch_file, workdir, change_into_dir=False)
change_dir(extracted_dir)
abs_patch_file = os.path.join(extracted_dir, patch_filestem)

if level is None and build_option('extended_dry_run'):
level = '<derived>'
if use_git:
verbose = '--verbose ' if build_option('debug') else ''
patch_cmd = "git apply %s%s" % (verbose, abs_patch_file)
else:
if level is None and build_option('extended_dry_run'):
level = '<derived>'

elif level is None:
# guess value for -p (patch level)
# - based on +++ lines
# - first +++ line that matches an existing file determines guessed level
# - we will try to match that level from current directory
patched_files = det_patched_files(path=apatch)
elif level is None:
# guess value for -p (patch level)
# - based on +++ lines
# - first +++ line that matches an existing file determines guessed level
# - we will try to match that level from current directory
patched_files = det_patched_files(path=abs_patch_file)

if not patched_files:
raise EasyBuildError("Can't guess patchlevel from patch %s: no testfile line found in patch", apatch)
return
if not patched_files:
raise EasyBuildError("Can't guess patchlevel from patch %s: no testfile line found in patch",
abs_patch_file)

level = guess_patch_level(patched_files, adest)
level = guess_patch_level(patched_files, abs_dest)

if level is None: # level can also be 0 (zero), so don't use "not level"
# no match
raise EasyBuildError("Can't determine patch level for patch %s from directory %s", patch_file, adest)
else:
_log.debug("Guessed patch level %d for patch %s" % (level, patch_file))
if level is None: # level can also be 0 (zero), so don't use "not level"
# no match
raise EasyBuildError("Can't determine patch level for patch %s from directory %s", patch_file, abs_dest)
else:
_log.debug("Guessed patch level %d for patch %s" % (level, patch_file))

else:
_log.debug("Using specified patch level %d for patch %s" % (level, patch_file))
else:
_log.debug("Using specified patch level %d for patch %s" % (level, patch_file))

if use_git_am:
patch_cmd = "git am patch %s" % apatch
else:
patch_cmd = "patch -b -p%s -i %s" % (level, apatch)
patch_cmd = "patch -b -p%s -i %s" % (level, abs_patch_file)

out, ec = run.run_cmd(patch_cmd, simple=False, path=adest, log_ok=False, trace=False)
out, ec = run.run_cmd(patch_cmd, simple=False, path=abs_dest, log_ok=False, trace=False)

if ec:
raise EasyBuildError("Couldn't apply patch file %s. Process exited with code %s: %s", patch_file, ec, out)

return ec == 0
boegel marked this conversation as resolved.
Show resolved Hide resolved
return True


def apply_regex_substitutions(path, regex_subs, backup='.orig.eb'):
Expand Down
2 changes: 1 addition & 1 deletion easybuild/tools/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ def fetch_files_from_pr(pr, path=None, github_user=None, github_repo=None):
elif not pr_closed:
try:
_log.debug("Trying to apply PR patch %s to %s...", diff_filepath, repo_target_branch)
apply_patch(diff_filepath, repo_target_branch, use_git_am=True)
apply_patch(diff_filepath, repo_target_branch, use_git=True)
_log.info("Using %s which included PR patch to test PR #%s", repo_target_branch, pr)
final_path = repo_target_branch

Expand Down