Patchwork [6,of,8] copies: update _checkcopies to work in a rotated DAG (issue4028)

login
register
mail settings
Submitter Gábor Stefanik
Date Oct. 4, 2016, 2:06 p.m.
Message ID <a1b8ff5837d36693338b.1475589964@waste.org>
Download mbox | patch
Permalink /patch/16845/
State Superseded
Headers show

Comments

Gábor Stefanik - Oct. 4, 2016, 2:06 p.m.
# HG changeset patch
# User Gábor Stefanik <gabor.stefanik@nng.com>
# Date 1475588213 -7200
#      Tue Oct 04 15:36:53 2016 +0200
# Node ID a1b8ff5837d36693338b51966dd92249e728cba2
# Parent  bc8729a69d10d61498712d5dab773918f1edcde0
copies: update _checkcopies to work in a rotated DAG (issue4028)

Patch

diff --git a/mercurial/copies.py b/mercurial/copies.py
--- a/mercurial/copies.py
+++ b/mercurial/copies.py
@@ -345,10 +345,12 @@ 
     bothnew = sorted(addedinm1 & addedinm2)
 
     for f in u1u:
-        _checkcopies(c1, f, m1, m2, ca, limit, diverge, copy1, fullcopy1)
+        _checkcopies(c1, f, m1, m2, ca, ca, False, limit, diverge, copy1,
+                     fullcopy1)
 
     for f in u2u:
-        _checkcopies(c2, f, m2, m1, ca, limit, diverge, copy2, fullcopy2)
+        _checkcopies(c2, f, m2, m1, ca, ca, False, limit, diverge, copy2,
+                     fullcopy2)
 
     copy = dict(copy1.items() + copy2.items())
     movewithdir = dict(movewithdir1.items() + movewithdir2.items())
@@ -373,8 +375,10 @@ 
                       % "\n   ".join(bothnew))
     bothdiverge, _copy, _fullcopy = {}, {}, {}
     for f in bothnew:
-        _checkcopies(c1, f, m1, m2, ca, limit, bothdiverge, _copy, _fullcopy)
-        _checkcopies(c2, f, m2, m1, ca, limit, bothdiverge, _copy, _fullcopy)
+        _checkcopies(c1, f, m1, m2, ca, ca, False, limit, bothdiverge, _copy,
+                     _fullcopy)
+        _checkcopies(c2, f, m2, m1, ca, ca, False, limit, bothdiverge, _copy,
+                     _fullcopy)
     for of, fl in bothdiverge.items():
         if len(fl) == 2 and fl[0] == fl[1]:
             copy[fl[0]] = of # not actually divergent, just matching renames
@@ -454,7 +458,8 @@ 
 
     return copy, movewithdir, diverge, renamedelete
 
-def _checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy):
+def _checkcopies(ctx, f, m1, m2, ca, tca, remoteca, limit, diverge, copy,
+                 fullcopy):
     """
     check possible copies of f from m1 to m2
 
@@ -462,7 +467,9 @@ 
     f = the filename to check
     m1 = the source manifest
     m2 = the destination manifest
-    ca = the changectx of the common ancestor
+    ca = the changectx of the common ancestor, overridden on graft
+    tca = topological common ancestor for graft-like scenarios
+    remoteca = True if ca is outside tca::ctx, False otherwise
     limit = the rev number to not search beyond
     diverge = record all diverges in this dict
     copy = record all non-divergent copies in this dict
@@ -475,6 +482,8 @@ 
     """
 
     ma = ca.manifest()
+    mta = tca.manifest()
+    backwards = ca != tca and not remoteca and f in ma
     getfctx = _makegetfctx(ctx)
 
     def _related(f1, f2, limit):
@@ -520,15 +529,26 @@ 
             continue
         seen.add(of)
 
-        fullcopy[f] = of # remember for dir rename detection
+        # remember for dir rename detection
+        if backwards:
+            fullcopy[of] = f # grafting backwards through renames
+        else:
+            fullcopy[f] = of
         if of not in m2:
             continue # no match, keep looking
         if m2[of] == ma.get(of):
             return # no merge needed, quit early
         c2 = getfctx(of, m2[of])
-        cr = _related(oc, c2, ca.rev())
+        cr = _related(oc, c2, tca.rev())
         if cr and (of == f or of == c2.path()): # non-divergent
-            copy[f] = of
+            if backwards:
+                copy[of] = f
+            elif of in ma:
+                copy[f] = of
+            elif remoteca: # special case: a <- b <- a -> b "ping-pong" rename
+                copy[of] = f
+                del fullcopy[f]
+                fullcopy[of] = f
             return
 
     if of in ma:
diff --git a/tests/test-graft.t b/tests/test-graft.t
--- a/tests/test-graft.t
+++ b/tests/test-graft.t
@@ -427,8 +427,8 @@ 
   $ hg graft 3 --log -u foo
   grafting 3:4c60f11aa304 "3"
   warning: can't find ancestor for 'c' copied from 'b'!
-  $ hg log --template '{rev} {parents} {desc}\n' -r tip
-  14 1:5d205f8b35b6  3
+  $ hg log --template '{rev}:{node|short} {parents} {desc}\n' -r tip
+  14:0c921c65ef1e 1:5d205f8b35b6  3
   (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
 
 Resolve conflicted graft
@@ -620,7 +620,7 @@ 
   date:        Thu Jan 01 00:00:00 1970 +0000
   summary:     2
   
-  changeset:   14:f64defefacee
+  changeset:   14:0c921c65ef1e
   parent:      1:5d205f8b35b6
   user:        foo
   date:        Thu Jan 01 00:00:00 1970 +0000