Patchwork [10,of,16] merge: keep destination filename as key in actions for merge with dir rename

login
register
mail settings
Submitter Mads Kiilerich
Date March 2, 2014, 7:15 p.m.
Message ID <6b0a190609ec080ff606.1393787743@localhost.localdomain>
Download mbox | patch
Permalink /patch/3822/
State Accepted
Commit 5b8d5803d7b7fb219ccc955c811646ca69e60330
Headers show

Comments

Mads Kiilerich - March 2, 2014, 7:15 p.m.
# HG changeset patch
# User Mads Kiilerich <madski@unity3d.com>
# Date 1393782576 -3600
#      Sun Mar 02 18:49:36 2014 +0100
# Node ID 6b0a190609ec080ff606f676bcebea54c89fc46f
# Parent  f35dafc5600776ed238241565e5cbfa7e2dfd71c
merge: keep destination filename as key in actions for merge with dir rename

Avoids
   None: local renamed directory to b/c -> d
  updating:None 1/1 files (100.00%)
and makes it possible to compare/merge actions later.

Patch

diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -274,11 +274,13 @@  def _checkcollision(repo, wmf, actions):
     def nop(f, args):
         pass
 
-    def renameop(f, args):
-        f2, fd, flags = args
-        if f:
-            pmmf.discard(f)
-        pmmf.add(fd)
+    def renamemoveop(f, args):
+        f2, flags = args
+        pmmf.discard(f2)
+        pmmf.add(f)
+    def renamegetop(f, args):
+        f2, flags = args
+        pmmf.add(f)
     def mergeop(f, args):
         f2, fa, fd, move, anc = args
         if move:
@@ -287,7 +289,8 @@  def _checkcollision(repo, wmf, actions):
 
     opmap = {
         "a": addop,
-        "d": renameop,
+        "dm": renamemoveop,
+        "dg": renamegetop,
         "dr": nop,
         "e": nop,
         "f": addop, # untracked file should be kept in working directory
@@ -412,10 +415,10 @@  def manifestmerge(repo, wctx, p2, pa, br
                                "versions differ"))
         elif f in copied: # files we'll deal with on m2 side
             pass
-        elif n1 and f in movewithdir: # directory rename
+        elif n1 and f in movewithdir: # directory rename, move local
             f2 = movewithdir[f]
-            actions.append((f, "d", (None, f2, fl1),
-                            "remote renamed directory to " + f2))
+            actions.append((f2, "dm", (f, fl1),
+                            "remote directory rename - move from " + f))
         elif n1 and f in copy:
             f2 = copy[f]
             actions.append((f, "m", (f2, f2, f, False, pa.node()),
@@ -432,8 +435,8 @@  def manifestmerge(repo, wctx, p2, pa, br
                 actions.append((f, "r", None, "other deleted"))
         elif n2 and f in movewithdir:
             f2 = movewithdir[f]
-            actions.append((None, "d", (f, f2, fl2),
-                            "local renamed directory to " + f2))
+            actions.append((f2, "dg", (f, fl2),
+                            "local directory rename - get from " + f))
         elif n2 and f in copy:
             f2 = copy[f]
             if f2 in m2:
@@ -633,16 +636,17 @@  def applyupdates(repo, actions, wctx, mc
                     updated += 1
                 else:
                     merged += 1
-        elif m == "d": # directory rename
-            f2, fd, flags = args
-            if f:
-                repo.ui.note(_("moving %s to %s\n") % (f, fd))
-                audit(fd)
-                repo.wwrite(fd, wctx.filectx(f).data(), flags)
-                util.unlinkpath(repo.wjoin(f))
-            if f2:
-                repo.ui.note(_("getting %s to %s\n") % (f2, fd))
-                repo.wwrite(fd, mctx.filectx(f2).data(), flags)
+        elif m == "dm": # directory rename, move local
+            f0, flags = args
+            repo.ui.note(_("moving %s to %s\n") % (f0, f))
+            audit(f)
+            repo.wwrite(f, wctx.filectx(f0).data(), flags)
+            util.unlinkpath(repo.wjoin(f0))
+            updated += 1
+        elif m == "dg": # local directory rename, get
+            f0, flags = args
+            repo.ui.note(_("getting %s to %s\n") % (f0, f))
+            repo.wwrite(f, mctx.filectx(f0).data(), flags)
             updated += 1
         elif m == "dr": # divergent renames
             fl, = args
@@ -751,22 +755,25 @@  def recordupdates(repo, actions, branchm
                     repo.dirstate.normallookup(fd)
                 if move:
                     repo.dirstate.drop(f)
-        elif m == "d": # directory rename
-            f2, fd, flag = args
-            if not f2 and f not in repo.dirstate:
+        elif m == "dm": # directory rename, move local
+            f0, flag = args
+            if f0 not in repo.dirstate:
                 # untracked file moved
                 continue
             if branchmerge:
-                repo.dirstate.add(fd)
-                if f:
-                    repo.dirstate.remove(f)
-                    repo.dirstate.copy(f, fd)
-                if f2:
-                    repo.dirstate.copy(f2, fd)
+                repo.dirstate.add(f)
+                repo.dirstate.remove(f0)
+                repo.dirstate.copy(f0, f)
             else:
-                repo.dirstate.normal(fd)
-                if f:
-                    repo.dirstate.drop(f)
+                repo.dirstate.normal(f)
+                repo.dirstate.drop(f0)
+        elif m == "dg": # directory rename, get
+            f0, flag = args
+            if branchmerge:
+                repo.dirstate.add(f)
+                repo.dirstate.copy(f0, f)
+            else:
+                repo.dirstate.normal(f)
 
 def update(repo, node, branchmerge, force, partial, ancestor=None,
            mergeancestor=False):
diff --git a/tests/test-rename-dir-merge.t b/tests/test-rename-dir-merge.t
--- a/tests/test-rename-dir-merge.t
+++ b/tests/test-rename-dir-merge.t
@@ -41,16 +41,16 @@ 
    ancestor: f9b20c0d4c51, local: ce36d17b18fb+, remote: 397f8b00a740
    a/a: other deleted -> r
    a/b: other deleted -> r
-   a/c: remote renamed directory to b/c -> d
    b/a: remote created -> g
    b/b: remote created -> g
+   b/c: remote directory rename - move from a/c -> dm
   removing a/a
   removing a/b
   updating: a/b 2/5 files (40.00%)
   getting b/a
   getting b/b
   updating: b/b 4/5 files (80.00%)
-  updating: a/c 5/5 files (100.00%)
+  updating: b/c 5/5 files (100.00%)
   moving a/c to b/c (glob)
   3 files updated, 0 files merged, 2 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
@@ -88,8 +88,8 @@ 
   resolving manifests
    branchmerge: True, force: False, partial: False
    ancestor: f9b20c0d4c51, local: 397f8b00a740+, remote: ce36d17b18fb
-   None: local renamed directory to b/c -> d
-  updating:None 1/1 files (100.00%)
+   b/c: local directory rename - get from a/c -> dg
+  updating: b/c 1/1 files (100.00%)
   getting a/c to b/c
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)