diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -1845,6 +1845,39 @@ } +def _extract_copies(actions, branchmerge): + """record merge actions to the dirstate""" + copies = {} + # resolve path conflicts + for f, args, msg in actions.get(ACTION_PATH_CONFLICT_RESOLVE, []): + (f0,) = args + copies[f] = f0 + + # merge + for f, args, msg in actions.get(ACTION_MERGE, []): + f1, f2, fa, move, anc = args + if branchmerge: + if f1 != f2: # copy/rename + if f1 != f: + copies[f] = f1 + else: + copies[f] = f2 + + # directory rename, move local + for f, args, msg in actions.get(ACTION_DIR_RENAME_MOVE_LOCAL, []): + f0, flag = args + if branchmerge: + copies[f] = f0 + + # directory rename, get + for f, args, msg in actions.get(ACTION_LOCAL_DIR_RENAME_GET, []): + f0, flag = args + if branchmerge: + copies[f] = f0 + + return copies + + def applyupdates( repo, actions, wctx, mctx, overwrite, wantfiledata, labels=None ): @@ -2155,7 +2188,6 @@ (f0,) = args origf0 = repo.dirstate.copied(f0) or f0 repo.dirstate.add(f) - repo.dirstate.copy(origf0, f) if f0 == origf0: repo.dirstate.remove(f0) else: @@ -2198,10 +2230,6 @@ if f1 != f2: # copy/rename if move: repo.dirstate.remove(f1) - if f1 != f: - repo.dirstate.copy(f1, f) - else: - repo.dirstate.copy(f2, f) else: # We've update-merged a locally modified file, so # we set the dirstate to emulate a normal checkout @@ -2219,7 +2247,6 @@ if branchmerge: repo.dirstate.add(f) repo.dirstate.remove(f0) - repo.dirstate.copy(f0, f) else: repo.dirstate.normal(f) repo.dirstate.drop(f0) @@ -2229,7 +2256,6 @@ f0, flag = args if branchmerge: repo.dirstate.add(f) - repo.dirstate.copy(f0, f) else: repo.dirstate.normal(f) @@ -2602,6 +2628,13 @@ ) wantfiledata = updatedirstate and not branchmerge + resulting_copies = {} + if not overwrite: + existing_copies = wc.p2copies() + existing_copies.update(wc.p1copies()) + new_copies = _extract_copies(actions, branchmerge) + resulting_copies = copies.chain(existing_copies, new_copies) + stats, getfiledata = applyupdates( repo, actions, wc, p2, overwrite, wantfiledata, labels=labels ) @@ -2609,6 +2642,7 @@ if updatedirstate: with repo.dirstate.parentchange(): repo.setparents(fp1, fp2) + wc = repo[None] recordupdates(repo, actions, branchmerge, getfiledata) # update completed, clear state util.unlink(repo.vfs.join(b'updatestate')) @@ -2616,6 +2650,16 @@ if not branchmerge: repo.dirstate.setbranch(p2.branch()) + # This is a version of copies.filter() modified to work with merges + for dst, src in resulting_copies.items(): + if dst == src: + continue + if dst not in wc: + continue + if not (src in wc.p1() or src in wc.p2()): + continue + wc[dst].markcopied(src) + # If we're updating to a location, clean up any stale temporary includes # (ex: this happens during hg rebase --abort). if not branchmerge: