diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -1166,6 +1166,45 @@ } +def _extract_copies(actions, branchmerge): + """extract a copy dict (dst->src) from a dict of merge actions""" + copies = {} + # resolve path conflicts + for f, args, msg in actions.get( + mergestatemod.ACTION_PATH_CONFLICT_RESOLVE, [] + ): + (f0, origf0) = args + copies[f] = origf0 + + # merge + for f, args, msg in actions.get(mergestatemod.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( + mergestatemod.ACTION_DIR_RENAME_MOVE_LOCAL, [] + ): + f0, flag = args + if branchmerge: + copies[f] = f0 + + # directory rename, get + for f, args, msg in actions.get( + mergestatemod.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 ): @@ -1848,6 +1887,12 @@ ) wantfiledata = updatedirstate and not branchmerge + copies = {} + # We don't want to record copies when doing `hg update -C` (which is + # what `overwrite` is about) + if not overwrite: + copies = _extract_copies(actions, branchmerge) + stats, getfiledata = applyupdates( repo, actions, wc, p2, overwrite, wantfiledata, labels=labels ) @@ -1855,6 +1900,7 @@ if updatedirstate: with repo.dirstate.parentchange(): repo.setparents(fp1, fp2) + wc = repo[None] mergestatemod.recordupdates( repo, actions, branchmerge, getfiledata ) @@ -1864,6 +1910,9 @@ if not branchmerge: repo.dirstate.setbranch(p2.branch()) + for dst, src in copies.items(): + 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: diff --git a/mercurial/mergestate.py b/mercurial/mergestate.py --- a/mercurial/mergestate.py +++ b/mercurial/mergestate.py @@ -771,7 +771,6 @@ for f, args, msg in actions.get(ACTION_PATH_CONFLICT_RESOLVE, []): (f0, origf0) = args repo.dirstate.add(f) - repo.dirstate.copy(origf0, f) if f0 == origf0: repo.dirstate.remove(f0) else: @@ -814,10 +813,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 @@ -835,16 +830,13 @@ if branchmerge: repo.dirstate.add(f) repo.dirstate.remove(f0) - repo.dirstate.copy(f0, f) else: repo.dirstate.normal(f) repo.dirstate.drop(f0) # directory rename, get for f, args, msg in actions.get(ACTION_LOCAL_DIR_RENAME_GET, []): - f0, flag = args if branchmerge: repo.dirstate.add(f) - repo.dirstate.copy(f0, f) else: repo.dirstate.normal(f)