mercurial/merge.py
changeset 34545 1913162854f2
parent 34522 bed1d2eaa108
child 34547 81aebcc73beb
equal deleted inserted replaced
34544:34c8080d12ac 34545:1913162854f2
    64     O: the node of the "other" part of the merge (hexified version)
    64     O: the node of the "other" part of the merge (hexified version)
    65     F: a file to be merged entry
    65     F: a file to be merged entry
    66     C: a change/delete or delete/change conflict
    66     C: a change/delete or delete/change conflict
    67     D: a file that the external merge driver will merge internally
    67     D: a file that the external merge driver will merge internally
    68        (experimental)
    68        (experimental)
       
    69     P: a path conflict (file vs directory)
    69     m: the external merge driver defined for this merge plus its run state
    70     m: the external merge driver defined for this merge plus its run state
    70        (experimental)
    71        (experimental)
    71     f: a (filename, dictionary) tuple of optional values for a given file
    72     f: a (filename, dictionary) tuple of optional values for a given file
    72     X: unsupported mandatory record type (used in tests)
    73     X: unsupported mandatory record type (used in tests)
    73     x: unsupported advisory record type (used in tests)
    74     x: unsupported advisory record type (used in tests)
    77     u: driver-resolved files unmarked -- needs to be run next time we're about
    78     u: driver-resolved files unmarked -- needs to be run next time we're about
    78        to resolve or commit
    79        to resolve or commit
    79     m: driver-resolved files marked -- only needs to be run before commit
    80     m: driver-resolved files marked -- only needs to be run before commit
    80     s: success/skipped -- does not need to be run any more
    81     s: success/skipped -- does not need to be run any more
    81 
    82 
       
    83     Merge record states (stored in self._state, indexed by filename):
       
    84     u: unresolved conflict
       
    85     r: resolved conflict
       
    86     pu: unresolved path conflict (file conflicts with directory)
       
    87     pr: resolved path conflict
       
    88     d: driver-resolved conflict
       
    89 
       
    90     The resolve command transitions between 'u' and 'r' for conflicts and
       
    91     'pu' and 'pr' for path conflicts.
    82     '''
    92     '''
    83     statepathv1 = 'merge/state'
    93     statepathv1 = 'merge/state'
    84     statepathv2 = 'merge/state2'
    94     statepathv2 = 'merge/state2'
    85 
    95 
    86     @staticmethod
    96     @staticmethod
   156                     # the merge driver should be idempotent, so just rerun it
   166                     # the merge driver should be idempotent, so just rerun it
   157                     mdstate = 'u'
   167                     mdstate = 'u'
   158 
   168 
   159                 self._readmergedriver = bits[0]
   169                 self._readmergedriver = bits[0]
   160                 self._mdstate = mdstate
   170                 self._mdstate = mdstate
   161             elif rtype in 'FDC':
   171             elif rtype in 'FDCP':
   162                 bits = record.split('\0')
   172                 bits = record.split('\0')
   163                 self._state[bits[0]] = bits[1:]
   173                 self._state[bits[0]] = bits[1:]
   164             elif rtype == 'f':
   174             elif rtype == 'f':
   165                 filename, rawextras = record.split('\0', 1)
   175                 filename, rawextras = record.split('\0', 1)
   166                 extraparts = rawextras.split('\0')
   176                 extraparts = rawextras.split('\0')
   352             records.append(('m', '\0'.join([
   362             records.append(('m', '\0'.join([
   353                 self.mergedriver, self._mdstate])))
   363                 self.mergedriver, self._mdstate])))
   354         for d, v in self._state.iteritems():
   364         for d, v in self._state.iteritems():
   355             if v[0] == 'd':
   365             if v[0] == 'd':
   356                 records.append(('D', '\0'.join([d] + v)))
   366                 records.append(('D', '\0'.join([d] + v)))
       
   367             elif v[0] in ('pu', 'pr'):
       
   368                 records.append(('P', '\0'.join([d] + v)))
   357             # v[1] == local ('cd'), v[6] == other ('dc') -- not supported by
   369             # v[1] == local ('cd'), v[6] == other ('dc') -- not supported by
   358             # older versions of Mercurial
   370             # older versions of Mercurial
   359             elif v[1] == nullhex or v[6] == nullhex:
   371             elif v[1] == nullhex or v[6] == nullhex:
   360                 records.append(('C', '\0'.join([d] + v)))
   372                 records.append(('C', '\0'.join([d] + v)))
   361             else:
   373             else:
   420                            fco.path(), hex(fco.filenode()),
   432                            fco.path(), hex(fco.filenode()),
   421                            fcl.flags()]
   433                            fcl.flags()]
   422         self._stateextras[fd] = {'ancestorlinknode': hex(fca.node())}
   434         self._stateextras[fd] = {'ancestorlinknode': hex(fca.node())}
   423         self._dirty = True
   435         self._dirty = True
   424 
   436 
       
   437     def addpath(self, path, frename, forigin):
       
   438         """add a new conflicting path to the merge state
       
   439         path:    the path that conflicts
       
   440         frename: the filename the conflicting file was renamed to
       
   441         forigin: origin of the file ('l' or 'r' for local/remote)
       
   442         """
       
   443         self._state[path] = ['pu', frename, forigin]
       
   444         self._dirty = True
       
   445 
   425     def __contains__(self, dfile):
   446     def __contains__(self, dfile):
   426         return dfile in self._state
   447         return dfile in self._state
   427 
   448 
   428     def __getitem__(self, dfile):
   449     def __getitem__(self, dfile):
   429         return self._state[dfile][0]
   450         return self._state[dfile][0]
   443 
   464 
   444     def unresolved(self):
   465     def unresolved(self):
   445         """Obtain the paths of unresolved files."""
   466         """Obtain the paths of unresolved files."""
   446 
   467 
   447         for f, entry in self._state.iteritems():
   468         for f, entry in self._state.iteritems():
   448             if entry[0] == 'u':
   469             if entry[0] in ('u', 'pu'):
   449                 yield f
   470                 yield f
   450 
   471 
   451     def driverresolved(self):
   472     def driverresolved(self):
   452         """Obtain the paths of driver-resolved files."""
   473         """Obtain the paths of driver-resolved files."""
   453 
   474