# HG changeset patch # User Thomas Arendsen Hein # Date 1337799016 -7200 # Node ID 98687cdddcb1a562b827f784418d8c331b02a99f # Parent 9cbc44a6600e9427642ee78f9a5b4a243ab9c855 merge: warn about file deleted in one branch and renamed in other (issue3074) For divergent renames the following message is printed during merge: note: possible conflict - file was renamed multiple times to: newfile file2 When a file is renamed in one branch and deleted in the other, the file still exists after a merge. With this change a similar message is printed for mv+rm: note: possible conflict - file was deleted and renamed to: newfile diff -r 9cbc44a6600e -r 98687cdddcb1 mercurial/copies.py --- a/mercurial/copies.py Wed May 23 17:33:19 2012 +0200 +++ b/mercurial/copies.py Wed May 23 20:50:16 2012 +0200 @@ -177,19 +177,22 @@ "diverge" is a mapping of source name -> list of destination names for divergent renames. + + "renamedelete" is a mapping of source name -> list of destination + names for files deleted in c1 that were renamed in c2 or vice-versa. """ # avoid silly behavior for update from empty dir if not c1 or not c2 or c1 == c2: - return {}, {} + return {}, {}, {} # avoid silly behavior for parent -> working dir if c2.node() is None and c1.node() == repo.dirstate.p1(): - return repo.dirstate.copies(), {} + return repo.dirstate.copies(), {}, {} limit = _findlimit(repo, c1.rev(), c2.rev()) if limit is None: # no common ancestor, no copies - return {}, {} + return {}, {}, {} m1 = c1.manifest() m2 = c2.manifest() ma = ca.manifest() @@ -283,10 +286,15 @@ for f in u2: checkcopies(f, m2, m1) + renamedelete = {} diverge2 = set() for of, fl in diverge.items(): if len(fl) == 1 or of in c1 or of in c2: del diverge[of] # not actually divergent, or not a rename + if of not in c1 and of not in c2: + # renamed on one side, deleted on the other side, but filter + # out files that have been renamed and then deleted + renamedelete[of] = [f for f in fl if f in c1 or f in c2] else: diverge2.update(fl) # reverse map for below @@ -302,7 +310,7 @@ del diverge2 if not fullcopy: - return copy, diverge + return copy, diverge, renamedelete repo.ui.debug(" checking for directory renames\n") @@ -337,7 +345,7 @@ del d1, d2, invalid if not dirmove: - return copy, diverge + return copy, diverge, renamedelete for d in dirmove: repo.ui.debug(" dir %s -> %s\n" % (d, dirmove[d])) @@ -354,4 +362,4 @@ repo.ui.debug(" file %s -> %s\n" % (f, copy[f])) break - return copy, diverge + return copy, diverge, renamedelete diff -r 9cbc44a6600e -r 98687cdddcb1 mercurial/merge.py --- a/mercurial/merge.py Wed May 23 17:33:19 2012 +0200 +++ b/mercurial/merge.py Wed May 23 20:50:16 2012 +0200 @@ -198,9 +198,11 @@ elif pa == p2: # backwards pa = p1.p1() elif pa and repo.ui.configbool("merge", "followcopies", True): - copy, diverge = copies.mergecopies(repo, p1, p2, pa) + copy, diverge, renamedelete = copies.mergecopies(repo, p1, p2, pa) for of, fl in diverge.iteritems(): act("divergent renames", "dr", of, fl) + for of, fl in renamedelete.iteritems(): + act("rename and delete", "rd", of, fl) repo.ui.note(_("resolving manifests\n")) repo.ui.debug(" overwrite: %s, partial: %s\n" @@ -409,6 +411,12 @@ "multiple times to:\n") % f) for nf in fl: repo.ui.warn(" %s\n" % nf) + elif m == "rd": # rename and delete + fl = a[2] + repo.ui.warn(_("note: possible conflict - %s was deleted " + "and renamed to:\n") % f) + for nf in fl: + repo.ui.warn(" %s\n" % nf) elif m == "e": # exec flags = a[2] repo.wopener.audit(f) diff -r 9cbc44a6600e -r 98687cdddcb1 tests/test-rename-merge1.t --- a/tests/test-rename-merge1.t Wed May 23 17:33:19 2012 +0200 +++ b/tests/test-rename-merge1.t Wed May 23 20:50:16 2012 +0200 @@ -156,3 +156,26 @@ c2 $ cd .. + +Check for issue3074 + + $ hg init repo3074 + $ cd repo3074 + $ echo foo > file + $ hg add file + $ hg commit -m "added file" + $ hg mv file newfile + $ hg commit -m "renamed file" + $ hg update 0 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg rm file + $ hg commit -m "deleted file" + created new head + $ hg merge + note: possible conflict - file was deleted and renamed to: + newfile + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg status + M newfile + $ cd ..