merge: warn user about divergent renames
authorMatt Mackall <mpm@selenic.com>
Thu, 21 Jun 2007 18:02:03 -0500
changeset 4674 723e0ddb6ada
parent 4673 d8442fc0da8d
child 4676 0f6e2b37512d
merge: warn user about divergent renames
mercurial/merge.py
tests/test-bundle-r.out
tests/test-rename-merge1.out
tests/test-rename-merge2.out
--- a/mercurial/merge.py	Thu Jun 21 22:19:41 2007 +0200
+++ b/mercurial/merge.py	Thu Jun 21 18:02:03 2007 -0500
@@ -155,11 +155,15 @@
 
     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 @@
                 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 @@
     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 @@
     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 @@
                     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 @@
     backwards = (pa == p2)
     action = []
     copy = {}
+    diverge = {}
 
     def fmerge(f, f2=None, fa=None):
         """merge flags"""
@@ -273,7 +285,11 @@
         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 @@
                 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)
--- a/tests/test-bundle-r.out	Thu Jun 21 22:19:41 2007 +0200
+++ b/tests/test-bundle-r.out	Thu Jun 21 18:02:03 2007 -0500
@@ -197,6 +197,9 @@
 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
--- a/tests/test-rename-merge1.out	Thu Jun 21 22:19:41 2007 +0200
+++ b/tests/test-rename-merge1.out	Thu Jun 21 18:02:03 2007 -0500
@@ -4,12 +4,16 @@
 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)
--- a/tests/test-rename-merge2.out	Thu Jun 21 22:19:41 2007 +0200
+++ b/tests/test-rename-merge2.out	Thu Jun 21 18:02:03 2007 -0500
@@ -173,8 +173,12 @@
 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