Mercurial > public > mercurial-scm > hg
comparison mercurial/merge.py @ 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 | bed1d2eaa108 |
children | 81aebcc73beb |
comparison
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 |