[IMP] forwardport: use ORT and zdiff3 for cherrypicks

- zdiff3 should provide better conflict annotations than diff3
- ORT might also provide less conflicts period
- always perform cherrypicks without rename limit, since we're
  re-trying every failure without rename limit, it seems like
  unnecessary work, assuming git only ever looks as far as it needs
- also enable copy support maybe...

Fixes #827
This commit is contained in:
Xavier Morel 2024-06-04 14:18:36 +02:00
parent c1e2e5a2e0
commit cc9f239261
2 changed files with 28 additions and 20 deletions

View File

@ -423,9 +423,13 @@ class PullRequests(models.Model):
# switch back to the PR branch # switch back to the PR branch
conf.checkout(fp_branch_name) conf.checkout(fp_branch_name)
# cherry-pick the squashed commit to generate the conflict # cherry-pick the squashed commit to generate the conflict
conf.with_params('merge.renamelimit=0', 'merge.conflictstyle=diff3')\ conf.with_params(
'merge.renamelimit=0',
'merge.renames=copies',
'merge.conflictstyle=zdiff3'
)\
.with_config(check=False)\ .with_config(check=False)\
.cherry_pick(squashed, no_commit=True) .cherry_pick(squashed, no_commit=True, strategy="ort")
status = conf.stdout().status(short=True, untracked_files='no').stdout.decode() status = conf.stdout().status(short=True, untracked_files='no').stdout.decode()
if err.strip(): if err.strip():
err = err.rstrip() + '\n----------\nstatus:\n' + status err = err.rstrip() + '\n----------\nstatus:\n' + status
@ -459,7 +463,7 @@ stderr:
logger = _logger.getChild(str(self.id)).getChild('cherrypick') logger = _logger.getChild(str(self.id)).getChild('cherrypick')
# original head so we can reset # original head so we can reset
prev = original_head = working_copy.stdout().rev_parse('HEAD').stdout.decode().strip() original_head = working_copy.stdout().rev_parse('HEAD').stdout.decode().strip()
commits = self.commits() commits = self.commits()
logger.info("%s: copy %s commits to %s\n%s", self, len(commits), original_head, '\n'.join( logger.info("%s: copy %s commits to %s\n%s", self, len(commits), original_head, '\n'.join(
@ -467,6 +471,13 @@ stderr:
for c in commits for c in commits
)) ))
conf_base = working_copy.with_params(
'merge.renamelimit=0',
'merge.renames=copies',
).with_config(
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
check=False
)
for commit in commits: for commit in commits:
commit_sha = commit['sha'] commit_sha = commit['sha']
# config (global -c) or commit options don't really give access to # config (global -c) or commit options don't really give access to
@ -481,19 +492,10 @@ stderr:
} }
configured = working_copy.with_config(env=env) configured = working_copy.with_config(env=env)
conf = working_copy.with_config( conf = conf_base.with_config(env={**env, 'GIT_TRACE': 'true'})
env={**env, 'GIT_TRACE': 'true'},
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
check=False
)
# first try with default / low renamelimit # first try with default / low renamelimit
r = conf.cherry_pick(commit_sha) r = conf.cherry_pick(commit_sha, strategy="ort")
logger.debug("Cherry-picked %s: %s\n%s\n%s", commit_sha, r.returncode, r.stdout.decode(), _clean_rename(r.stderr.decode())) logger.debug("Cherry-picked %s: %s\n%s\n%s", commit_sha, r.returncode, r.stdout.decode(), _clean_rename(r.stderr.decode()))
if r.returncode:
# if it failed, retry with high renamelimit
configured.reset('--hard', prev)
r = conf.with_params('merge.renamelimit=0').cherry_pick(commit_sha)
logger.debug("Cherry-picked %s (renamelimit=0): %s\n%s\n%s", commit_sha, r.returncode, r.stdout.decode(), _clean_rename(r.stderr.decode()))
if r.returncode: # pick failed, reset and bail if r.returncode: # pick failed, reset and bail
# try to log inflateInit: out of memory errors as warning, they # try to log inflateInit: out of memory errors as warning, they
@ -516,8 +518,8 @@ stderr:
configured \ configured \
.with_config(input=str(msg).encode())\ .with_config(input=str(msg).encode())\
.commit(amend=True, file='-') .commit(amend=True, file='-')
prev = configured.stdout().rev_parse('HEAD').stdout.decode() result = configured.stdout().rev_parse('HEAD').stdout.decode()
logger.info('%s: success -> %s', commit_sha, prev) logger.info('%s: success -> %s', commit_sha, result)
def _make_fp_message(self, commit): def _make_fp_message(self, commit):
cmap = json.loads(self.commits_map) cmap = json.loads(self.commits_map)

View File

@ -470,10 +470,16 @@ CONFLICT (add/add): Merge conflict in h
stderr: stderr:
``` ```
$$:$$:$$.$$ {pr2_id.head} $$ trace: built-in: git cherry-pick {pr2_id.head} --strategy ort
error: could not apply $$... newfiles error: could not apply {pr2_id.head[:7]}... newfiles
hint: $$ hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config advice.mergeConflict false"
---------- ----------
status: status:
''')) ```'''))
] ]