merge: add rename following
authorMatt Mackall <mpm@selenic.com>
Wed, 04 Oct 2006 15:43:27 -0500
changeset 3249 f05c182430a0
parent 3248 751840e739a1
child 3250 7c114915fbdb
merge: add rename following Currently disabled by default, enable with [merge] followcopies = 1
mercurial/merge.py
--- a/mercurial/merge.py	Wed Oct 04 14:33:22 2006 -0500
+++ b/mercurial/merge.py	Wed Oct 04 15:43:27 2006 -0500
@@ -54,6 +54,13 @@
                              'HG_OTHER_NODE': p2})
     if r:
         repo.ui.warn(_("merging %s failed!\n") % fw)
+    else:
+        if fd != fw:
+            repo.ui.debug(_("copying %s to %s\n") % (fw, fd))
+            repo.wwrite(fd, repo.wread(fw))
+            if move:
+                repo.ui.debug(_("removing %s\n") % fw)
+                os.unlink(a)
 
     os.unlink(b)
     os.unlink(c)
@@ -126,6 +133,9 @@
     Find moves and copies between m1 and m2 back to limit linkrev
     """
 
+    if not repo.ui.config("merge", "followcopies"):
+        return {}
+
     # avoid silly behavior for update from empty dir
     if not m1:
         return {}
@@ -164,14 +174,17 @@
 
     return copy
 
-def manifestmerge(ui, m1, m2, ma, overwrite, backwards, partial):
+def manifestmerge(ui, m1, m2, ma, copy, overwrite, backwards, partial):
     """
     Merge manifest m1 with m2 using ancestor ma and generate merge action list
     """
 
-    def fmerge(f):
+    def fmerge(f, f2=None, fa=None):
         """merge executable flags"""
-        a, b, c = ma.execf(f), m1.execf(f), m2.execf(f)
+        if not f2:
+            f2 = f
+            fa = f
+        a, b, c = ma.execf(fa), m1.execf(f), m2.execf(f2)
         return ((a^b) | (a^c)) ^ a
 
     action = []
@@ -203,6 +216,18 @@
             elif m1.execf(f) != m2.execf(f):
                 if overwrite or fmerge(f) != m1.execf(f):
                     act("update permissions", f, "e", m2.execf(f))
+        elif f in copy:
+            f2 = copy[f]
+            if f in ma: # case 3,20 A/B/A
+                act("remote moved",
+                    f, "c", f2, f2, m1[f], m2[f2], fmerge(f, f2, f), True)
+            else:
+                if f2 in m1: # case 2 A,B/B/B
+                    act("local copied",
+                        f, "c", f2, f, m1[f], m2[f2], fmerge(f, f2, f2), False)
+                else: # case 4,21 A/B/B
+                    act("local moved",
+                        f, "c", f2, f, m1[f], m2[f2], fmerge(f, f2, f2), False)
         elif f in ma:
             if n != ma[f] and not overwrite:
                 if ui.prompt(
@@ -221,7 +246,14 @@
             continue
         if f in m1:
             continue
-        if f in ma:
+        if f in copy:
+            f2 = copy[f]
+            if f2 in ma or f2 in m1: # already seen
+                continue
+            # rename case 1, A/A,B/A
+            act("remote copied",
+                f, "c", f2, f, m1[f2], m2[f], fmerge(f2, f, f2), False)
+        elif f in ma:
             if overwrite or backwards:
                 act("recreating", f, "g", m2.execf(f), n)
             elif n != ma[f]:
@@ -251,6 +283,12 @@
                     repo.ui.warn(_("update failed to remove %s: %s!\n") %
                                  (f, inst.strerror))
             removed +=1
+        elif m == "c": # copy
+            f2, fd, my, other, flag, remove = a[2:]
+            if filemerge(repo, f, f2, fd, my, other, xp1, xp2, remove):
+                unresolved += 1
+            util.set_exec(repo.wjoin(fd), flag)
+            merged += 1
         elif m == "m": # merge
             flag, my, other = a[2:]
             repo.ui.status(_("merging %s\n") % f)
@@ -358,7 +396,8 @@
     if not (backwards or overwrite):
         copy = findcopies(repo, m1, m2, pa.rev())
 
-    action += manifestmerge(repo.ui, m1, m2, ma, overwrite, backwards, partial)
+    action += manifestmerge(repo.ui, m1, m2, ma, copy,
+                            overwrite, backwards, partial)
 
     ### apply phase