Patchwork [11,of,12,v2] copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)

login
register
mail settings
Submitter Gábor Stefanik
Date Oct. 16, 2016, 3:15 p.m.
Message ID <a3a36d782f4d4252adb9.1476630948@GSTEFANIK.NavnGo.local>
Download mbox | patch
Permalink /patch/17140/
State Accepted
Headers show

Comments

Gábor Stefanik - Oct. 16, 2016, 3:15 p.m.
# HG changeset patch
# User Gábor Stefanik <gabor.stefanik@nng.com>
# Date 1476153587 -7200
#      Tue Oct 11 04:39:47 2016 +0200
# Node ID a3a36d782f4d4252adb9069eb37149999f946881
# Parent  2bf601f8e1d3569fdef9ab9f3fefa354acce8669
copies: make _checkcopies handle copy sequences spanning the TCA (issue4028)

When working in a rotated DAG (for a graftlike merge), there can be files
that are renamed both between the base and the topological CA, and between
the TCA and the endpoint farther from the base. Such renames span the TCA
(and thus need both passes of _checkcopies to be fully detected), but may
not necessarily be divergent.

Make _checkcopies return "incomplete copies" and "incomplete divergences"
in this case, and let mergecopies recombine them once data from both passes
of _checkcopies is available.

With this patch, all known cases involving renames and grafts pass.

(Developed together with Pierre-Yves David)

Patch

