Mercurial > public > mercurial-scm > hg
diff 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 |
line wrap: on
line diff
--- a/mercurial/merge.py Wed Nov 18 23:42:32 2015 -0800 +++ b/mercurial/merge.py Wed Nov 18 15:46:45 2015 -0800 @@ -62,6 +62,8 @@ (experimental) m: the external merge driver defined for this merge plus its run state (experimental) + X: unsupported mandatory record type (used in tests) + x: unsupported advisory record type (used in tests) Merge driver run states (experimental): u: driver-resolved files unmarked -- needs to be run next time we're about @@ -231,6 +233,13 @@ `type` is a single character, `length` is a 4 byte integer, and `content` is an arbitrary byte sequence of length `length`. + Mercurial versions prior to 3.7 have a bug where if there are + unsupported mandatory merge records, attempting to clear out the merge + state with hg update --clean or similar aborts. The 't' record type + works around that by writing out what those versions treat as an + advisory record, but later versions interpret as special: the first + character is the 'real' record type and everything onwards is the data. + Returns list of records [(TYPE, data), ...].""" records = [] try: @@ -245,6 +254,8 @@ off += 4 record = data[off:(off + length)] off += length + if rtype == 't': + rtype, record = record[0], record[1:] records.append((rtype, record)) f.close() except IOError as err: @@ -326,10 +337,16 @@ f.close() def _writerecordsv2(self, records): - """Write current state on disk in a version 2 file""" + """Write current state on disk in a version 2 file + + See the docstring for _readrecordsv2 for why we use 't'.""" + # these are the records that all version 2 clients can read + whitelist = 'LOF' f = self._repo.vfs(self.statepathv2, 'w') for key, data in records: assert len(key) == 1 + if key not in whitelist: + key, data = 't', '%s%s' % (key, data) format = '>sI%is' % len(data) f.write(_pack(format, key, len(data), data)) f.close()