mercurial/merge.py
changeset 37111 aa5199c7aa42
parent 37110 1b158ca37ea4
child 37112 43ffd9070da1
equal deleted inserted replaced
37110:1b158ca37ea4 37111:aa5199c7aa42
    62 RECORD_UNSUPPORTED_ADVISORY = b'x'
    62 RECORD_UNSUPPORTED_ADVISORY = b'x'
    63 
    63 
    64 MERGE_DRIVER_STATE_UNMARKED = b'u'
    64 MERGE_DRIVER_STATE_UNMARKED = b'u'
    65 MERGE_DRIVER_STATE_MARKED = b'm'
    65 MERGE_DRIVER_STATE_MARKED = b'm'
    66 MERGE_DRIVER_STATE_SUCCESS = b's'
    66 MERGE_DRIVER_STATE_SUCCESS = b's'
       
    67 
       
    68 MERGE_RECORD_UNRESOLVED = b'u'
       
    69 MERGE_RECORD_RESOLVED = b'r'
       
    70 MERGE_RECORD_UNRESOLVED_PATH = b'pu'
       
    71 MERGE_RECORD_RESOLVED_PATH = b'pr'
       
    72 MERGE_RECORD_DRIVER_RESOLVED = b'd'
    67 
    73 
    68 class mergestate(object):
    74 class mergestate(object):
    69     '''track 3-way merge state of individual files
    75     '''track 3-way merge state of individual files
    70 
    76 
    71     The merge state is stored on disk when needed. Two files are used: one with
    77     The merge state is stored on disk when needed. Two files are used: one with
   389         # is written as the contents of the record. The record type depends on
   395         # is written as the contents of the record. The record type depends on
   390         # the type of state that is stored, and capital-letter records are used
   396         # the type of state that is stored, and capital-letter records are used
   391         # to prevent older versions of Mercurial that do not support the feature
   397         # to prevent older versions of Mercurial that do not support the feature
   392         # from loading them.
   398         # from loading them.
   393         for filename, v in self._state.iteritems():
   399         for filename, v in self._state.iteritems():
   394             if v[0] == 'd':
   400             if v[0] == MERGE_RECORD_DRIVER_RESOLVED:
   395                 # Driver-resolved merge. These are stored in 'D' records.
   401                 # Driver-resolved merge. These are stored in 'D' records.
   396                 records.append((RECORD_MERGE_DRIVER_MERGE,
   402                 records.append((RECORD_MERGE_DRIVER_MERGE,
   397                                 '\0'.join([filename] + v)))
   403                                 '\0'.join([filename] + v)))
   398             elif v[0] in ('pu', 'pr'):
   404             elif v[0] in (MERGE_RECORD_UNRESOLVED_PATH,
       
   405                           MERGE_RECORD_RESOLVED_PATH):
   399                 # Path conflicts. These are stored in 'P' records.  The current
   406                 # Path conflicts. These are stored in 'P' records.  The current
   400                 # resolution state ('pu' or 'pr') is stored within the record.
   407                 # resolution state ('pu' or 'pr') is stored within the record.
   401                 records.append((RECORD_PATH_CONFLICT,
   408                 records.append((RECORD_PATH_CONFLICT,
   402                                 '\0'.join([filename] + v)))
   409                                 '\0'.join([filename] + v)))
   403             elif v[1] == nullhex or v[6] == nullhex:
   410             elif v[1] == nullhex or v[6] == nullhex:
   465         if fcl.isabsent():
   472         if fcl.isabsent():
   466             hash = nullhex
   473             hash = nullhex
   467         else:
   474         else:
   468             hash = hex(hashlib.sha1(fcl.path()).digest())
   475             hash = hex(hashlib.sha1(fcl.path()).digest())
   469             self._repo.vfs.write('merge/' + hash, fcl.data())
   476             self._repo.vfs.write('merge/' + hash, fcl.data())
   470         self._state[fd] = ['u', hash, fcl.path(),
   477         self._state[fd] = [MERGE_RECORD_UNRESOLVED, hash, fcl.path(),
   471                            fca.path(), hex(fca.filenode()),
   478                            fca.path(), hex(fca.filenode()),
   472                            fco.path(), hex(fco.filenode()),
   479                            fco.path(), hex(fco.filenode()),
   473                            fcl.flags()]
   480                            fcl.flags()]
   474         self._stateextras[fd] = {'ancestorlinknode': hex(fca.node())}
   481         self._stateextras[fd] = {'ancestorlinknode': hex(fca.node())}
   475         self._dirty = True
   482         self._dirty = True
   478         """add a new conflicting path to the merge state
   485         """add a new conflicting path to the merge state
   479         path:    the path that conflicts
   486         path:    the path that conflicts
   480         frename: the filename the conflicting file was renamed to
   487         frename: the filename the conflicting file was renamed to
   481         forigin: origin of the file ('l' or 'r' for local/remote)
   488         forigin: origin of the file ('l' or 'r' for local/remote)
   482         """
   489         """
   483         self._state[path] = ['pu', frename, forigin]
   490         self._state[path] = [MERGE_RECORD_UNRESOLVED_PATH, frename, forigin]
   484         self._dirty = True
   491         self._dirty = True
   485 
   492 
   486     def __contains__(self, dfile):
   493     def __contains__(self, dfile):
   487         return dfile in self._state
   494         return dfile in self._state
   488 
   495 
   504 
   511 
   505     def unresolved(self):
   512     def unresolved(self):
   506         """Obtain the paths of unresolved files."""
   513         """Obtain the paths of unresolved files."""
   507 
   514 
   508         for f, entry in self._state.iteritems():
   515         for f, entry in self._state.iteritems():
   509             if entry[0] in ('u', 'pu'):
   516             if entry[0] in (MERGE_RECORD_UNRESOLVED,
       
   517                             MERGE_RECORD_UNRESOLVED_PATH):
   510                 yield f
   518                 yield f
   511 
   519 
   512     def driverresolved(self):
   520     def driverresolved(self):
   513         """Obtain the paths of driver-resolved files."""
   521         """Obtain the paths of driver-resolved files."""
   514 
   522 
   515         for f, entry in self._state.items():
   523         for f, entry in self._state.items():
   516             if entry[0] == 'd':
   524             if entry[0] == MERGE_RECORD_DRIVER_RESOLVED:
   517                 yield f
   525                 yield f
   518 
   526 
   519     def extras(self, filename):
   527     def extras(self, filename):
   520         return self._stateextras.setdefault(filename, {})
   528         return self._stateextras.setdefault(filename, {})
   521 
   529 
   522     def _resolve(self, preresolve, dfile, wctx):
   530     def _resolve(self, preresolve, dfile, wctx):
   523         """rerun merge process for file path `dfile`"""
   531         """rerun merge process for file path `dfile`"""
   524         if self[dfile] in 'rd':
   532         if self[dfile] in (MERGE_RECORD_RESOLVED,
       
   533                            MERGE_RECORD_DRIVER_RESOLVED):
   525             return True, 0
   534             return True, 0
   526         stateentry = self._state[dfile]
   535         stateentry = self._state[dfile]
   527         state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
   536         state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
   528         octx = self._repo[self._other]
   537         octx = self._repo[self._other]
   529         extras = self.extras(dfile)
   538         extras = self.extras(dfile)
   569             # no real conflict
   578             # no real conflict
   570             del self._state[dfile]
   579             del self._state[dfile]
   571             self._stateextras.pop(dfile, None)
   580             self._stateextras.pop(dfile, None)
   572             self._dirty = True
   581             self._dirty = True
   573         elif not r:
   582         elif not r:
   574             self.mark(dfile, 'r')
   583             self.mark(dfile, MERGE_RECORD_RESOLVED)
   575 
   584 
   576         if complete:
   585         if complete:
   577             action = None
   586             action = None
   578             if deleted:
   587             if deleted:
   579                 if fcd.isabsent():
   588                 if fcd.isabsent():