comparison mercurial/merge.py @ 28009:4a25e91fa55d

merge: add state extras merge state data In future commits we will want to store more data related to each file in the merge state. This patch adds an optional record for storing a dictionary of extras for each file.
author Durham Goode <durham@fb.com>
date Fri, 05 Feb 2016 10:15:28 -0800
parents 6bce6d925e45
children 8abd9f785030
comparison
equal deleted inserted replaced
28008:86c4cbdaffee 28009:4a25e91fa55d
63 C: a change/delete or delete/change conflict 63 C: a change/delete or delete/change conflict
64 D: a file that the external merge driver will merge internally 64 D: a file that the external merge driver will merge internally
65 (experimental) 65 (experimental)
66 m: the external merge driver defined for this merge plus its run state 66 m: the external merge driver defined for this merge plus its run state
67 (experimental) 67 (experimental)
68 f: a (filename, dictonary) tuple of optional values for a given file
68 X: unsupported mandatory record type (used in tests) 69 X: unsupported mandatory record type (used in tests)
69 x: unsupported advisory record type (used in tests) 70 x: unsupported advisory record type (used in tests)
70 71
71 Merge driver run states (experimental): 72 Merge driver run states (experimental):
72 u: driver-resolved files unmarked -- needs to be run next time we're about 73 u: driver-resolved files unmarked -- needs to be run next time we're about
100 self._repo = repo 101 self._repo = repo
101 self._dirty = False 102 self._dirty = False
102 103
103 def reset(self, node=None, other=None): 104 def reset(self, node=None, other=None):
104 self._state = {} 105 self._state = {}
106 self._stateextras = {}
105 self._local = None 107 self._local = None
106 self._other = None 108 self._other = None
107 for var in ('localctx', 'otherctx'): 109 for var in ('localctx', 'otherctx'):
108 if var in vars(self): 110 if var in vars(self):
109 delattr(self, var) 111 delattr(self, var)
124 126
125 This function process "record" entry produced by the de-serialization 127 This function process "record" entry produced by the de-serialization
126 of on disk file. 128 of on disk file.
127 """ 129 """
128 self._state = {} 130 self._state = {}
131 self._stateextras = {}
129 self._local = None 132 self._local = None
130 self._other = None 133 self._other = None
131 for var in ('localctx', 'otherctx'): 134 for var in ('localctx', 'otherctx'):
132 if var in vars(self): 135 if var in vars(self):
133 delattr(self, var) 136 delattr(self, var)
150 self._readmergedriver = bits[0] 153 self._readmergedriver = bits[0]
151 self._mdstate = mdstate 154 self._mdstate = mdstate
152 elif rtype in 'FDC': 155 elif rtype in 'FDC':
153 bits = record.split('\0') 156 bits = record.split('\0')
154 self._state[bits[0]] = bits[1:] 157 self._state[bits[0]] = bits[1:]
158 elif rtype == 'f':
159 filename, rawextras = record.split('\0', 1)
160 extraparts = rawextras.split('\0')
161 extras = {}
162 i = 0
163 while i < len(extraparts):
164 extras[extraparts[i]] = extraparts[i + 1]
165 i += 2
166
167 self._stateextras[filename] = extras
155 elif not rtype.islower(): 168 elif not rtype.islower():
156 unsupported.add(rtype) 169 unsupported.add(rtype)
157 self._results = {} 170 self._results = {}
158 self._dirty = False 171 self._dirty = False
159 172
334 # older versions of Mercurial 347 # older versions of Mercurial
335 elif v[1] == nullhex or v[6] == nullhex: 348 elif v[1] == nullhex or v[6] == nullhex:
336 records.append(('C', '\0'.join([d] + v))) 349 records.append(('C', '\0'.join([d] + v)))
337 else: 350 else:
338 records.append(('F', '\0'.join([d] + v))) 351 records.append(('F', '\0'.join([d] + v)))
352 for filename, extras in sorted(self._stateextras.iteritems()):
353 rawextras = '\0'.join('%s\0%s' % (k, v) for k, v in
354 extras.iteritems())
355 records.append(('f', '%s\0%s' % (filename, rawextras)))
339 return records 356 return records
340 357
341 def _writerecords(self, records): 358 def _writerecords(self, records):
342 """Write current state on disk (both v1 and v2)""" 359 """Write current state on disk (both v1 and v2)"""
343 self._writerecordsv1(records) 360 self._writerecordsv1(records)
420 """Obtain the paths of driver-resolved files.""" 437 """Obtain the paths of driver-resolved files."""
421 438
422 for f, entry in self._state.items(): 439 for f, entry in self._state.items():
423 if entry[0] == 'd': 440 if entry[0] == 'd':
424 yield f 441 yield f
442
443 def extras(self, filename):
444 return self._stateextras.setdefault(filename, {})
425 445
426 def _resolve(self, preresolve, dfile, wctx, labels=None): 446 def _resolve(self, preresolve, dfile, wctx, labels=None):
427 """rerun merge process for file path `dfile`""" 447 """rerun merge process for file path `dfile`"""
428 if self[dfile] in 'rd': 448 if self[dfile] in 'rd':
429 return True, 0 449 return True, 0
460 lfile, fcd, fco, fca, 480 lfile, fcd, fco, fca,
461 labels=labels) 481 labels=labels)
462 if r is None: 482 if r is None:
463 # no real conflict 483 # no real conflict
464 del self._state[dfile] 484 del self._state[dfile]
485 self._stateextras.pop(dfile, None)
465 self._dirty = True 486 self._dirty = True
466 elif not r: 487 elif not r:
467 self.mark(dfile, 'r') 488 self.mark(dfile, 'r')
468 489
469 if complete: 490 if complete: