Show More
@@ -0,0 +1,25 b'' | |||
|
1 | # Extension to write out fake unsupported records into the merge state | |
|
2 | # | |
|
3 | # | |
|
4 | ||
|
5 | from __future__ import absolute_import | |
|
6 | ||
|
7 | from mercurial import ( | |
|
8 | cmdutil, | |
|
9 | merge, | |
|
10 | ) | |
|
11 | ||
|
12 | cmdtable = {} | |
|
13 | command = cmdutil.command(cmdtable) | |
|
14 | ||
|
15 | @command('fakemergerecord', | |
|
16 | [('X', 'mandatory', None, 'add a fake mandatory record'), | |
|
17 | ('x', 'advisory', None, 'add a fake advisory record')], '') | |
|
18 | def fakemergerecord(ui, repo, *pats, **opts): | |
|
19 | ms = merge.mergestate.read(repo) | |
|
20 | records = ms._makerecords() | |
|
21 | if opts.get('mandatory'): | |
|
22 | records.append(('X', 'mandatory record')) | |
|
23 | if opts.get('advisory'): | |
|
24 | records.append(('x', 'advisory record')) | |
|
25 | ms._writerecords(records) |
@@ -62,6 +62,8 b' class mergestate(object):' | |||
|
62 | 62 | (experimental) |
|
63 | 63 | m: the external merge driver defined for this merge plus its run state |
|
64 | 64 | (experimental) |
|
65 | X: unsupported mandatory record type (used in tests) | |
|
66 | x: unsupported advisory record type (used in tests) | |
|
65 | 67 | |
|
66 | 68 | Merge driver run states (experimental): |
|
67 | 69 | u: driver-resolved files unmarked -- needs to be run next time we're about |
@@ -231,6 +233,13 b' class mergestate(object):' | |||
|
231 | 233 | `type` is a single character, `length` is a 4 byte integer, and |
|
232 | 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 | 243 | Returns list of records [(TYPE, data), ...].""" |
|
235 | 244 | records = [] |
|
236 | 245 | try: |
@@ -245,6 +254,8 b' class mergestate(object):' | |||
|
245 | 254 | off += 4 |
|
246 | 255 | record = data[off:(off + length)] |
|
247 | 256 | off += length |
|
257 | if rtype == 't': | |
|
258 | rtype, record = record[0], record[1:] | |
|
248 | 259 | records.append((rtype, record)) |
|
249 | 260 | f.close() |
|
250 | 261 | except IOError as err: |
@@ -326,10 +337,16 b' class mergestate(object):' | |||
|
326 | 337 | f.close() |
|
327 | 338 | |
|
328 | 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 | 345 | f = self._repo.vfs(self.statepathv2, 'w') |
|
331 | 346 | for key, data in records: |
|
332 | 347 | assert len(key) == 1 |
|
348 | if key not in whitelist: | |
|
349 | key, data = 't', '%s%s' % (key, data) | |
|
333 | 350 | format = '>sI%is' % len(data) |
|
334 | 351 | f.write(_pack(format, key, len(data), data)) |
|
335 | 352 | f.close() |
@@ -75,10 +75,45 b' edit the history' | |||
|
75 | 75 | warning: conflicts while merging e! (edit, then use 'hg resolve --mark') |
|
76 | 76 | Fix up the change and run hg histedit --continue |
|
77 | 77 | |
|
78 | insert unsupported advisory merge record | |
|
79 | $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -x | |
|
80 | $ hg debugmergestate | |
|
81 | * version 2 records | |
|
82 | local: 8f7551c7e4a2f2efe0bc8c741baf7f227d65d758 | |
|
83 | other: e860deea161a2f77de56603b340ebbb4536308ae | |
|
84 | unrecognized entry: x advisory record | |
|
85 | file: e (record type "F", state "u", hash 58e6b3a414a1e090dfc6029add0f3555ccba127f) | |
|
86 | local path: e (flags "") | |
|
87 | ancestor path: e (node 0000000000000000000000000000000000000000) | |
|
88 | other path: e (node 6b67ccefd5ce6de77e7ead4f5292843a0255329f) | |
|
89 | $ hg resolve -l | |
|
90 | U e | |
|
78 | 91 | |
|
79 | abort the edit | |
|
92 | insert unsupported mandatory merge record | |
|
93 | $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -X | |
|
94 | $ hg debugmergestate | |
|
95 | * version 2 records | |
|
96 | local: 8f7551c7e4a2f2efe0bc8c741baf7f227d65d758 | |
|
97 | other: e860deea161a2f77de56603b340ebbb4536308ae | |
|
98 | file: e (record type "F", state "u", hash 58e6b3a414a1e090dfc6029add0f3555ccba127f) | |
|
99 | local path: e (flags "") | |
|
100 | ancestor path: e (node 0000000000000000000000000000000000000000) | |
|
101 | other path: e (node 6b67ccefd5ce6de77e7ead4f5292843a0255329f) | |
|
102 | unrecognized entry: X mandatory record | |
|
103 | $ hg resolve -l | |
|
104 | abort: unsupported merge state records: X | |
|
105 | (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) | |
|
106 | [255] | |
|
107 | $ hg resolve -ma | |
|
108 | abort: unsupported merge state records: X | |
|
109 | (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) | |
|
110 | [255] | |
|
111 | ||
|
112 | abort the edit (should clear out merge state) | |
|
80 | 113 | $ hg histedit --abort 2>&1 | fixbundle |
|
81 | 114 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
115 | $ hg debugmergestate | |
|
116 | no merge state found | |
|
82 | 117 | |
|
83 | 118 | log after abort |
|
84 | 119 | $ hg resolve -l |
@@ -68,11 +68,49 b' Conflicting rebase:' | |||
|
68 | 68 | unresolved conflicts (see hg resolve, then hg rebase --continue) |
|
69 | 69 | [1] |
|
70 | 70 | |
|
71 | Abort: | |
|
71 | Insert unsupported advisory merge record: | |
|
72 | ||
|
73 | $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -x | |
|
74 | $ hg debugmergestate | |
|
75 | * version 2 records | |
|
76 | local: 3e046f2ecedb793b97ed32108086edd1a162f8bc | |
|
77 | other: 46f0b057b5c061d276b91491c22151f78698abd2 | |
|
78 | unrecognized entry: x advisory record | |
|
79 | file: common (record type "F", state "u", hash 94c8c21d08740f5da9eaa38d1f175c592692f0d1) | |
|
80 | local path: common (flags "") | |
|
81 | ancestor path: common (node de0a666fdd9c1a0b0698b90d85064d8bd34f74b6) | |
|
82 | other path: common (node 2f6411de53677f6f1048fef5bf888d67a342e0a5) | |
|
83 | $ hg resolve -l | |
|
84 | U common | |
|
85 | ||
|
86 | Insert unsupported mandatory merge record: | |
|
87 | ||
|
88 | $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -X | |
|
89 | $ hg debugmergestate | |
|
90 | * version 2 records | |
|
91 | local: 3e046f2ecedb793b97ed32108086edd1a162f8bc | |
|
92 | other: 46f0b057b5c061d276b91491c22151f78698abd2 | |
|
93 | file: common (record type "F", state "u", hash 94c8c21d08740f5da9eaa38d1f175c592692f0d1) | |
|
94 | local path: common (flags "") | |
|
95 | ancestor path: common (node de0a666fdd9c1a0b0698b90d85064d8bd34f74b6) | |
|
96 | other path: common (node 2f6411de53677f6f1048fef5bf888d67a342e0a5) | |
|
97 | unrecognized entry: X mandatory record | |
|
98 | $ hg resolve -l | |
|
99 | abort: unsupported merge state records: X | |
|
100 | (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) | |
|
101 | [255] | |
|
102 | $ hg resolve -ma | |
|
103 | abort: unsupported merge state records: X | |
|
104 | (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) | |
|
105 | [255] | |
|
106 | ||
|
107 | Abort (should clear out unsupported merge state): | |
|
72 | 108 | |
|
73 | 109 | $ hg rebase --abort |
|
74 | 110 | saved backup bundle to $TESTTMP/a/.hg/strip-backup/3e046f2ecedb-6beef7d5-backup.hg (glob) |
|
75 | 111 | rebase aborted |
|
112 | $ hg debugmergestate | |
|
113 | no merge state found | |
|
76 | 114 | |
|
77 | 115 | $ hg tglog |
|
78 | 116 | @ 4:draft 'L2' |
@@ -249,9 +249,69 b" resolve <file> should do nothing if 'fil" | |||
|
249 | 249 | $ cat file1 |
|
250 | 250 | resolved |
|
251 | 251 | |
|
252 | insert unsupported advisory merge record | |
|
253 | ||
|
254 | $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -x | |
|
255 | $ hg debugmergestate | |
|
256 | * version 2 records | |
|
257 | local: 57653b9f834a4493f7240b0681efcb9ae7cab745 | |
|
258 | other: dc77451844e37f03f5c559e3b8529b2b48d381d1 | |
|
259 | unrecognized entry: x advisory record | |
|
260 | file: file1 (record type "F", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) | |
|
261 | local path: file1 (flags "") | |
|
262 | ancestor path: file1 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) | |
|
263 | other path: file1 (node 6f4310b00b9a147241b071a60c28a650827fb03d) | |
|
264 | file: file2 (record type "F", state "u", hash cb99b709a1978bd205ab9dfd4c5aaa1fc91c7523) | |
|
265 | local path: file2 (flags "") | |
|
266 | ancestor path: file2 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) | |
|
267 | other path: file2 (node 6f4310b00b9a147241b071a60c28a650827fb03d) | |
|
268 | $ hg resolve -l | |
|
269 | R file1 | |
|
270 | U file2 | |
|
271 | ||
|
272 | insert unsupported mandatory merge record | |
|
273 | ||
|
274 | $ hg --config extensions.fakemergerecord=$TESTDIR/fakemergerecord.py fakemergerecord -X | |
|
275 | $ hg debugmergestate | |
|
276 | * version 2 records | |
|
277 | local: 57653b9f834a4493f7240b0681efcb9ae7cab745 | |
|
278 | other: dc77451844e37f03f5c559e3b8529b2b48d381d1 | |
|
279 | file: file1 (record type "F", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390) | |
|
280 | local path: file1 (flags "") | |
|
281 | ancestor path: file1 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) | |
|
282 | other path: file1 (node 6f4310b00b9a147241b071a60c28a650827fb03d) | |
|
283 | file: file2 (record type "F", state "u", hash cb99b709a1978bd205ab9dfd4c5aaa1fc91c7523) | |
|
284 | local path: file2 (flags "") | |
|
285 | ancestor path: file2 (node 2ed2a3912a0b24502043eae84ee4b279c18b90dd) | |
|
286 | other path: file2 (node 6f4310b00b9a147241b071a60c28a650827fb03d) | |
|
287 | unrecognized entry: X mandatory record | |
|
288 | $ hg resolve -l | |
|
289 | abort: unsupported merge state records: X | |
|
290 | (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) | |
|
291 | [255] | |
|
292 | $ hg resolve -ma | |
|
293 | abort: unsupported merge state records: X | |
|
294 | (see https://mercurial-scm.org/wiki/MergeStateRecords for more information) | |
|
295 | [255] | |
|
296 | $ hg summary | |
|
297 | parent: 2:57653b9f834a | |
|
298 | append baz to files | |
|
299 | parent: 1:dc77451844e3 | |
|
300 | append bar to files | |
|
301 | branch: default | |
|
302 | warning: merge state has unsupported record types: X | |
|
303 | commit: 2 modified, 2 unknown (merge) | |
|
304 | update: 2 new changesets (update) | |
|
305 | phases: 5 draft | |
|
306 | ||
|
307 | update --clean shouldn't abort on unsupported records | |
|
308 | ||
|
309 | $ hg up -qC 1 | |
|
310 | $ hg debugmergestate | |
|
311 | no merge state found | |
|
312 | ||
|
252 | 313 | test crashed merge with empty mergestate |
|
253 | 314 | |
|
254 | $ hg up -qC 1 | |
|
255 | 315 | $ mkdir .hg/merge |
|
256 | 316 | $ touch .hg/merge/state |
|
257 | 317 |
General Comments 0
You need to be logged in to leave comments.
Login now