changeset 34545:1913162854f2

merge: add pathconflict merge state Path conflicts that occur during merges are represented by 'pu' (unresolved) and 'pr' (resolved) records in the merge state. These are stored on disk in 'P' records. Differential Revision: https://phab.mercurial-scm.org/D774
author Mark Thomas <mbthomas@fb.com>
date Mon, 02 Oct 2017 14:05:30 -0700
parents 34c8080d12ac
children e4cf957bf7ce
files mercurial/merge.py
diffstat 1 files changed, 23 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/merge.py	Mon Oct 02 14:05:30 2017 -0700
+++ b/mercurial/merge.py	Mon Oct 02 14:05:30 2017 -0700
@@ -66,6 +66,7 @@
     C: a change/delete or delete/change conflict
     D: a file that the external merge driver will merge internally
        (experimental)
+    P: a path conflict (file vs directory)
     m: the external merge driver defined for this merge plus its run state
        (experimental)
     f: a (filename, dictionary) tuple of optional values for a given file
@@ -79,6 +80,15 @@
     m: driver-resolved files marked -- only needs to be run before commit
     s: success/skipped -- does not need to be run any more
 
+    Merge record states (stored in self._state, indexed by filename):
+    u: unresolved conflict
+    r: resolved conflict
+    pu: unresolved path conflict (file conflicts with directory)
+    pr: resolved path conflict
+    d: driver-resolved conflict
+
+    The resolve command transitions between 'u' and 'r' for conflicts and
+    'pu' and 'pr' for path conflicts.
     '''
     statepathv1 = 'merge/state'
     statepathv2 = 'merge/state2'
@@ -158,7 +168,7 @@
 
                 self._readmergedriver = bits[0]
                 self._mdstate = mdstate
-            elif rtype in 'FDC':
+            elif rtype in 'FDCP':
                 bits = record.split('\0')
                 self._state[bits[0]] = bits[1:]
             elif rtype == 'f':
@@ -354,6 +364,8 @@
         for d, v in self._state.iteritems():
             if v[0] == 'd':
                 records.append(('D', '\0'.join([d] + v)))
+            elif v[0] in ('pu', 'pr'):
+                records.append(('P', '\0'.join([d] + v)))
             # v[1] == local ('cd'), v[6] == other ('dc') -- not supported by
             # older versions of Mercurial
             elif v[1] == nullhex or v[6] == nullhex:
@@ -422,6 +434,15 @@
         self._stateextras[fd] = {'ancestorlinknode': hex(fca.node())}
         self._dirty = True
 
+    def addpath(self, path, frename, forigin):
+        """add a new conflicting path to the merge state
+        path:    the path that conflicts
+        frename: the filename the conflicting file was renamed to
+        forigin: origin of the file ('l' or 'r' for local/remote)
+        """
+        self._state[path] = ['pu', frename, forigin]
+        self._dirty = True
+
     def __contains__(self, dfile):
         return dfile in self._state
 
@@ -445,7 +466,7 @@
         """Obtain the paths of unresolved files."""
 
         for f, entry in self._state.iteritems():
-            if entry[0] == 'u':
+            if entry[0] in ('u', 'pu'):
                 yield f
 
     def driverresolved(self):