diff -r 2bf601f8e1d3 -r a3a36d782f4d mercurial/copies.py
--- a/mercurial/copies.py	Tue Oct 11 04:25:59 2016 +0200
+++ b/mercurial/copies.py	Tue Oct 11 04:39:47 2016 +0200
@@ -611,6 +611,7 @@ 
     """
 
     mb = base.manifest()
+    mta = tca.manifest()
     # Might be true if this call is about finding backward renames,
     # This happens in the case of grafts because the DAG is then rotated.
     # If the file exists in both the base and the source, we are not looking
@@ -665,8 +666,17 @@ 
                         break
             return
 
-    if of in mb:
-        data['diverge'].setdefault(of, []).append(f)
+    if of in mta:
+        if backwards or remotebase:
+            data['incomplete'][of] = f
+        else:
+            for sf in seen:
+                if sf in mb:
+                    if tca == base:
+                        data['diverge'].setdefault(sf, []).append(f)
+                    else:
+                        data['incompletediverge'][sf] = [of, f]
+                    return
 
 def duplicatecopies(repo, rev, fromrev, skiprev=None):
     '''reproduce copies from fromrev to rev in the dirstate
diff -r 2bf601f8e1d3 -r a3a36d782f4d tests/test-graft.t
--- a/tests/test-graft.t	Tue Oct 11 04:25:59 2016 +0200
+++ b/tests/test-graft.t	Tue Oct 11 04:39:47 2016 +0200
@@ -957,15 +957,6 @@ 
   grafting 2:f58c7e2b28fa "C0"
   merging f1a and f1b to f1a
   merging f5a
-  warning: conflicts while merging f5a! (edit, then use 'hg resolve --mark')
-  abort: unresolved conflicts, can't continue
-  (use 'hg resolve' and 'hg graft --continue')
-  [255]
-  $ hg resolve f5a -t ':other' # XXX work around failure
-  (no more unresolved files)
-  continue: hg graft --continue
-  $ hg graft --continue # XXX work around failure
-  grafting 2:f58c7e2b28fa "C0"
   warning: can't find ancestor for 'f5a' copied from 'f5b'!
   $ hg status --change .
   M f1a
@@ -975,7 +966,7 @@ 
   $ hg cat f1a
   c1c
   $ hg cat f1b
-  f1b: no such file in rev 43e4b415492d
+  f1b: no such file in rev c9763722f9bd
   [1]
 
 Test the cases A.0 (f4x) and A.6 (f3x)
@@ -997,23 +988,23 @@ 
   $ hg mv f5a f5b
   $ hg ci -qAm "E0"
   $ hg log -G
-  @  changeset:   6:ebba59d1fb02
+  @  changeset:   6:6bd1736cab86
   |  tag:         tip
   |  parent:      0:11f7a1b56675
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     E0
   |
-  | o  changeset:   5:4f4ba7a6e606
+  | o  changeset:   5:560daee679da
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     D1
   | |
-  | o  changeset:   4:43e4b415492d
+  | o  changeset:   4:c9763722f9bd
   |/   parent:      0:11f7a1b56675
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    summary:     C0
+  |    summary:     C1
   |
   | o  changeset:   3:b69f5839d2d9
   | |  user:        test
@@ -1041,34 +1032,24 @@ 
 
   $ HGEDITOR="echo C2 >" hg graft -r 'desc("C0")' --edit
   grafting 2:f58c7e2b28fa "C0"
-  other [graft] changed f1b which local [local] deleted
-  use (c)hanged version, leave (d)eleted, or leave (u)nresolved? u
+  merging f1e and f1b to f1e
   merging f2a and f2c to f2c
   merging f5b and f5a to f5a
-  abort: unresolved conflicts, can't continue
-  (use 'hg resolve' and 'hg graft --continue')
-  [255]
-  $ hg resolve f1b -t ':other' # XXX work around failure
-  (no more unresolved files)
-  continue: hg graft --continue
-  $ hg graft --continue # XXX work around failure
-  grafting 2:f58c7e2b28fa "C0"
-  grafting 4:43e4b415492d "C0"
-  merging f1e and f1a to f1e
-  merging f2c
-  warning: can't find ancestor for 'f2c' copied from 'f2a'!
 
 Test the cases A.1 (f4x) and A.7 (f3x).
 
   $ HGEDITOR="echo D2 >" hg graft -r 'desc("D0")' --edit
   grafting 3:b69f5839d2d9 "D0"
+  note: possible conflict - f3b was renamed multiple times to:
+   f3e
+   f3d
   merging f4e and f4a to f4e
   warning: can't find ancestor for 'f3d' copied from 'f3b'!
 
 Check the results of the grafts tested
 
   $ hg log -CGv --patch --git
-  @  changeset:   9:100f4d78e056
+  @  changeset:   8:93ee502e8b0a
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
@@ -1090,12 +1071,13 @@ 
   |  -c4a
   |  +c4d
   |
-  o  changeset:   8:84915a7da133
+  o  changeset:   7:539cf145f496
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  files:       f1e f5a.orig
+  |  files:       f1e f2a f2c f5a f5b
+  |  copies:      f2c (f2a) f5a (f5b)
   |  description:
-  |  C0
+  |  C2
   |
   |
   |  diff --git a/f1e b/f1e
@@ -1104,32 +1086,6 @@ 
   |  @@ -1,1 +1,1 @@
   |  -c1a
   |  +c1c
-  |  diff --git a/f5a.orig b/f5a.orig
-  |  deleted file mode 100644
-  |  --- a/f5a.orig
-  |  +++ /dev/null
-  |  @@ -1,5 +0,0 @@
-  |  -<<<<<<< local: 11f7a1b56675  - test: A0
-  |  -c5a
-  |  -=======
-  |  -c5c
-  |  ->>>>>>> graft: f58c7e2b28fa  - test: C0
-  |
-  o  changeset:   7:dc778749ee9a
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  files:       f1b f2a f2c f5a f5b
-  |  copies:      f2c (f2a) f5a (f5b)
-  |  description:
-  |  C0
-  |
-  |
-  |  diff --git a/f1b b/f1b
-  |  new file mode 100644
-  |  --- /dev/null
-  |  +++ b/f1b
-  |  @@ -0,0 +1,1 @@
-  |  +c1c
   |  diff --git a/f2a b/f2c
   |  rename from f2a
   |  rename to f2c
@@ -1142,11 +1098,11 @@ 
   |  -c5a
   |  +c5c
   |
-  o  changeset:   6:ebba59d1fb02
+  o  changeset:   6:6bd1736cab86
   |  parent:      0:11f7a1b56675
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  files:       f1a f1e f2a f3a f3e f4a f4e f5a f5a.orig f5b
+  |  files:       f1a f1e f2a f3a f3e f4a f4e f5a f5b
   |  copies:      f1e (f1a) f3e (f3a) f4e (f4a) f5b (f5a)
   |  description:
   |  E0
@@ -1167,21 +1123,11 @@ 
   |  diff --git a/f4a b/f4e
   |  rename from f4a
   |  rename to f4e
-  |  diff --git a/f5a.orig b/f5a.orig
-  |  new file mode 100644
-  |  --- /dev/null
-  |  +++ b/f5a.orig
-  |  @@ -0,0 +1,5 @@
-  |  +<<<<<<< local: 11f7a1b56675  - test: A0
-  |  +c5a
-  |  +=======
-  |  +c5c
-  |  +>>>>>>> graft: f58c7e2b28fa  - test: C0
   |  diff --git a/f5a b/f5b
   |  rename from f5a
   |  rename to f5b
   |
-  | o  changeset:   5:4f4ba7a6e606
+  | o  changeset:   5:560daee679da
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  files:       f3d f4a
@@ -1202,14 +1148,14 @@ 
   | |  -c4a
   | |  +c4d
   | |
-  | o  changeset:   4:43e4b415492d
+  | o  changeset:   4:c9763722f9bd
   |/   parent:      0:11f7a1b56675
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    files:       f1a f2a f2c f5a
   |    copies:      f2c (f2a)
   |    description:
-  |    C0
+  |    C1
   |
   |
   |    diff --git a/f1a b/f1a