##// END OF EJS Templates
merge: use constants for merge state record types...
Gregory Szorc -
r37127:a532b2f5 default
parent child Browse files
Show More
@@ -47,6 +47,20 b' def _droponode(data):'
47 47 bits = bits[:-2] + bits[-1:]
48 48 return '\0'.join(bits)
49 49
50 # Merge state record types. See ``mergestate`` docs for more.
51 RECORD_LOCAL = b'L'
52 RECORD_OTHER = b'O'
53 RECORD_MERGED = b'F'
54 RECORD_CHANGEDELETE_CONFLICT = b'C'
55 RECORD_MERGE_DRIVER_MERGE = b'D'
56 RECORD_PATH_CONFLICT = b'P'
57 RECORD_MERGE_DRIVER_STATE = b'm'
58 RECORD_FILE_VALUES = b'f'
59 RECORD_LABELS = b'l'
60 RECORD_OVERRIDE = b't'
61 RECORD_UNSUPPORTED_MANDATORY = b'X'
62 RECORD_UNSUPPORTED_ADVISORY = b'x'
63
50 64 class mergestate(object):
51 65 '''track 3-way merge state of individual files
52 66
@@ -158,11 +172,11 b' class mergestate(object):'
158 172 unsupported = set()
159 173 records = self._readrecords()
160 174 for rtype, record in records:
161 if rtype == 'L':
175 if rtype == RECORD_LOCAL:
162 176 self._local = bin(record)
163 elif rtype == 'O':
177 elif rtype == RECORD_OTHER:
164 178 self._other = bin(record)
165 elif rtype == 'm':
179 elif rtype == RECORD_MERGE_DRIVER_STATE:
166 180 bits = record.split('\0', 1)
167 181 mdstate = bits[1]
168 182 if len(mdstate) != 1 or mdstate not in 'ums':
@@ -171,10 +185,11 b' class mergestate(object):'
171 185
172 186 self._readmergedriver = bits[0]
173 187 self._mdstate = mdstate
174 elif rtype in 'FDCP':
188 elif rtype in (RECORD_MERGED, RECORD_CHANGEDELETE_CONFLICT,
189 RECORD_PATH_CONFLICT, RECORD_MERGE_DRIVER_MERGE):
175 190 bits = record.split('\0')
176 191 self._state[bits[0]] = bits[1:]
177 elif rtype == 'f':
192 elif rtype == RECORD_FILE_VALUES:
178 193 filename, rawextras = record.split('\0', 1)
179 194 extraparts = rawextras.split('\0')
180 195 extras = {}
@@ -184,7 +199,7 b' class mergestate(object):'
184 199 i += 2
185 200
186 201 self._stateextras[filename] = extras
187 elif rtype == 'l':
202 elif rtype == RECORD_LABELS:
188 203 labels = record.split('\0', 2)
189 204 self._labels = [l for l in labels if len(l) > 0]
190 205 elif not rtype.islower():
@@ -218,12 +233,12 b' class mergestate(object):'
218 233 # we have to infer the "other" changeset of the merge
219 234 # we cannot do better than that with v1 of the format
220 235 mctx = self._repo[None].parents()[-1]
221 v1records.append(('O', mctx.hex()))
236 v1records.append((RECORD_OTHER, mctx.hex()))
222 237 # add place holder "other" file node information
223 238 # nobody is using it yet so we do no need to fetch the data
224 239 # if mctx was wrong `mctx[bits[-2]]` may fails.
225 240 for idx, r in enumerate(v1records):
226 if r[0] == 'F':
241 if r[0] == RECORD_MERGED:
227 242 bits = r[1].split('\0')
228 243 bits.insert(-2, '')
229 244 v1records[idx] = (r[0], '\0'.join(bits))
@@ -232,11 +247,11 b' class mergestate(object):'
232 247 def _v1v2match(self, v1records, v2records):
233 248 oldv2 = set() # old format version of v2 record
234 249 for rec in v2records:
235 if rec[0] == 'L':
250 if rec[0] == RECORD_LOCAL:
236 251 oldv2.add(rec)
237 elif rec[0] == 'F':
252 elif rec[0] == RECORD_MERGED:
238 253 # drop the onode data (not contained in v1)
239 oldv2.add(('F', _droponode(rec[1])))
254 oldv2.add((RECORD_MERGED, _droponode(rec[1])))
240 255 for rec in v1records:
241 256 if rec not in oldv2:
242 257 return False
@@ -256,9 +271,9 b' class mergestate(object):'
256 271 f = self._repo.vfs(self.statepathv1)
257 272 for i, l in enumerate(f):
258 273 if i == 0:
259 records.append(('L', l[:-1]))
274 records.append((RECORD_LOCAL, l[:-1]))
260 275 else:
261 records.append(('F', l[:-1]))
276 records.append((RECORD_MERGED, l[:-1]))
262 277 f.close()
263 278 except IOError as err:
264 279 if err.errno != errno.ENOENT:
@@ -296,7 +311,7 b' class mergestate(object):'
296 311 off += 4
297 312 record = data[off:(off + length)]
298 313 off += length
299 if rtype == 't':
314 if rtype == RECORD_OVERRIDE:
300 315 rtype, record = record[0:1], record[1:]
301 316 records.append((rtype, record))
302 317 f.close()
@@ -359,10 +374,10 b' class mergestate(object):'
359 374
360 375 def _makerecords(self):
361 376 records = []
362 records.append(('L', hex(self._local)))
363 records.append(('O', hex(self._other)))
377 records.append((RECORD_LOCAL, hex(self._local)))
378 records.append((RECORD_OTHER, hex(self._other)))
364 379 if self.mergedriver:
365 records.append(('m', '\0'.join([
380 records.append((RECORD_MERGE_DRIVER_STATE, '\0'.join([
366 381 self.mergedriver, self._mdstate])))
367 382 # Write out state items. In all cases, the value of the state map entry
368 383 # is written as the contents of the record. The record type depends on
@@ -372,27 +387,32 b' class mergestate(object):'
372 387 for filename, v in self._state.iteritems():
373 388 if v[0] == 'd':
374 389 # Driver-resolved merge. These are stored in 'D' records.
375 records.append(('D', '\0'.join([filename] + v)))
390 records.append((RECORD_MERGE_DRIVER_MERGE,
391 '\0'.join([filename] + v)))
376 392 elif v[0] in ('pu', 'pr'):
377 393 # Path conflicts. These are stored in 'P' records. The current
378 394 # resolution state ('pu' or 'pr') is stored within the record.
379 records.append(('P', '\0'.join([filename] + v)))
395 records.append((RECORD_PATH_CONFLICT,
396 '\0'.join([filename] + v)))
380 397 elif v[1] == nullhex or v[6] == nullhex:
381 398 # Change/Delete or Delete/Change conflicts. These are stored in
382 399 # 'C' records. v[1] is the local file, and is nullhex when the
383 400 # file is deleted locally ('dc'). v[6] is the remote file, and
384 401 # is nullhex when the file is deleted remotely ('cd').
385 records.append(('C', '\0'.join([filename] + v)))
402 records.append((RECORD_CHANGEDELETE_CONFLICT,
403 '\0'.join([filename] + v)))
386 404 else:
387 405 # Normal files. These are stored in 'F' records.
388 records.append(('F', '\0'.join([filename] + v)))
406 records.append((RECORD_MERGED,
407 '\0'.join([filename] + v)))
389 408 for filename, extras in sorted(self._stateextras.iteritems()):
390 409 rawextras = '\0'.join('%s\0%s' % (k, v) for k, v in
391 410 extras.iteritems())
392 records.append(('f', '%s\0%s' % (filename, rawextras)))
411 records.append((RECORD_FILE_VALUES,
412 '%s\0%s' % (filename, rawextras)))
393 413 if self._labels is not None:
394 414 labels = '\0'.join(self._labels)
395 records.append(('l', labels))
415 records.append((RECORD_LABELS, labels))
396 416 return records
397 417
398 418 def _writerecords(self, records):
@@ -405,10 +425,10 b' class mergestate(object):'
405 425 f = self._repo.vfs(self.statepathv1, 'wb')
406 426 irecords = iter(records)
407 427 lrecords = next(irecords)
408 assert lrecords[0] == 'L'
428 assert lrecords[0] == RECORD_LOCAL
409 429 f.write(hex(self._local) + '\n')
410 430 for rtype, data in irecords:
411 if rtype == 'F':
431 if rtype == RECORD_MERGED:
412 432 f.write('%s\n' % _droponode(data))
413 433 f.close()
414 434
@@ -417,12 +437,12 b' class mergestate(object):'
417 437
418 438 See the docstring for _readrecordsv2 for why we use 't'."""
419 439 # these are the records that all version 2 clients can read
420 whitelist = 'LOF'
440 allowlist = (RECORD_LOCAL, RECORD_OTHER, RECORD_MERGED)
421 441 f = self._repo.vfs(self.statepathv2, 'wb')
422 442 for key, data in records:
423 443 assert len(key) == 1
424 if key not in whitelist:
425 key, data = 't', '%s%s' % (key, data)
444 if key not in allowlist:
445 key, data = RECORD_OVERRIDE, '%s%s' % (key, data)
426 446 format = '>sI%is' % len(data)
427 447 f.write(_pack(format, key, len(data), data))
428 448 f.close()
General Comments 0
You need to be logged in to leave comments. Login now