# HG changeset patch # User Matt Mackall # Date 1182466923 18000 # Node ID 723e0ddb6ada4087e467125b40637191617ec8b3 # Parent d8442fc0da8dd45becf49a1915f014c4e6df2881 merge: warn user about divergent renames diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -155,11 +155,15 @@ def findcopies(repo, m1, m2, ma, limit): copy = {} fullcopy = {} + diverge = {} def checkcopies(c, man): '''check possible copies for filectx c''' for of in findold(c): + fullcopy[c.path()] = of # remember for dir rename detection if of not in man: # original file not in other manifest? + if of in ma: + diverge.setdefault(of, []).append(c.path()) continue c2 = ctx(of, man[of]) ca = c.ancestor(c2) @@ -167,17 +171,16 @@ def findcopies(repo, m1, m2, ma, limit): continue # named changed on only one side? if ca.path() == c.path() or ca.path() == c2.path(): - fullcopy[c.path()] = of # remember for dir rename detection if c == ca or c2 == ca: # no merge needed, ignore copy continue copy[c.path()] = of if not repo.ui.configbool("merge", "followcopies", True): - return {} + return {}, {} # avoid silly behavior for update from empty dir if not m1 or not m2 or not ma: - return {} + return {}, {} u1 = nonoverlap(m1, m2, ma) u2 = nonoverlap(m2, m1, ma) @@ -188,8 +191,16 @@ def findcopies(repo, m1, m2, ma, limit): for f in u2: checkcopies(ctx(f, m2[f]), m1) + d2 = {} + for of, fl in diverge.items(): + for f in fl: + fo = list(fl) + fo.remove(f) + d2[f] = (of, fo) + #diverge = d2 + if not fullcopy or not repo.ui.configbool("merge", "followdirs", True): - return copy + return copy, diverge # generate a directory move map d1, d2 = dirs(m1), dirs(m2) @@ -223,7 +234,7 @@ def findcopies(repo, m1, m2, ma, limit): del d1, d2, invalid if not dirmove: - return copy + return copy, diverge # check unaccounted nonoverlapping files against directory moves for f in u1 + u2: @@ -234,7 +245,7 @@ def findcopies(repo, m1, m2, ma, limit): copy[f] = dirmove[d] + f[len(d):] break - return copy + return copy, diverge def manifestmerge(repo, p1, p2, pa, overwrite, partial): """ @@ -254,6 +265,7 @@ def manifestmerge(repo, p1, p2, pa, over backwards = (pa == p2) action = [] copy = {} + diverge = {} def fmerge(f, f2=None, fa=None): """merge flags""" @@ -273,7 +285,11 @@ def manifestmerge(repo, p1, p2, pa, over action.append((f, m) + args) if not (backwards or overwrite): - copy = findcopies(repo, m1, m2, ma, pa.rev()) + copy, diverge = findcopies(repo, m1, m2, ma, pa.rev()) + + for of, fl in diverge.items(): + act("divergent renames", "dr", of, fl) + copied = dict.fromkeys(copy.values()) # Compare manifests @@ -410,6 +426,11 @@ def applyupdates(repo, action, wctx, mct t = mctx.filectx(f2).data() repo.wwrite(fd, t, flags) updated += 1 + elif m == "dr": # divergent renames + fl = a[2] + repo.ui.warn("warning: detected divergent renames of %s to:\n" % f) + for nf in fl: + repo.ui.warn(" %s\n" % nf) elif m == "e": # exec flags = a[2] util.set_exec(repo.wjoin(f), flags) diff --git a/tests/test-bundle-r.out b/tests/test-bundle-r.out --- a/tests/test-bundle-r.out +++ b/tests/test-bundle-r.out @@ -197,6 +197,9 @@ checking manifests crosschecking files in changesets and manifests checking files 3 files, 7 changesets, 6 total revisions +warning: detected divergent renames of afile to: + anotherfile + adifferentfile 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) 1 files updated, 0 files merged, 0 files removed, 0 files unresolved diff --git a/tests/test-rename-merge1.out b/tests/test-rename-merge1.out --- a/tests/test-rename-merge1.out +++ b/tests/test-rename-merge1.out @@ -4,12 +4,16 @@ merge resolving manifests overwrite None partial False ancestor af1939970a1c local f26ec4fc3fa3+ remote 8e765a822af2 + a2: divergent renames -> dr a: remote moved to b -> m b2: remote created -> g merging a and b my a@f26ec4fc3fa3+ other b@8e765a822af2 ancestor a@af1939970a1c copying a to b removing a +warning: detected divergent renames of a2 to: + c2 + b2 getting b2 1 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) diff --git a/tests/test-rename-merge2.out b/tests/test-rename-merge2.out --- a/tests/test-rename-merge2.out +++ b/tests/test-rename-merge2.out @@ -173,8 +173,12 @@ test L:nm a b R:nm a c W: - 11 get resolving manifests overwrite None partial False ancestor 924404dff337 local ecf3cb2a4219+ remote e6abcc1a30c2 + a: divergent renames -> dr rev: versions differ -> m c: remote created -> g +warning: detected divergent renames of a to: + b + c getting c merging rev my rev@ecf3cb2a4219+ other rev@e6abcc1a30c2 ancestor rev@924404dff337