comparison mercurial/merge.py @ 27027:a01ecbcfaf84

mergestate: handle additional record types specially This works around a bug in older Mercurial versions' handling of the v2 merge state. We also add a bunch of tests that make sure that (1) we correctly abort when the merge state has an unsupported record type (2) aborting the merge, rebase or histedit continues to work and clears out the merge state.
author Siddharth Agarwal <sid0@fb.com>
date Wed, 18 Nov 2015 15:46:45 -0800
parents 35102876d648
children 8be0af32e513
comparison
equal deleted inserted replaced
27026:c93b44b79359 27027:a01ecbcfaf84
60 F: a file to be merged entry 60 F: a file to be merged entry
61 D: a file that the external merge driver will merge internally 61 D: a file that the external merge driver will merge internally
62 (experimental) 62 (experimental)
63 m: the external merge driver defined for this merge plus its run state 63 m: the external merge driver defined for this merge plus its run state
64 (experimental) 64 (experimental)
65 X: unsupported mandatory record type (used in tests)
66 x: unsupported advisory record type (used in tests)
65 67
66 Merge driver run states (experimental): 68 Merge driver run states (experimental):
67 u: driver-resolved files unmarked -- needs to be run next time we're about 69 u: driver-resolved files unmarked -- needs to be run next time we're about
68 to resolve or commit 70 to resolve or commit
69 m: driver-resolved files marked -- only needs to be run before commit 71 m: driver-resolved files marked -- only needs to be run before commit
229 [type][length][content] 231 [type][length][content]
230 232
231 `type` is a single character, `length` is a 4 byte integer, and 233 `type` is a single character, `length` is a 4 byte integer, and
232 `content` is an arbitrary byte sequence of length `length`. 234 `content` is an arbitrary byte sequence of length `length`.
233 235
236 Mercurial versions prior to 3.7 have a bug where if there are
237 unsupported mandatory merge records, attempting to clear out the merge
238 state with hg update --clean or similar aborts. The 't' record type
239 works around that by writing out what those versions treat as an
240 advisory record, but later versions interpret as special: the first
241 character is the 'real' record type and everything onwards is the data.
242
234 Returns list of records [(TYPE, data), ...].""" 243 Returns list of records [(TYPE, data), ...]."""
235 records = [] 244 records = []
236 try: 245 try:
237 f = self._repo.vfs(self.statepathv2) 246 f = self._repo.vfs(self.statepathv2)
238 data = f.read() 247 data = f.read()
243 off += 1 252 off += 1
244 length = _unpack('>I', data[off:(off + 4)])[0] 253 length = _unpack('>I', data[off:(off + 4)])[0]
245 off += 4 254 off += 4
246 record = data[off:(off + length)] 255 record = data[off:(off + length)]
247 off += length 256 off += length
257 if rtype == 't':
258 rtype, record = record[0], record[1:]
248 records.append((rtype, record)) 259 records.append((rtype, record))
249 f.close() 260 f.close()
250 except IOError as err: 261 except IOError as err:
251 if err.errno != errno.ENOENT: 262 if err.errno != errno.ENOENT:
252 raise 263 raise
324 if rtype == 'F': 335 if rtype == 'F':
325 f.write('%s\n' % _droponode(data)) 336 f.write('%s\n' % _droponode(data))
326 f.close() 337 f.close()
327 338
328 def _writerecordsv2(self, records): 339 def _writerecordsv2(self, records):
329 """Write current state on disk in a version 2 file""" 340 """Write current state on disk in a version 2 file
341
342 See the docstring for _readrecordsv2 for why we use 't'."""
343 # these are the records that all version 2 clients can read
344 whitelist = 'LOF'
330 f = self._repo.vfs(self.statepathv2, 'w') 345 f = self._repo.vfs(self.statepathv2, 'w')
331 for key, data in records: 346 for key, data in records:
332 assert len(key) == 1 347 assert len(key) == 1
348 if key not in whitelist:
349 key, data = 't', '%s%s' % (key, data)
333 format = '>sI%is' % len(data) 350 format = '>sI%is' % len(data)
334 f.write(_pack(format, key, len(data), data)) 351 f.write(_pack(format, key, len(data), data))
335 f.close() 352 f.close()
336 353
337 def add(self, fcl, fco, fca, fd): 354 def add(self, fcl, fco, fca, fd):