[PATCH 09 of 12 v2] mergecopies: add logic to process incomplete data

Gábor Stefanik gabor.stefanik at nng.com
Sun Oct 16 11:15:46 EDT 2016


# HG changeset patch
# User Gábor Stefanik <gabor.stefanik at nng.com>
# Date 1475578314 -7200
#      Tue Oct 04 12:51:54 2016 +0200
# Node ID 9fc636d9950feb76af774f881ea179037231e697
# Parent  73b55839aca7019d88cc9885e43244fb1e6d68ab
mergecopies: add logic to process incomplete data

We first combine incomplete copies on the two sides of the topological CA
into complete copies.
Any leftover incomplete copies are then combined with the incomplete
divergences to reconstruct divergences spanning over the topological CA.
Finally we promote any divergences falsely flagged as incomplete to full
divergences.

Right now, there is nothing generating incomplete copy/divergence data,
so this code does nothing. Changes to _checkcopies to populate these
dicts are coming later in this series.

diff -r 73b55839aca7 -r 9fc636d9950f mercurial/copies.py
--- a/mercurial/copies.py	Wed Oct 12 11:54:03 2016 +0200
+++ b/mercurial/copies.py	Tue Oct 04 12:51:54 2016 +0200
@@ -289,6 +289,22 @@
         return fctx
     return util.lrucachefunc(makectx)
 
+def _combinecopies(copyfrom, copyto, finalcopy, diverge, incompletediverge):
+    """combine partial copy paths"""
+    remainder = {}
+    for f in copyfrom:
+        if f in copyto:
+            finalcopy[copyto[f]] = copyfrom[f]
+            del copyto[f]
+    for f in incompletediverge:
+        assert f not in diverge
+        ic = incompletediverge[f]
+        if ic[0] in copyto:
+            diverge[f] = [copyto[ic[0]], ic[1]]
+        else:
+            remainder[f] = ic
+    return remainder
+
 def mergecopies(repo, c1, c2, base):
     """
     Find moves and copies between context c1 and c2 that are relevant
@@ -360,14 +376,21 @@
     # - diverge = record all diverges in this dict
     # - copy = record all non-divergent copies in this dict
     # - fullcopy = record all copies in this dict
+    # - incomplete = record non-divergent partial copies here
+    # - incompletediverge = record divergent partial copies here
     diverge = {} # divergence data is shared
+    incompletediverge  = {}
     data1 = {'copy': {},
              'fullcopy': {},
+             'incomplete': {},
              'diverge': diverge,
+             'incompletediverge': incompletediverge,
             }
     data2 = {'copy': {},
              'fullcopy': {},
+             'incomplete': {},
              'diverge': diverge,
+             'incompletediverge': incompletediverge,
             }
 
     # find interesting file sets from manifests
@@ -398,6 +421,13 @@
     copy = dict(data1['copy'].items() + data2['copy'].items())
     fullcopy = dict(data1['fullcopy'].items() + data2['fullcopy'].items())
 
+    if dirtyc1:
+        _combinecopies(data2['incomplete'], data1['incomplete'], copy, diverge,
+                       incompletediverge)
+    else:
+        _combinecopies(data1['incomplete'], data2['incomplete'], copy, diverge,
+                       incompletediverge)
+
     renamedelete = {}
     renamedeleteset = set()
     divergeset = set()
@@ -416,13 +446,36 @@
         repo.ui.debug("  unmatched files new in both:\n   %s\n"
                       % "\n   ".join(bothnew))
     bothdiverge = {}
-    bothdata = {'copy': {},
-                'fullcopy': {},
-                'diverge': bothdiverge,
-               }
+    bothincompletediverge = {}
+    both1 = {'copy': {},
+             'fullcopy': {},
+             'incomplete': {},
+             'diverge': bothdiverge,
+             'incompletediverge': bothincompletediverge
+            }
+    both2 = {'copy': {},
+             'fullcopy': {},
+             'incomplete': {},
+             'diverge': bothdiverge,
+             'incompletediverge': bothincompletediverge
+            }
     for f in bothnew:
-        _checkcopies(c1, f, m1, m2, base, tca, limit, bothdata)
-        _checkcopies(c2, f, m2, m1, base, tca, limit, bothdata)
+        _checkcopies(c1, f, m1, m2, base, tca, limit, both1)
+        _checkcopies(c2, f, m2, m1, base, tca, limit, both2)
+    if dirtyc1:
+        assert both2['incomplete'] == {}
+        remainder = _combinecopies({}, both1['incomplete'], copy, bothdiverge,
+                                   bothincompletediverge)
+    else:
+        assert both1['incomplete'] == {}
+        remainder = _combinecopies({}, both2['incomplete'], copy, bothdiverge,
+                                   bothincompletediverge)
+    for f in remainder:
+        assert f not in bothdiverge
+        ic = remainder[f]
+        if ic[0] in (m1 if dirtyc1 else m2):
+            # backed-out rename on one side, but watch out for deleted files
+            bothdiverge[f] = ic
     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


More information about the Mercurial-devel mailing list