##// END OF EJS Templates
copies: distinguish between merged and touched files during upgrade...
marmoute -
r47571:433cef8f default
parent child Browse files
Show More
@@ -1,958 +1,966 b''
1 1 # coding: utf-8
2 2 # metadata.py -- code related to various metadata computation and access.
3 3 #
4 4 # Copyright 2019 Google, Inc <martinvonz@google.com>
5 5 # Copyright 2020 Pierre-Yves David <pierre-yves.david@octobus.net>
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9 from __future__ import absolute_import, print_function
10 10
11 11 import multiprocessing
12 12 import struct
13 13
14 14 from .node import (
15 15 nullid,
16 16 nullrev,
17 17 )
18 18 from . import (
19 19 error,
20 20 pycompat,
21 21 requirements as requirementsmod,
22 22 util,
23 23 )
24 24
25 25 from .revlogutils import (
26 26 flagutil as sidedataflag,
27 27 sidedata as sidedatamod,
28 28 )
29 29
30 30
31 31 class ChangingFiles(object):
32 32 """A class recording the changes made to files by a changeset
33 33
34 34 Actions performed on files are gathered into 3 sets:
35 35
36 36 - added: files actively added in the changeset.
37 37 - merged: files whose history got merged
38 38 - removed: files removed in the revision
39 39 - salvaged: files that might have been deleted by a merge but were not
40 40 - touched: files affected by the merge
41 41
42 42 and copies information is held by 2 mappings
43 43
44 44 - copied_from_p1: {"<new-name>": "<source-name-in-p1>"} mapping for copies
45 45 - copied_from_p2: {"<new-name>": "<source-name-in-p2>"} mapping for copies
46 46
47 47 See their inline help for details.
48 48 """
49 49
50 50 def __init__(
51 51 self,
52 52 touched=None,
53 53 added=None,
54 54 removed=None,
55 55 merged=None,
56 56 salvaged=None,
57 57 p1_copies=None,
58 58 p2_copies=None,
59 59 ):
60 60 self._added = set(() if added is None else added)
61 61 self._merged = set(() if merged is None else merged)
62 62 self._removed = set(() if removed is None else removed)
63 63 self._touched = set(() if touched is None else touched)
64 64 self._salvaged = set(() if salvaged is None else salvaged)
65 65 self._touched.update(self._added)
66 66 self._touched.update(self._merged)
67 67 self._touched.update(self._removed)
68 68 self._p1_copies = dict(() if p1_copies is None else p1_copies)
69 69 self._p2_copies = dict(() if p2_copies is None else p2_copies)
70 70
71 71 def __eq__(self, other):
72 72 return (
73 73 self.added == other.added
74 74 and self.merged == other.merged
75 75 and self.removed == other.removed
76 76 and self.salvaged == other.salvaged
77 77 and self.touched == other.touched
78 78 and self.copied_from_p1 == other.copied_from_p1
79 79 and self.copied_from_p2 == other.copied_from_p2
80 80 )
81 81
82 82 @property
83 83 def has_copies_info(self):
84 84 return bool(
85 85 self.removed
86 86 or self.merged
87 87 or self.salvaged
88 88 or self.copied_from_p1
89 89 or self.copied_from_p2
90 90 )
91 91
92 92 @util.propertycache
93 93 def added(self):
94 94 """files actively added in the changeset
95 95
96 96 Any file present in that revision that was absent in all the changeset's
97 97 parents.
98 98
99 99 In case of merge, this means a file absent in one of the parents but
100 100 existing in the other will *not* be contained in this set. (They were
101 101 added by an ancestor)
102 102 """
103 103 return frozenset(self._added)
104 104
105 105 def mark_added(self, filename):
106 106 if 'added' in vars(self):
107 107 del self.added
108 108 self._added.add(filename)
109 109 self.mark_touched(filename)
110 110
111 111 def update_added(self, filenames):
112 112 for f in filenames:
113 113 self.mark_added(f)
114 114
115 115 @util.propertycache
116 116 def merged(self):
117 117 """files actively merged during a merge
118 118
119 119 Any modified files which had modification on both size that needed merging.
120 120
121 121 In this case a new filenode was created and it has two parents.
122 122 """
123 123 return frozenset(self._merged)
124 124
125 125 def mark_merged(self, filename):
126 126 if 'merged' in vars(self):
127 127 del self.merged
128 128 self._merged.add(filename)
129 129 self.mark_touched(filename)
130 130
131 131 def update_merged(self, filenames):
132 132 for f in filenames:
133 133 self.mark_merged(f)
134 134
135 135 @util.propertycache
136 136 def removed(self):
137 137 """files actively removed by the changeset
138 138
139 139 In case of merge this will only contain the set of files removing "new"
140 140 content. For any file absent in the current changeset:
141 141
142 142 a) If the file exists in both parents, it is clearly "actively" removed
143 143 by this changeset.
144 144
145 145 b) If a file exists in only one parent and in none of the common
146 146 ancestors, then the file was newly added in one of the merged branches
147 147 and then got "actively" removed.
148 148
149 149 c) If a file exists in only one parent and at least one of the common
150 150 ancestors using the same filenode, then the file was unchanged on one
151 151 side and deleted on the other side. The merge "passively" propagated
152 152 that deletion, but didn't "actively" remove the file. In this case the
153 153 file is *not* included in the `removed` set.
154 154
155 155 d) If a file exists in only one parent and at least one of the common
156 156 ancestors using a different filenode, then the file was changed on one
157 157 side and removed on the other side. The merge process "actively"
158 158 decided to drop the new change and delete the file. Unlike in the
159 159 previous case, (c), the file included in the `removed` set.
160 160
161 161 Summary table for merge:
162 162
163 163 case | exists in parents | exists in gca || removed
164 164 (a) | both | * || yes
165 165 (b) | one | none || yes
166 166 (c) | one | same filenode || no
167 167 (d) | one | new filenode || yes
168 168 """
169 169 return frozenset(self._removed)
170 170
171 171 def mark_removed(self, filename):
172 172 if 'removed' in vars(self):
173 173 del self.removed
174 174 self._removed.add(filename)
175 175 self.mark_touched(filename)
176 176
177 177 def update_removed(self, filenames):
178 178 for f in filenames:
179 179 self.mark_removed(f)
180 180
181 181 @util.propertycache
182 182 def salvaged(self):
183 183 """files that might have been deleted by a merge, but still exists.
184 184
185 185 During a merge, the manifest merging might select some files for
186 186 removal, or for a removed/changed conflict. If at commit time the file
187 187 still exists, its removal was "reverted" and the file is "salvaged"
188 188 """
189 189 return frozenset(self._salvaged)
190 190
191 191 def mark_salvaged(self, filename):
192 192 if "salvaged" in vars(self):
193 193 del self.salvaged
194 194 self._salvaged.add(filename)
195 195 self.mark_touched(filename)
196 196
197 197 def update_salvaged(self, filenames):
198 198 for f in filenames:
199 199 self.mark_salvaged(f)
200 200
201 201 @util.propertycache
202 202 def touched(self):
203 203 """files either actively modified, added or removed"""
204 204 return frozenset(self._touched)
205 205
206 206 def mark_touched(self, filename):
207 207 if 'touched' in vars(self):
208 208 del self.touched
209 209 self._touched.add(filename)
210 210
211 211 def update_touched(self, filenames):
212 212 for f in filenames:
213 213 self.mark_touched(f)
214 214
215 215 @util.propertycache
216 216 def copied_from_p1(self):
217 217 return self._p1_copies.copy()
218 218
219 219 def mark_copied_from_p1(self, source, dest):
220 220 if 'copied_from_p1' in vars(self):
221 221 del self.copied_from_p1
222 222 self._p1_copies[dest] = source
223 223
224 224 def update_copies_from_p1(self, copies):
225 225 for dest, source in copies.items():
226 226 self.mark_copied_from_p1(source, dest)
227 227
228 228 @util.propertycache
229 229 def copied_from_p2(self):
230 230 return self._p2_copies.copy()
231 231
232 232 def mark_copied_from_p2(self, source, dest):
233 233 if 'copied_from_p2' in vars(self):
234 234 del self.copied_from_p2
235 235 self._p2_copies[dest] = source
236 236
237 237 def update_copies_from_p2(self, copies):
238 238 for dest, source in copies.items():
239 239 self.mark_copied_from_p2(source, dest)
240 240
241 241
242 242 def compute_all_files_changes(ctx):
243 243 """compute the files changed by a revision"""
244 244 p1 = ctx.p1()
245 245 p2 = ctx.p2()
246 246 if p1.rev() == nullrev and p2.rev() == nullrev:
247 247 return _process_root(ctx)
248 248 elif p1.rev() != nullrev and p2.rev() == nullrev:
249 249 return _process_linear(p1, ctx)
250 250 elif p1.rev() == nullrev and p2.rev() != nullrev:
251 251 # In the wild, one can encounter changeset where p1 is null but p2 is not
252 252 return _process_linear(p1, ctx, parent=2)
253 253 elif p1.rev() == p2.rev():
254 254 # In the wild, one can encounter such "non-merge"
255 255 return _process_linear(p1, ctx)
256 256 else:
257 257 return _process_merge(p1, p2, ctx)
258 258
259 259
260 260 def _process_root(ctx):
261 261 """compute the appropriate changed files for a changeset with no parents"""
262 262 # Simple, there was nothing before it, so everything is added.
263 263 md = ChangingFiles()
264 264 manifest = ctx.manifest()
265 265 for filename in manifest:
266 266 md.mark_added(filename)
267 267 return md
268 268
269 269
270 270 def _process_linear(parent_ctx, children_ctx, parent=1):
271 271 """compute the appropriate changed files for a changeset with a single parent"""
272 272 md = ChangingFiles()
273 273 parent_manifest = parent_ctx.manifest()
274 274 children_manifest = children_ctx.manifest()
275 275
276 276 copies_candidate = []
277 277
278 278 for filename, d in parent_manifest.diff(children_manifest).items():
279 279 if d[1][0] is None:
280 280 # no filenode for the "new" value, file is absent
281 281 md.mark_removed(filename)
282 282 else:
283 283 copies_candidate.append(filename)
284 284 if d[0][0] is None:
285 285 # not filenode for the "old" value file was absent
286 286 md.mark_added(filename)
287 287 else:
288 288 # filenode for both "old" and "new"
289 289 md.mark_touched(filename)
290 290
291 291 if parent == 1:
292 292 copied = md.mark_copied_from_p1
293 293 elif parent == 2:
294 294 copied = md.mark_copied_from_p2
295 295 else:
296 296 assert False, "bad parent value %d" % parent
297 297
298 298 for filename in copies_candidate:
299 299 copy_info = children_ctx[filename].renamed()
300 300 if copy_info:
301 301 source, srcnode = copy_info
302 302 copied(source, filename)
303 303
304 304 return md
305 305
306 306
307 307 def _process_merge(p1_ctx, p2_ctx, ctx):
308 308 """compute the appropriate changed files for a changeset with two parents
309 309
310 310 This is a more advance case. The information we need to record is summarise
311 311 in the following table:
312 312
313 313 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
314 314 β”‚ diff β•² diff β”‚ ΓΈ β”‚ (Some, None) β”‚ (None, Some) β”‚ (Some, Some) β”‚
315 315 β”‚ p2 β•² p1 β”‚ β”‚ β”‚ β”‚ β”‚
316 316 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
317 317 β”‚ β”‚ β”‚πŸ„± No Changes β”‚πŸ„³ No Changes β”‚ β”‚
318 318 β”‚ ΓΈ β”‚πŸ„° No Changes β”‚ OR β”‚ OR β”‚πŸ„΅ No Changes β”‚
319 319 β”‚ β”‚ β”‚πŸ„² Deleted[1] β”‚πŸ„΄ Salvaged[2]β”‚ [3] β”‚
320 320 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
321 321 β”‚ β”‚πŸ„Ά No Changes β”‚ β”‚ β”‚ β”‚
322 322 β”‚ (Some, None) β”‚ OR β”‚πŸ„» Deleted β”‚ ΓΈ β”‚ ΓΈ β”‚
323 323 β”‚ β”‚πŸ„· Deleted[1] β”‚ β”‚ β”‚ β”‚
324 324 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
325 325 β”‚ β”‚πŸ„Έ No Changes β”‚ β”‚ β”‚ πŸ„½ Touched β”‚
326 326 β”‚ (None, Some) β”‚ OR β”‚ ΓΈ β”‚πŸ„Ό Added β”‚OR πŸ…€ Salvaged β”‚
327 327 β”‚ β”‚πŸ„Ή Salvaged[2]β”‚ β”‚ (copied?) β”‚ (copied?) β”‚
328 328 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
329 β”‚ β”‚ β”‚ β”‚ πŸ„Ύ Touched β”‚ β”‚
330 β”‚ (Some, Some) β”‚πŸ„Ί No Changes β”‚ ΓΈ β”‚OR πŸ… Salvaged β”‚πŸ„Ώ Merged β”‚
329 β”‚ β”‚ β”‚ β”‚ πŸ„Ύ Touched β”‚ πŸ„Ώ Merged β”‚
330 β”‚ (Some, Some) β”‚πŸ„Ί No Changes β”‚ ΓΈ β”‚OR πŸ… Salvaged β”‚OR πŸ…‚ Touched β”‚
331 331 β”‚ β”‚ [3] β”‚ β”‚ (copied?) β”‚ (copied?) β”‚
332 332 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
333 333
334 334 Special case [1]:
335 335
336 336 The situation is:
337 337 - parent-A: file exists,
338 338 - parent-B: no file,
339 339 - working-copy: no file.
340 340
341 341 Detecting a "deletion" will depend on the presence of actual change on
342 342 the "parent-A" branch:
343 343
344 344 Subcase πŸ„± or πŸ„Ά : if the state of the file in "parent-A" is unchanged
345 345 compared to the merge ancestors, then parent-A branch left the file
346 346 untouched while parent-B deleted it. We simply apply the change from
347 347 "parent-B" branch the file was automatically dropped.
348 348 The result is:
349 349 - file is not recorded as touched by the merge.
350 350
351 351 Subcase πŸ„² or πŸ„· : otherwise, the change from parent-A branch were explicitly dropped and
352 352 the file was "deleted again". From a user perspective, the message
353 353 about "locally changed" while "remotely deleted" (or the other way
354 354 around) was issued and the user chose to deleted the file.
355 355 The result:
356 356 - file is recorded as touched by the merge.
357 357
358 358
359 359 Special case [2]:
360 360
361 361 The situation is:
362 362 - parent-A: no file,
363 363 - parent-B: file,
364 364 - working-copy: file (same content as parent-B).
365 365
366 366 There are three subcases depending on the ancestors contents:
367 367
368 368 - A) the file is missing in all ancestors,
369 369 - B) at least one ancestor has the file with filenode β‰  from parent-B,
370 370 - C) all ancestors use the same filenode as parent-B,
371 371
372 372 Subcase (A) is the simpler, nothing happend on parent-A side while
373 373 parent-B added it.
374 374
375 375 The result:
376 376 - the file is not marked as touched by the merge.
377 377
378 378 Subcase (B) is the counter part of "Special case [1]", the file was
379 379 modified on parent-B side, while parent-A side deleted it. However this
380 380 time, the conflict was solved by keeping the file (and its
381 381 modification). We consider the file as "salvaged".
382 382
383 383 The result:
384 384 - the file is marked as "salvaged" by the merge.
385 385
386 386 Subcase (C) is subtle variation of the case above. In this case, the
387 387 file in unchanged on the parent-B side and actively removed on the
388 388 parent-A side. So the merge machinery correctly decide it should be
389 389 removed. However, the file was explicitly restored to its parent-B
390 390 content before the merge was commited. The file is be marked
391 391 as salvaged too. From the merge result perspective, this is similar to
392 392 Subcase (B), however from the merge resolution perspective they differ
393 393 since in (C), there was some conflict not obvious solution to the
394 394 merge (That got reversed)
395 395
396 396 Special case [3]:
397 397
398 398 The situation is:
399 399 - parent-A: file,
400 400 - parent-B: file (different filenode as parent-A),
401 401 - working-copy: file (same filenode as parent-B).
402 402
403 403 This case is in theory much simple, for this to happens, this mean the
404 404 filenode in parent-A is purely replacing the one in parent-B (either a
405 405 descendant, or a full new file history, see changeset). So the merge
406 406 introduce no changes, and the file is not affected by the merge...
407 407
408 408 However, in the wild it is possible to find commit with the above is not
409 409 True. For example repository have some commit where the *new* node is an
410 410 ancestor of the node in parent-A, or where parent-A and parent-B are two
411 411 branches of the same file history, yet not merge-filenode were created
412 412 (while the "merge" should have led to a "modification").
413 413
414 414 Detecting such cases (and not recording the file as modified) would be a
415 415 nice bonus. However do not any of this yet.
416 416 """
417 417
418 repo = ctx.repo()
418 419 md = ChangingFiles()
419 420
420 421 m = ctx.manifest()
421 422 p1m = p1_ctx.manifest()
422 423 p2m = p2_ctx.manifest()
423 424 diff_p1 = p1m.diff(m)
424 425 diff_p2 = p2m.diff(m)
425 426
426 427 cahs = ctx.repo().changelog.commonancestorsheads(
427 428 p1_ctx.node(), p2_ctx.node()
428 429 )
429 430 if not cahs:
430 431 cahs = [nullrev]
431 432 mas = [ctx.repo()[r].manifest() for r in cahs]
432 433
433 434 copy_candidates = []
434 435
435 436 # Dealing with case πŸ„° happens automatically. Since there are no entry in
436 437 # d1 nor d2, we won't iterate on it ever.
437 438
438 439 # Iteration over d1 content will deal with all cases, but the one in the
439 440 # first column of the table.
440 441 for filename, d1 in diff_p1.items():
441 442
442 443 d2 = diff_p2.pop(filename, None)
443 444
444 445 if d2 is None:
445 446 # this deal with the first line of the table.
446 447 _process_other_unchanged(md, mas, filename, d1)
447 448 else:
448 449
449 450 if d1[0][0] is None and d2[0][0] is None:
450 451 # case πŸ„Ό β€” both deleted the file.
451 452 md.mark_added(filename)
452 453 copy_candidates.append(filename)
453 454 elif d1[1][0] is None and d2[1][0] is None:
454 455 # case πŸ„» β€” both deleted the file.
455 456 md.mark_removed(filename)
456 457 elif d1[1][0] is not None and d2[1][0] is not None:
457 458 if d1[0][0] is None or d2[0][0] is None:
458 459 if any(_find(ma, filename) is not None for ma in mas):
459 460 # case πŸ…€ or πŸ…
460 461 md.mark_salvaged(filename)
461 462 else:
462 463 # case πŸ„½ πŸ„Ύ : touched
463 464 md.mark_touched(filename)
464 465 else:
465 # case πŸ„Ώ : merged
466 md.mark_merged(filename)
466 fctx = repo.filectx(filename, fileid=d1[1][0])
467 if fctx.p2().rev() == nullrev:
468 # case πŸ…‚
469 # lets assume we can trust the file history. If the
470 # filenode is not a merge, the file was not merged.
471 md.mark_touched(filename)
472 else:
473 # case πŸ„Ώ
474 md.mark_merged(filename)
467 475 copy_candidates.append(filename)
468 476 else:
469 477 # Impossible case, the post-merge file status cannot be None on
470 478 # one side and Something on the other side.
471 479 assert False, "unreachable"
472 480
473 481 # Iteration over remaining d2 content deal with the first column of the
474 482 # table.
475 483 for filename, d2 in diff_p2.items():
476 484 _process_other_unchanged(md, mas, filename, d2)
477 485
478 486 for filename in copy_candidates:
479 487 copy_info = ctx[filename].renamed()
480 488 if copy_info:
481 489 source, srcnode = copy_info
482 490 if source in p1_ctx and p1_ctx[source].filenode() == srcnode:
483 491 md.mark_copied_from_p1(source, filename)
484 492 elif source in p2_ctx and p2_ctx[source].filenode() == srcnode:
485 493 md.mark_copied_from_p2(source, filename)
486 494 return md
487 495
488 496
489 497 def _find(manifest, filename):
490 498 """return the associate filenode or None"""
491 499 if filename not in manifest:
492 500 return None
493 501 return manifest.find(filename)[0]
494 502
495 503
496 504 def _process_other_unchanged(md, mas, filename, diff):
497 505 source_node = diff[0][0]
498 506 target_node = diff[1][0]
499 507
500 508 if source_node is not None and target_node is None:
501 509 if any(not _find(ma, filename) == source_node for ma in mas):
502 510 # case πŸ„² of πŸ„·
503 511 md.mark_removed(filename)
504 512 # else, we have case πŸ„± or πŸ„Ά : no change need to be recorded
505 513 elif source_node is None and target_node is not None:
506 514 if any(_find(ma, filename) is not None for ma in mas):
507 515 # case πŸ„΄ or πŸ„Ή
508 516 md.mark_salvaged(filename)
509 517 # else, we have case πŸ„³ or πŸ„Έ : simple merge without intervention
510 518 elif source_node is not None and target_node is not None:
511 519 # case πŸ„΅ or πŸ„Ί : simple merge without intervention
512 520 #
513 521 # In buggy case where source_node is not an ancestors of target_node.
514 522 # There should have a been a new filenode created, recording this as
515 523 # "modified". We do not deal with them yet.
516 524 pass
517 525 else:
518 526 # An impossible case, the diff algorithm should not return entry if the
519 527 # file is missing on both side.
520 528 assert False, "unreachable"
521 529
522 530
523 531 def _missing_from_all_ancestors(mas, filename):
524 532 return all(_find(ma, filename) is None for ma in mas)
525 533
526 534
527 535 def computechangesetfilesadded(ctx):
528 536 """return the list of files added in a changeset"""
529 537 added = []
530 538 for f in ctx.files():
531 539 if not any(f in p for p in ctx.parents()):
532 540 added.append(f)
533 541 return added
534 542
535 543
536 544 def get_removal_filter(ctx, x=None):
537 545 """return a function to detect files "wrongly" detected as `removed`
538 546
539 547 When a file is removed relative to p1 in a merge, this
540 548 function determines whether the absence is due to a
541 549 deletion from a parent, or whether the merge commit
542 550 itself deletes the file. We decide this by doing a
543 551 simplified three way merge of the manifest entry for
544 552 the file. There are two ways we decide the merge
545 553 itself didn't delete a file:
546 554 - neither parent (nor the merge) contain the file
547 555 - exactly one parent contains the file, and that
548 556 parent has the same filelog entry as the merge
549 557 ancestor (or all of them if there two). In other
550 558 words, that parent left the file unchanged while the
551 559 other one deleted it.
552 560 One way to think about this is that deleting a file is
553 561 similar to emptying it, so the list of changed files
554 562 should be similar either way. The computation
555 563 described above is not done directly in _filecommit
556 564 when creating the list of changed files, however
557 565 it does something very similar by comparing filelog
558 566 nodes.
559 567 """
560 568
561 569 if x is not None:
562 570 p1, p2, m1, m2 = x
563 571 else:
564 572 p1 = ctx.p1()
565 573 p2 = ctx.p2()
566 574 m1 = p1.manifest()
567 575 m2 = p2.manifest()
568 576
569 577 @util.cachefunc
570 578 def mas():
571 579 p1n = p1.node()
572 580 p2n = p2.node()
573 581 cahs = ctx.repo().changelog.commonancestorsheads(p1n, p2n)
574 582 if not cahs:
575 583 cahs = [nullrev]
576 584 return [ctx.repo()[r].manifest() for r in cahs]
577 585
578 586 def deletionfromparent(f):
579 587 if f in m1:
580 588 return f not in m2 and all(
581 589 f in ma and ma.find(f) == m1.find(f) for ma in mas()
582 590 )
583 591 elif f in m2:
584 592 return all(f in ma and ma.find(f) == m2.find(f) for ma in mas())
585 593 else:
586 594 return True
587 595
588 596 return deletionfromparent
589 597
590 598
591 599 def computechangesetfilesremoved(ctx):
592 600 """return the list of files removed in a changeset"""
593 601 removed = []
594 602 for f in ctx.files():
595 603 if f not in ctx:
596 604 removed.append(f)
597 605 if removed:
598 606 rf = get_removal_filter(ctx)
599 607 removed = [r for r in removed if not rf(r)]
600 608 return removed
601 609
602 610
603 611 def computechangesetfilesmerged(ctx):
604 612 """return the list of files merged in a changeset"""
605 613 merged = []
606 614 if len(ctx.parents()) < 2:
607 615 return merged
608 616 for f in ctx.files():
609 617 if f in ctx:
610 618 fctx = ctx[f]
611 619 parents = fctx._filelog.parents(fctx._filenode)
612 620 if parents[1] != nullid:
613 621 merged.append(f)
614 622 return merged
615 623
616 624
617 625 def computechangesetcopies(ctx):
618 626 """return the copies data for a changeset
619 627
620 628 The copies data are returned as a pair of dictionnary (p1copies, p2copies).
621 629
622 630 Each dictionnary are in the form: `{newname: oldname}`
623 631 """
624 632 p1copies = {}
625 633 p2copies = {}
626 634 p1 = ctx.p1()
627 635 p2 = ctx.p2()
628 636 narrowmatch = ctx._repo.narrowmatch()
629 637 for dst in ctx.files():
630 638 if not narrowmatch(dst) or dst not in ctx:
631 639 continue
632 640 copied = ctx[dst].renamed()
633 641 if not copied:
634 642 continue
635 643 src, srcnode = copied
636 644 if src in p1 and p1[src].filenode() == srcnode:
637 645 p1copies[dst] = src
638 646 elif src in p2 and p2[src].filenode() == srcnode:
639 647 p2copies[dst] = src
640 648 return p1copies, p2copies
641 649
642 650
643 651 def encodecopies(files, copies):
644 652 items = []
645 653 for i, dst in enumerate(files):
646 654 if dst in copies:
647 655 items.append(b'%d\0%s' % (i, copies[dst]))
648 656 if len(items) != len(copies):
649 657 raise error.ProgrammingError(
650 658 b'some copy targets missing from file list'
651 659 )
652 660 return b"\n".join(items)
653 661
654 662
655 663 def decodecopies(files, data):
656 664 try:
657 665 copies = {}
658 666 if not data:
659 667 return copies
660 668 for l in data.split(b'\n'):
661 669 strindex, src = l.split(b'\0')
662 670 i = int(strindex)
663 671 dst = files[i]
664 672 copies[dst] = src
665 673 return copies
666 674 except (ValueError, IndexError):
667 675 # Perhaps someone had chosen the same key name (e.g. "p1copies") and
668 676 # used different syntax for the value.
669 677 return None
670 678
671 679
672 680 def encodefileindices(files, subset):
673 681 subset = set(subset)
674 682 indices = []
675 683 for i, f in enumerate(files):
676 684 if f in subset:
677 685 indices.append(b'%d' % i)
678 686 return b'\n'.join(indices)
679 687
680 688
681 689 def decodefileindices(files, data):
682 690 try:
683 691 subset = []
684 692 if not data:
685 693 return subset
686 694 for strindex in data.split(b'\n'):
687 695 i = int(strindex)
688 696 if i < 0 or i >= len(files):
689 697 return None
690 698 subset.append(files[i])
691 699 return subset
692 700 except (ValueError, IndexError):
693 701 # Perhaps someone had chosen the same key name (e.g. "added") and
694 702 # used different syntax for the value.
695 703 return None
696 704
697 705
698 706 # see mercurial/helptext/internals/revlogs.txt for details about the format
699 707
700 708 ACTION_MASK = int("111" "00", 2)
701 709 # note: untouched file used as copy source will as `000` for this mask.
702 710 ADDED_FLAG = int("001" "00", 2)
703 711 MERGED_FLAG = int("010" "00", 2)
704 712 REMOVED_FLAG = int("011" "00", 2)
705 713 SALVAGED_FLAG = int("100" "00", 2)
706 714 TOUCHED_FLAG = int("101" "00", 2)
707 715
708 716 COPIED_MASK = int("11", 2)
709 717 COPIED_FROM_P1_FLAG = int("10", 2)
710 718 COPIED_FROM_P2_FLAG = int("11", 2)
711 719
712 720 # structure is <flag><filename-end><copy-source>
713 721 INDEX_HEADER = struct.Struct(">L")
714 722 INDEX_ENTRY = struct.Struct(">bLL")
715 723
716 724
717 725 def encode_files_sidedata(files):
718 726 all_files = set(files.touched)
719 727 all_files.update(files.copied_from_p1.values())
720 728 all_files.update(files.copied_from_p2.values())
721 729 all_files = sorted(all_files)
722 730 file_idx = {f: i for (i, f) in enumerate(all_files)}
723 731 file_idx[None] = 0
724 732
725 733 chunks = [INDEX_HEADER.pack(len(all_files))]
726 734
727 735 filename_length = 0
728 736 for f in all_files:
729 737 filename_size = len(f)
730 738 filename_length += filename_size
731 739 flag = 0
732 740 if f in files.added:
733 741 flag |= ADDED_FLAG
734 742 elif f in files.merged:
735 743 flag |= MERGED_FLAG
736 744 elif f in files.removed:
737 745 flag |= REMOVED_FLAG
738 746 elif f in files.salvaged:
739 747 flag |= SALVAGED_FLAG
740 748 elif f in files.touched:
741 749 flag |= TOUCHED_FLAG
742 750
743 751 copy = None
744 752 if f in files.copied_from_p1:
745 753 flag |= COPIED_FROM_P1_FLAG
746 754 copy = files.copied_from_p1.get(f)
747 755 elif f in files.copied_from_p2:
748 756 copy = files.copied_from_p2.get(f)
749 757 flag |= COPIED_FROM_P2_FLAG
750 758 copy_idx = file_idx[copy]
751 759 chunks.append(INDEX_ENTRY.pack(flag, filename_length, copy_idx))
752 760 chunks.extend(all_files)
753 761 return {sidedatamod.SD_FILES: b''.join(chunks)}
754 762
755 763
756 764 def decode_files_sidedata(sidedata):
757 765 md = ChangingFiles()
758 766 raw = sidedata.get(sidedatamod.SD_FILES)
759 767
760 768 if raw is None:
761 769 return md
762 770
763 771 copies = []
764 772 all_files = []
765 773
766 774 assert len(raw) >= INDEX_HEADER.size
767 775 total_files = INDEX_HEADER.unpack_from(raw, 0)[0]
768 776
769 777 offset = INDEX_HEADER.size
770 778 file_offset_base = offset + (INDEX_ENTRY.size * total_files)
771 779 file_offset_last = file_offset_base
772 780
773 781 assert len(raw) >= file_offset_base
774 782
775 783 for idx in range(total_files):
776 784 flag, file_end, copy_idx = INDEX_ENTRY.unpack_from(raw, offset)
777 785 file_end += file_offset_base
778 786 filename = raw[file_offset_last:file_end]
779 787 filesize = file_end - file_offset_last
780 788 assert len(filename) == filesize
781 789 offset += INDEX_ENTRY.size
782 790 file_offset_last = file_end
783 791 all_files.append(filename)
784 792 if flag & ACTION_MASK == ADDED_FLAG:
785 793 md.mark_added(filename)
786 794 elif flag & ACTION_MASK == MERGED_FLAG:
787 795 md.mark_merged(filename)
788 796 elif flag & ACTION_MASK == REMOVED_FLAG:
789 797 md.mark_removed(filename)
790 798 elif flag & ACTION_MASK == SALVAGED_FLAG:
791 799 md.mark_salvaged(filename)
792 800 elif flag & ACTION_MASK == TOUCHED_FLAG:
793 801 md.mark_touched(filename)
794 802
795 803 copied = None
796 804 if flag & COPIED_MASK == COPIED_FROM_P1_FLAG:
797 805 copied = md.mark_copied_from_p1
798 806 elif flag & COPIED_MASK == COPIED_FROM_P2_FLAG:
799 807 copied = md.mark_copied_from_p2
800 808
801 809 if copied is not None:
802 810 copies.append((copied, filename, copy_idx))
803 811
804 812 for copied, filename, copy_idx in copies:
805 813 copied(all_files[copy_idx], filename)
806 814
807 815 return md
808 816
809 817
810 818 def _getsidedata(srcrepo, rev):
811 819 ctx = srcrepo[rev]
812 820 files = compute_all_files_changes(ctx)
813 821 return encode_files_sidedata(files), files.has_copies_info
814 822
815 823
816 824 def copies_sidedata_computer(repo, revlog, rev, existing_sidedata):
817 825 return _getsidedata(repo, rev)[0]
818 826
819 827
820 828 def set_sidedata_spec_for_repo(repo):
821 829 if requirementsmod.COPIESSDC_REQUIREMENT in repo.requirements:
822 830 repo.register_wanted_sidedata(sidedatamod.SD_FILES)
823 831 repo.register_sidedata_computer(
824 832 b"changelog",
825 833 sidedatamod.SD_FILES,
826 834 (sidedatamod.SD_FILES,),
827 835 copies_sidedata_computer,
828 836 )
829 837
830 838
831 839 def getsidedataadder(srcrepo, destrepo):
832 840 use_w = srcrepo.ui.configbool(b'experimental', b'worker.repository-upgrade')
833 841 if pycompat.iswindows or not use_w:
834 842 return _get_simple_sidedata_adder(srcrepo, destrepo)
835 843 else:
836 844 return _get_worker_sidedata_adder(srcrepo, destrepo)
837 845
838 846
839 847 def _sidedata_worker(srcrepo, revs_queue, sidedata_queue, tokens):
840 848 """The function used by worker precomputing sidedata
841 849
842 850 It read an input queue containing revision numbers
843 851 It write in an output queue containing (rev, <sidedata-map>)
844 852
845 853 The `None` input value is used as a stop signal.
846 854
847 855 The `tokens` semaphore is user to avoid having too many unprocessed
848 856 entries. The workers needs to acquire one token before fetching a task.
849 857 They will be released by the consumer of the produced data.
850 858 """
851 859 tokens.acquire()
852 860 rev = revs_queue.get()
853 861 while rev is not None:
854 862 data = _getsidedata(srcrepo, rev)
855 863 sidedata_queue.put((rev, data))
856 864 tokens.acquire()
857 865 rev = revs_queue.get()
858 866 # processing of `None` is completed, release the token.
859 867 tokens.release()
860 868
861 869
862 870 BUFF_PER_WORKER = 50
863 871
864 872
865 873 def _get_worker_sidedata_adder(srcrepo, destrepo):
866 874 """The parallel version of the sidedata computation
867 875
868 876 This code spawn a pool of worker that precompute a buffer of sidedata
869 877 before we actually need them"""
870 878 # avoid circular import copies -> scmutil -> worker -> copies
871 879 from . import worker
872 880
873 881 nbworkers = worker._numworkers(srcrepo.ui)
874 882
875 883 tokens = multiprocessing.BoundedSemaphore(nbworkers * BUFF_PER_WORKER)
876 884 revsq = multiprocessing.Queue()
877 885 sidedataq = multiprocessing.Queue()
878 886
879 887 assert srcrepo.filtername is None
880 888 # queue all tasks beforehand, revision numbers are small and it make
881 889 # synchronisation simpler
882 890 #
883 891 # Since the computation for each node can be quite expensive, the overhead
884 892 # of using a single queue is not revelant. In practice, most computation
885 893 # are fast but some are very expensive and dominate all the other smaller
886 894 # cost.
887 895 for r in srcrepo.changelog.revs():
888 896 revsq.put(r)
889 897 # queue the "no more tasks" markers
890 898 for i in range(nbworkers):
891 899 revsq.put(None)
892 900
893 901 allworkers = []
894 902 for i in range(nbworkers):
895 903 args = (srcrepo, revsq, sidedataq, tokens)
896 904 w = multiprocessing.Process(target=_sidedata_worker, args=args)
897 905 allworkers.append(w)
898 906 w.start()
899 907
900 908 # dictionnary to store results for revision higher than we one we are
901 909 # looking for. For example, if we need the sidedatamap for 42, and 43 is
902 910 # received, when shelve 43 for later use.
903 911 staging = {}
904 912
905 913 def sidedata_companion(revlog, rev):
906 914 data = {}, False
907 915 if util.safehasattr(revlog, b'filteredrevs'): # this is a changelog
908 916 # Is the data previously shelved ?
909 917 data = staging.pop(rev, None)
910 918 if data is None:
911 919 # look at the queued result until we find the one we are lookig
912 920 # for (shelve the other ones)
913 921 r, data = sidedataq.get()
914 922 while r != rev:
915 923 staging[r] = data
916 924 r, data = sidedataq.get()
917 925 tokens.release()
918 926 sidedata, has_copies_info = data
919 927 new_flag = 0
920 928 if has_copies_info:
921 929 new_flag = sidedataflag.REVIDX_HASCOPIESINFO
922 930 return False, (), sidedata, new_flag, 0
923 931
924 932 return sidedata_companion
925 933
926 934
927 935 def _get_simple_sidedata_adder(srcrepo, destrepo):
928 936 """The simple version of the sidedata computation
929 937
930 938 It just compute it in the same thread on request"""
931 939
932 940 def sidedatacompanion(revlog, rev):
933 941 sidedata, has_copies_info = {}, False
934 942 if util.safehasattr(revlog, 'filteredrevs'): # this is a changelog
935 943 sidedata, has_copies_info = _getsidedata(srcrepo, rev)
936 944 new_flag = 0
937 945 if has_copies_info:
938 946 new_flag = sidedataflag.REVIDX_HASCOPIESINFO
939 947
940 948 return False, (), sidedata, new_flag, 0
941 949
942 950 return sidedatacompanion
943 951
944 952
945 953 def getsidedataremover(srcrepo, destrepo):
946 954 def sidedatacompanion(revlog, rev):
947 955 f = ()
948 956 if util.safehasattr(revlog, 'filteredrevs'): # this is a changelog
949 957 if revlog.flags(rev) & sidedataflag.REVIDX_SIDEDATA:
950 958 f = (
951 959 sidedatamod.SD_P1COPIES,
952 960 sidedatamod.SD_P2COPIES,
953 961 sidedatamod.SD_FILESADDED,
954 962 sidedatamod.SD_FILESREMOVED,
955 963 )
956 964 return False, f, {}, 0, sidedataflag.REVIDX_HASCOPIESINFO
957 965
958 966 return sidedatacompanion
@@ -1,3833 +1,3819 b''
1 1 #testcases filelog compatibility changeset sidedata upgraded upgraded-parallel
2 2
3 3 =====================================================
4 4 Test Copy tracing for chain of copies involving merge
5 5 =====================================================
6 6
7 7 This test files covers copies/rename case for a chains of commit where merges
8 8 are involved. It cheks we do not have unwanted update of behavior and that the
9 9 different options to retrieve copies behave correctly.
10 10
11 11
12 12 Setup
13 13 =====
14 14
15 15 use git diff to see rename
16 16
17 17 $ cat << EOF >> ./no-linkrev
18 18 > #!$PYTHON
19 19 > # filter out linkrev part of the debugindex command
20 20 > import sys
21 21 > for line in sys.stdin:
22 22 > if " linkrev " in line:
23 23 > print(line.rstrip())
24 24 > else:
25 25 > l = "%s *%s" % (line[:6], line[14:].rstrip())
26 26 > print(l)
27 27 > EOF
28 28 $ chmod +x no-linkrev
29 29
30 30 $ cat << EOF >> $HGRCPATH
31 31 > [diff]
32 32 > git=yes
33 33 > [command-templates]
34 34 > log={desc}\n
35 35 > EOF
36 36
37 37 #if compatibility
38 38 $ cat >> $HGRCPATH << EOF
39 39 > [experimental]
40 40 > copies.read-from = compatibility
41 41 > EOF
42 42 #endif
43 43
44 44 #if changeset
45 45 $ cat >> $HGRCPATH << EOF
46 46 > [experimental]
47 47 > copies.read-from = changeset-only
48 48 > copies.write-to = changeset-only
49 49 > EOF
50 50 #endif
51 51
52 52 #if sidedata
53 53 $ cat >> $HGRCPATH << EOF
54 54 > [format]
55 55 > exp-use-side-data = yes
56 56 > exp-use-copies-side-data-changeset = yes
57 57 > EOF
58 58 #endif
59 59
60 60
61 61 $ cat > same-content.txt << EOF
62 62 > Here is some content that will be the same accros multiple file.
63 63 >
64 64 > This is done on purpose so that we end up in some merge situation, were the
65 65 > resulting content is the same as in the parent(s), but a new filenodes still
66 66 > need to be created to record some file history information (especially
67 67 > about copies).
68 68 > EOF
69 69
70 70 $ hg init repo-chain
71 71 $ cd repo-chain
72 72
73 73 Add some linear rename initialy
74 74
75 75 $ cp ../same-content.txt a
76 76 $ cp ../same-content.txt b
77 77 $ cp ../same-content.txt h
78 78 $ echo "original content for P" > p
79 79 $ echo "original content for Q" > q
80 80 $ echo "original content for R" > r
81 81 $ hg ci -Am 'i-0 initial commit: a b h p q r'
82 82 adding a
83 83 adding b
84 84 adding h
85 85 adding p
86 86 adding q
87 87 adding r
88 88 $ hg mv a c
89 89 $ hg mv p s
90 90 $ hg ci -Am 'i-1: a -move-> c, p -move-> s'
91 91 $ hg mv c d
92 92 $ hg mv s t
93 93 $ hg ci -Am 'i-2: c -move-> d, s -move-> t'
94 94 $ hg log -G
95 95 @ i-2: c -move-> d, s -move-> t
96 96 |
97 97 o i-1: a -move-> c, p -move-> s
98 98 |
99 99 o i-0 initial commit: a b h p q r
100 100
101 101
102 102 And having another branch with renames on the other side
103 103
104 104 $ hg mv d e
105 105 $ hg ci -Am 'a-1: d -move-> e'
106 106 $ hg mv e f
107 107 $ hg ci -Am 'a-2: e -move-> f'
108 108 $ hg log -G --rev '::.'
109 109 @ a-2: e -move-> f
110 110 |
111 111 o a-1: d -move-> e
112 112 |
113 113 o i-2: c -move-> d, s -move-> t
114 114 |
115 115 o i-1: a -move-> c, p -move-> s
116 116 |
117 117 o i-0 initial commit: a b h p q r
118 118
119 119
120 120 Have a branching with nothing on one side
121 121
122 122 $ hg up 'desc("i-2")'
123 123 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
124 124 $ echo foo > b
125 125 $ hg ci -m 'b-1: b update'
126 126 created new head
127 127 $ hg log -G --rev '::.'
128 128 @ b-1: b update
129 129 |
130 130 o i-2: c -move-> d, s -move-> t
131 131 |
132 132 o i-1: a -move-> c, p -move-> s
133 133 |
134 134 o i-0 initial commit: a b h p q r
135 135
136 136
137 137 Create a branch that delete a file previous renamed
138 138
139 139 $ hg up 'desc("i-2")'
140 140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 141 $ hg rm d
142 142 $ hg ci -m 'c-1 delete d'
143 143 created new head
144 144 $ hg log -G --rev '::.'
145 145 @ c-1 delete d
146 146 |
147 147 o i-2: c -move-> d, s -move-> t
148 148 |
149 149 o i-1: a -move-> c, p -move-> s
150 150 |
151 151 o i-0 initial commit: a b h p q r
152 152
153 153
154 154 Create a branch that delete a file previous renamed and recreate it
155 155
156 156 $ hg up 'desc("i-2")'
157 157 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
158 158 $ hg rm d
159 159 $ hg ci -m 'd-1 delete d'
160 160 created new head
161 161 $ echo bar > d
162 162 $ hg add d
163 163 $ hg ci -m 'd-2 re-add d'
164 164 $ hg log -G --rev '::.'
165 165 @ d-2 re-add d
166 166 |
167 167 o d-1 delete d
168 168 |
169 169 o i-2: c -move-> d, s -move-> t
170 170 |
171 171 o i-1: a -move-> c, p -move-> s
172 172 |
173 173 o i-0 initial commit: a b h p q r
174 174
175 175
176 176 Having another branch renaming a different file to the same filename as another
177 177
178 178 $ hg up 'desc("i-2")'
179 179 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
180 180 $ hg mv b g
181 181 $ hg ci -m 'e-1 b -move-> g'
182 182 created new head
183 183 $ hg mv g f
184 184 $ hg ci -m 'e-2 g -move-> f'
185 185 $ hg log -G --rev '::.'
186 186 @ e-2 g -move-> f
187 187 |
188 188 o e-1 b -move-> g
189 189 |
190 190 o i-2: c -move-> d, s -move-> t
191 191 |
192 192 o i-1: a -move-> c, p -move-> s
193 193 |
194 194 o i-0 initial commit: a b h p q r
195 195
196 196 $ hg up -q null
197 197
198 198 Having a branch similar to the 'a' one, but moving the 'p' file around.
199 199
200 200 $ hg up 'desc("i-2")'
201 201 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
202 202 $ hg mv t u
203 203 $ hg ci -Am 'p-1: t -move-> u'
204 204 created new head
205 205 $ hg mv u v
206 206 $ hg ci -Am 'p-2: u -move-> v'
207 207 $ hg log -G --rev '::.'
208 208 @ p-2: u -move-> v
209 209 |
210 210 o p-1: t -move-> u
211 211 |
212 212 o i-2: c -move-> d, s -move-> t
213 213 |
214 214 o i-1: a -move-> c, p -move-> s
215 215 |
216 216 o i-0 initial commit: a b h p q r
217 217
218 218 $ hg up -q null
219 219
220 220 Having another branch renaming a different file to the same filename as another
221 221
222 222 $ hg up 'desc("i-2")'
223 223 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
224 224 $ hg mv r w
225 225 $ hg ci -m 'q-1 r -move-> w'
226 226 created new head
227 227 $ hg mv w v
228 228 $ hg ci -m 'q-2 w -move-> v'
229 229 $ hg log -G --rev '::.'
230 230 @ q-2 w -move-> v
231 231 |
232 232 o q-1 r -move-> w
233 233 |
234 234 o i-2: c -move-> d, s -move-> t
235 235 |
236 236 o i-1: a -move-> c, p -move-> s
237 237 |
238 238 o i-0 initial commit: a b h p q r
239 239
240 240 $ hg up -q null
241 241
242 242 Setup all merge
243 243 ===============
244 244
245 245 This is done beforehand to validate that the upgrade process creates valid copy
246 246 information.
247 247
248 248 merging with unrelated change does not interfere with the renames
249 249 ---------------------------------------------------------------
250 250
251 251 - rename on one side
252 252 - unrelated change on the other side
253 253
254 254 $ case_desc="simple merge - A side: multiple renames, B side: unrelated update"
255 255
256 256 $ hg up 'desc("b-1")'
257 257 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 258 $ hg merge 'desc("a-2")'
259 259 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
260 260 (branch merge, don't forget to commit)
261 261 $ hg ci -m "mBAm-0 $case_desc - one way"
262 262 $ hg up 'desc("a-2")'
263 263 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
264 264 $ hg merge 'desc("b-1")'
265 265 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
266 266 (branch merge, don't forget to commit)
267 267 $ hg ci -m "mABm-0 $case_desc - the other way"
268 268 created new head
269 269 $ hg log -G --rev '::(desc("mABm")+desc("mBAm"))'
270 270 @ mABm-0 simple merge - A side: multiple renames, B side: unrelated update - the other way
271 271 |\
272 272 +---o mBAm-0 simple merge - A side: multiple renames, B side: unrelated update - one way
273 273 | |/
274 274 | o b-1: b update
275 275 | |
276 276 o | a-2: e -move-> f
277 277 | |
278 278 o | a-1: d -move-> e
279 279 |/
280 280 o i-2: c -move-> d, s -move-> t
281 281 |
282 282 o i-1: a -move-> c, p -move-> s
283 283 |
284 284 o i-0 initial commit: a b h p q r
285 285
286 286
287 287
288 288 merging with the side having a delete
289 289 -------------------------------------
290 290
291 291 case summary:
292 292 - one with change to an unrelated file
293 293 - one deleting the change
294 294 and recreate an unrelated file after the merge
295 295
296 296 $ case_desc="simple merge - C side: delete a file with copies history , B side: unrelated update"
297 297
298 298 $ hg up 'desc("b-1")'
299 299 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
300 300 $ hg merge 'desc("c-1")'
301 301 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
302 302 (branch merge, don't forget to commit)
303 303 $ hg ci -m "mBCm-0 $case_desc - one way"
304 304 $ echo bar > d
305 305 $ hg add d
306 306 $ hg ci -m 'mBCm-1 re-add d'
307 307 $ hg up 'desc("c-1")'
308 308 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
309 309 $ hg merge 'desc("b-1")'
310 310 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
311 311 (branch merge, don't forget to commit)
312 312 $ hg ci -m "mCBm-0 $case_desc - the other way"
313 313 created new head
314 314 $ echo bar > d
315 315 $ hg add d
316 316 $ hg ci -m 'mCBm-1 re-add d'
317 317 $ hg log -G --rev '::(desc("mCBm")+desc("mBCm"))'
318 318 @ mCBm-1 re-add d
319 319 |
320 320 o mCBm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - the other way
321 321 |\
322 322 | | o mBCm-1 re-add d
323 323 | | |
324 324 +---o mBCm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - one way
325 325 | |/
326 326 | o c-1 delete d
327 327 | |
328 328 o | b-1: b update
329 329 |/
330 330 o i-2: c -move-> d, s -move-> t
331 331 |
332 332 o i-1: a -move-> c, p -move-> s
333 333 |
334 334 o i-0 initial commit: a b h p q r
335 335
336 336
337 337 Comparing with a merge re-adding the file afterward
338 338 ---------------------------------------------------
339 339
340 340 Merge:
341 341 - one with change to an unrelated file
342 342 - one deleting and recreating the change
343 343
344 344 $ case_desc="simple merge - B side: unrelated update, D side: delete and recreate a file (with different content)"
345 345
346 346 $ hg up 'desc("b-1")'
347 347 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
348 348 $ hg merge 'desc("d-2")'
349 349 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
350 350 (branch merge, don't forget to commit)
351 351 $ hg ci -m "mBDm-0 $case_desc - one way"
352 352 $ hg up 'desc("d-2")'
353 353 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
354 354 $ hg merge 'desc("b-1")'
355 355 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
356 356 (branch merge, don't forget to commit)
357 357 $ hg ci -m "mDBm-0 $case_desc - the other way"
358 358 created new head
359 359 $ hg log -G --rev '::(desc("mDBm")+desc("mBDm"))'
360 360 @ mDBm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - the other way
361 361 |\
362 362 +---o mBDm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - one way
363 363 | |/
364 364 | o d-2 re-add d
365 365 | |
366 366 | o d-1 delete d
367 367 | |
368 368 o | b-1: b update
369 369 |/
370 370 o i-2: c -move-> d, s -move-> t
371 371 |
372 372 o i-1: a -move-> c, p -move-> s
373 373 |
374 374 o i-0 initial commit: a b h p q r
375 375
376 376
377 377
378 378 Comparing with a merge with colliding rename
379 379 --------------------------------------------
380 380
381 381 Subcase: new copy information on both side
382 382 ``````````````````````````````````````````
383 383
384 384 - the "e-" branch renaming b to f (through 'g')
385 385 - the "a-" branch renaming d to f (through e)
386 386
387 387 $ case_desc="merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f)"
388 388
389 389 $ hg up 'desc("a-2")'
390 390 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
391 391 $ hg merge 'desc("e-2")'
392 392 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
393 393 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
394 394 (branch merge, don't forget to commit)
395 395 $ hg ci -m "mAEm-0 $case_desc - one way"
396 396 $ hg up 'desc("e-2")'
397 397 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
398 398 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
399 399 $ hg merge 'desc("a-2")'
400 400 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
401 401 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
402 402 (branch merge, don't forget to commit)
403 403 $ hg ci -m "mEAm-0 $case_desc - the other way"
404 404 created new head
405 405 $ hg log -G --rev '::(desc("mAEm")+desc("mEAm"))'
406 406 @ mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
407 407 |\
408 408 +---o mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
409 409 | |/
410 410 | o e-2 g -move-> f
411 411 | |
412 412 | o e-1 b -move-> g
413 413 | |
414 414 o | a-2: e -move-> f
415 415 | |
416 416 o | a-1: d -move-> e
417 417 |/
418 418 o i-2: c -move-> d, s -move-> t
419 419 |
420 420 o i-1: a -move-> c, p -move-> s
421 421 |
422 422 o i-0 initial commit: a b h p q r
423 423
424 424
425 425 Subcase: new copy information on both side with an actual merge happening
426 426 `````````````````````````````````````````````````````````````````````````
427 427
428 428 - the "p-" branch renaming 't' to 'v' (through 'u')
429 429 - the "q-" branch renaming 'r' to 'v' (through 'w')
430 430
431 431 $ case_desc="merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content)"
432 432
433 433 $ hg up 'desc("p-2")'
434 434 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
435 435 $ hg merge 'desc("q-2")' --tool ':union'
436 436 merging v
437 437 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
438 438 (branch merge, don't forget to commit)
439 439 $ hg ci -m "mPQm-0 $case_desc - one way"
440 440 $ hg up 'desc("q-2")'
441 441 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
442 442 $ hg merge 'desc("p-2")' --tool ':union'
443 443 merging v
444 444 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
445 445 (branch merge, don't forget to commit)
446 446 $ hg ci -m "mQPm-0 $case_desc - the other way"
447 447 created new head
448 448 $ hg log -G --rev '::(desc("mAEm")+desc("mEAm"))'
449 449 o mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
450 450 |\
451 451 +---o mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
452 452 | |/
453 453 | o e-2 g -move-> f
454 454 | |
455 455 | o e-1 b -move-> g
456 456 | |
457 457 o | a-2: e -move-> f
458 458 | |
459 459 o | a-1: d -move-> e
460 460 |/
461 461 o i-2: c -move-> d, s -move-> t
462 462 |
463 463 o i-1: a -move-> c, p -move-> s
464 464 |
465 465 o i-0 initial commit: a b h p q r
466 466
467 467
468 468 Subcase: existing copy information overwritten on one branch
469 469 ````````````````````````````````````````````````````````````
470 470
471 471 Merge:
472 472 - one with change to an unrelated file (b)
473 473 - one overwriting a file (d) with a rename (from h to i to d)
474 474
475 475 $ case_desc="simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d)"
476 476
477 477 $ hg up 'desc("i-2")'
478 478 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
479 479 $ hg mv h i
480 480 $ hg commit -m "f-1: rename h -> i"
481 481 created new head
482 482 $ hg mv --force i d
483 483 $ hg commit -m "f-2: rename i -> d"
484 484 $ hg debugindex d | ../no-linkrev
485 485 rev linkrev nodeid p1 p2
486 486 0 * d8252ab2e760 000000000000 000000000000 (no-changeset !)
487 487 0 * ae258f702dfe 000000000000 000000000000 (changeset !)
488 488 1 * b004912a8510 000000000000 000000000000
489 489 2 * 7b79e2fe0c89 000000000000 000000000000 (no-changeset !)
490 490 $ hg up 'desc("b-1")'
491 491 3 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
492 492 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
493 493 $ hg merge 'desc("f-2")'
494 494 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
495 495 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
496 496 (branch merge, don't forget to commit)
497 497 $ hg ci -m "mBFm-0 $case_desc - one way"
498 498 $ hg up 'desc("f-2")'
499 499 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
500 500 $ hg merge 'desc("b-1")'
501 501 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
502 502 (branch merge, don't forget to commit)
503 503 $ hg ci -m "mFBm-0 $case_desc - the other way"
504 504 created new head
505 505 $ hg up null --quiet
506 506 $ hg log -G --rev '::(desc("mBFm")+desc("mFBm"))'
507 507 o mFBm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
508 508 |\
509 509 +---o mBFm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
510 510 | |/
511 511 | o f-2: rename i -> d
512 512 | |
513 513 | o f-1: rename h -> i
514 514 | |
515 515 o | b-1: b update
516 516 |/
517 517 o i-2: c -move-> d, s -move-> t
518 518 |
519 519 o i-1: a -move-> c, p -move-> s
520 520 |
521 521 o i-0 initial commit: a b h p q r
522 522
523 523
524 524 Subcase: existing copy information overwritten on one branch, with different content)
525 525 `````````````````````````````````````````````````````````````````````````````````````
526 526
527 527 Merge:
528 528 - one with change to an unrelated file (b)
529 529 - one overwriting a file (t) with a rename (from r to x to t), v content is not the same as on the other branch
530 530
531 531 $ case_desc="simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content"
532 532
533 533 $ hg up 'desc("i-2")'
534 534 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
535 535 $ hg mv r x
536 536 $ hg commit -m "r-1: rename r -> x"
537 537 created new head
538 538 $ hg mv --force x t
539 539 $ hg commit -m "r-2: rename t -> x"
540 540 $ hg debugindex t | ../no-linkrev
541 541 rev linkrev nodeid p1 p2
542 542 0 * d74efbf65309 000000000000 000000000000 (no-changeset !)
543 543 1 * 02a930b9d7ad 000000000000 000000000000 (no-changeset !)
544 544 0 * 5aed6a8dbff0 000000000000 000000000000 (changeset !)
545 545 1 * a38b2fa17021 000000000000 000000000000 (changeset !)
546 546 $ hg up 'desc("b-1")'
547 547 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
548 548 $ hg merge 'desc("r-2")'
549 549 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
550 550 (branch merge, don't forget to commit)
551 551 $ hg ci -m "mBRm-0 $case_desc - one way"
552 552 $ hg up 'desc("r-2")'
553 553 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
554 554 $ hg merge 'desc("b-1")'
555 555 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
556 556 (branch merge, don't forget to commit)
557 557 $ hg ci -m "mRBm-0 $case_desc - the other way"
558 558 created new head
559 559 $ hg up null --quiet
560 560 $ hg log -G --rev '::(desc("mBRm")+desc("mRBm"))'
561 561 o mRBm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - the other way
562 562 |\
563 563 +---o mBRm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - one way
564 564 | |/
565 565 | o r-2: rename t -> x
566 566 | |
567 567 | o r-1: rename r -> x
568 568 | |
569 569 o | b-1: b update
570 570 |/
571 571 o i-2: c -move-> d, s -move-> t
572 572 |
573 573 o i-1: a -move-> c, p -move-> s
574 574 |
575 575 o i-0 initial commit: a b h p q r
576 576
577 577
578 578
579 579 Subcase: reset of the copy history on one side
580 580 ``````````````````````````````````````````````
581 581
582 582 Merge:
583 583 - one with change to a file
584 584 - one deleting and recreating the file
585 585
586 586 Unlike in the 'BD/DB' cases, an actual merge happened here. So we should
587 587 consider history and rename on both branch of the merge.
588 588
589 589 $ case_desc="actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content"
590 590
591 591 $ hg up 'desc("i-2")'
592 592 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
593 593 $ echo "some update" >> d
594 594 $ hg commit -m "g-1: update d"
595 595 created new head
596 596 $ hg up 'desc("d-2")'
597 597 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
598 598 $ hg merge 'desc("g-1")' --tool :union
599 599 merging d
600 600 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
601 601 (branch merge, don't forget to commit)
602 602 $ hg ci -m "mDGm-0 $case_desc - one way"
603 603 $ hg up 'desc("g-1")'
604 604 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
605 605 $ hg merge 'desc("d-2")' --tool :union
606 606 merging d
607 607 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
608 608 (branch merge, don't forget to commit)
609 609 $ hg ci -m "mGDm-0 $case_desc - the other way"
610 610 created new head
611 611 $ hg log -G --rev '::(desc("mDGm")+desc("mGDm"))'
612 612 @ mGDm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - the other way
613 613 |\
614 614 +---o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
615 615 | |/
616 616 | o g-1: update d
617 617 | |
618 618 o | d-2 re-add d
619 619 | |
620 620 o | d-1 delete d
621 621 |/
622 622 o i-2: c -move-> d, s -move-> t
623 623 |
624 624 o i-1: a -move-> c, p -move-> s
625 625 |
626 626 o i-0 initial commit: a b h p q r
627 627
628 628
629 629 Subcase: merging a change to a file with a "copy overwrite" to that file from another branch
630 630 ````````````````````````````````````````````````````````````````````````````````````````````
631 631
632 632 Merge:
633 633 - one with change to a file (d)
634 634 - one overwriting that file with a rename (from h to i, to d)
635 635
636 636 This case is similar to BF/FB, but an actual merge happens, so both side of the
637 637 history are relevant.
638 638
639 639 Note:
640 640 | In this case, the merge get conflicting information since on one side we have
641 641 | "a -> c -> d". and one the other one we have "h -> i -> d".
642 642 |
643 643 | The current code arbitrarily pick one side
644 644
645 645 $ case_desc="merge - G side: content change, F side: copy overwrite, no content change"
646 646
647 647 $ hg up 'desc("f-2")'
648 648 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
649 649 $ hg merge 'desc("g-1")' --tool :union
650 650 merging d (no-changeset !)
651 651 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (no-changeset !)
652 652 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
653 653 (branch merge, don't forget to commit)
654 654 $ hg ci -m "mFGm-0 $case_desc - one way"
655 655 created new head
656 656 $ hg up 'desc("g-1")'
657 657 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
658 658 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
659 659 $ hg merge 'desc("f-2")' --tool :union
660 660 merging d (no-changeset !)
661 661 0 files updated, 1 files merged, 1 files removed, 0 files unresolved (no-changeset !)
662 662 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
663 663 (branch merge, don't forget to commit)
664 664 $ hg ci -m "mGFm-0 $case_desc - the other way"
665 665 created new head
666 666 $ hg log -G --rev '::(desc("mGFm")+desc("mFGm"))'
667 667 @ mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
668 668 |\
669 669 +---o mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
670 670 | |/
671 671 | o g-1: update d
672 672 | |
673 673 o | f-2: rename i -> d
674 674 | |
675 675 o | f-1: rename h -> i
676 676 |/
677 677 o i-2: c -move-> d, s -move-> t
678 678 |
679 679 o i-1: a -move-> c, p -move-> s
680 680 |
681 681 o i-0 initial commit: a b h p q r
682 682
683 683
684 684
685 685 Comparing with merging with a deletion (and keeping the file)
686 686 -------------------------------------------------------------
687 687
688 688 Merge:
689 689 - one removing a file (d)
690 690 - one updating that file
691 691 - the merge keep the modified version of the file (canceling the delete)
692 692
693 693 In this case, the file keep on living after the merge. So we should not drop its
694 694 copy tracing chain.
695 695
696 696 $ case_desc="merge updated/deleted - revive the file (updated content)"
697 697
698 698 $ hg up 'desc("c-1")'
699 699 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
700 700 $ hg merge 'desc("g-1")'
701 701 file 'd' was deleted in local [working copy] but was modified in other [merge rev].
702 702 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
703 703 What do you want to do? u
704 704 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
705 705 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
706 706 [1]
707 707 $ hg resolve -t :other d
708 708 (no more unresolved files)
709 709 $ hg ci -m "mCGm-0 $case_desc - one way"
710 710 created new head
711 711
712 712 $ hg up 'desc("g-1")'
713 713 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
714 714 $ hg merge 'desc("c-1")'
715 715 file 'd' was deleted in other [merge rev] but was modified in local [working copy].
716 716 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
717 717 What do you want to do? u
718 718 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
719 719 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
720 720 [1]
721 721 $ hg resolve -t :local d
722 722 (no more unresolved files)
723 723 $ hg ci -m "mGCm-0 $case_desc - the other way"
724 724 created new head
725 725
726 726 $ hg log -G --rev '::(desc("mCGm")+desc("mGCm"))'
727 727 @ mGCm-0 merge updated/deleted - revive the file (updated content) - the other way
728 728 |\
729 729 +---o mCGm-0 merge updated/deleted - revive the file (updated content) - one way
730 730 | |/
731 731 | o g-1: update d
732 732 | |
733 733 o | c-1 delete d
734 734 |/
735 735 o i-2: c -move-> d, s -move-> t
736 736 |
737 737 o i-1: a -move-> c, p -move-> s
738 738 |
739 739 o i-0 initial commit: a b h p q r
740 740
741 741
742 742
743 743
744 744 Comparing with merge restoring an untouched deleted file
745 745 --------------------------------------------------------
746 746
747 747 Merge:
748 748 - one removing a file (d)
749 749 - one leaving the file untouched
750 750 - the merge actively restore the file to the same content.
751 751
752 752 In this case, the file keep on living after the merge. So we should not drop its
753 753 copy tracing chain.
754 754
755 755 $ case_desc="merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge)"
756 756
757 757 $ hg up 'desc("c-1")'
758 758 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
759 759 $ hg merge 'desc("b-1")'
760 760 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
761 761 (branch merge, don't forget to commit)
762 762 $ hg revert --rev 'desc("b-1")' d
763 763 $ hg ci -m "mCB-revert-m-0 $case_desc - one way"
764 764 created new head
765 765
766 766 $ hg up 'desc("b-1")'
767 767 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
768 768 $ hg merge 'desc("c-1")'
769 769 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
770 770 (branch merge, don't forget to commit)
771 771 $ hg revert --rev 'desc("b-1")' d
772 772 $ hg ci -m "mBC-revert-m-0 $case_desc - the other way"
773 773 created new head
774 774
775 775 $ hg log -G --rev '::(desc("mCB-revert-m")+desc("mBC-revert-m"))'
776 776 @ mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
777 777 |\
778 778 +---o mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
779 779 | |/
780 780 | o c-1 delete d
781 781 | |
782 782 o | b-1: b update
783 783 |/
784 784 o i-2: c -move-> d, s -move-> t
785 785 |
786 786 o i-1: a -move-> c, p -move-> s
787 787 |
788 788 o i-0 initial commit: a b h p q r
789 789
790 790
791 791
792 792 $ hg up null --quiet
793 793
794 794 Merging a branch where a rename was deleted with a branch where the same file was renamed
795 795 ------------------------------------------------------------------------------------------
796 796
797 797 Create a "conflicting" merge where `d` get removed on one branch before its
798 798 rename information actually conflict with the other branch.
799 799
800 800 (the copy information from the branch that was not deleted should win).
801 801
802 802 $ case_desc="simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch)"
803 803
804 804 $ hg up 'desc("i-0")'
805 805 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
806 806 $ hg mv b d
807 807 $ hg ci -m "h-1: b -(move)-> d"
808 808 created new head
809 809
810 810 $ hg up 'desc("c-1")'
811 811 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
812 812 $ hg merge 'desc("h-1")'
813 813 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
814 814 (branch merge, don't forget to commit)
815 815 $ hg ci -m "mCH-delete-before-conflict-m-0 $case_desc - one way"
816 816
817 817 $ hg up 'desc("h-1")'
818 818 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
819 819 $ hg merge 'desc("c-1")'
820 820 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
821 821 (branch merge, don't forget to commit)
822 822 $ hg ci -m "mHC-delete-before-conflict-m-0 $case_desc - the other way"
823 823 created new head
824 824 $ hg log -G --rev '::(desc("mCH-delete-before-conflict-m")+desc("mHC-delete-before-conflict-m"))'
825 825 @ mHC-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - the other way
826 826 |\
827 827 +---o mCH-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - one way
828 828 | |/
829 829 | o h-1: b -(move)-> d
830 830 | |
831 831 o | c-1 delete d
832 832 | |
833 833 o | i-2: c -move-> d, s -move-> t
834 834 | |
835 835 o | i-1: a -move-> c, p -move-> s
836 836 |/
837 837 o i-0 initial commit: a b h p q r
838 838
839 839
840 840 Variant of previous with extra changes introduced by the merge
841 841 --------------------------------------------------------------
842 842
843 843 Multiple cases above explicitely test cases where content are the same on both side during merge. In this section we will introduce variants for theses cases where new change are introduced to these file content during the merges.
844 844
845 845
846 846 Subcase: merge has same initial content on both side, but merge introduced a change
847 847 ```````````````````````````````````````````````````````````````````````````````````
848 848
849 849 Same as `mAEm` and `mEAm` but with extra change to the file before commiting
850 850
851 851 - the "e-" branch renaming b to f (through 'g')
852 852 - the "a-" branch renaming d to f (through e)
853 853
854 854 $ case_desc="merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent)"
855 855
856 856 $ hg up 'desc("a-2")'
857 857 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
858 858 $ hg merge 'desc("e-2")'
859 859 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
860 860 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
861 861 (branch merge, don't forget to commit)
862 862 $ echo "content change for mAE-change-m" > f
863 863 $ hg ci -m "mAE-change-m-0 $case_desc - one way"
864 864 created new head
865 865 $ hg up 'desc("e-2")'
866 866 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
867 867 $ hg merge 'desc("a-2")'
868 868 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
869 869 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
870 870 (branch merge, don't forget to commit)
871 871 $ echo "content change for mEA-change-m" > f
872 872 $ hg ci -m "mEA-change-m-0 $case_desc - the other way"
873 873 created new head
874 874 $ hg log -G --rev '::(desc("mAE-change-m")+desc("mEA-change-m"))'
875 875 @ mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
876 876 |\
877 877 +---o mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
878 878 | |/
879 879 | o e-2 g -move-> f
880 880 | |
881 881 | o e-1 b -move-> g
882 882 | |
883 883 o | a-2: e -move-> f
884 884 | |
885 885 o | a-1: d -move-> e
886 886 |/
887 887 o i-2: c -move-> d, s -move-> t
888 888 |
889 889 o i-1: a -move-> c, p -move-> s
890 890 |
891 891 o i-0 initial commit: a b h p q r
892 892
893 893
894 894 Subcase: merge overwrite common copy information, but with extra change during the merge
895 895 ````````````````````````````````````````````````````````````````````````````````````````
896 896
897 897 Merge:
898 898 - one with change to an unrelated file (b)
899 899 - one overwriting a file (d) with a rename (from h to i to d)
900 900 - the merge update f content
901 901
902 902 $ case_desc="merge with extra change - B side: unrelated change, F side: overwrite d with a copy (from h->i->d)"
903 903
904 904 $ hg up 'desc("f-2")'
905 905 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
906 906 #if no-changeset
907 907 $ hg debugindex d | ../no-linkrev
908 908 rev linkrev nodeid p1 p2
909 909 0 * d8252ab2e760 000000000000 000000000000
910 910 1 * b004912a8510 000000000000 000000000000
911 911 2 * 7b79e2fe0c89 000000000000 000000000000
912 912 3 * 17ec97e60577 d8252ab2e760 000000000000
913 913 4 * 06dabf50734c b004912a8510 17ec97e60577
914 914 5 * 19c0e3924691 17ec97e60577 b004912a8510
915 915 6 * 89c873a01d97 7b79e2fe0c89 17ec97e60577
916 916 7 * d55cb4e9ef57 000000000000 000000000000
917 917 #else
918 918 $ hg debugindex d | ../no-linkrev
919 919 rev linkrev nodeid p1 p2
920 920 0 * ae258f702dfe 000000000000 000000000000
921 921 1 * b004912a8510 000000000000 000000000000
922 922 2 * 5cce88bf349f ae258f702dfe 000000000000
923 923 3 * cc269dd788c8 b004912a8510 5cce88bf349f
924 924 4 * 51c91a115080 5cce88bf349f b004912a8510
925 925 #endif
926 926 $ hg up 'desc("b-1")'
927 927 3 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
928 928 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
929 929 $ hg merge 'desc("f-2")'
930 930 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
931 931 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
932 932 (branch merge, don't forget to commit)
933 933 $ echo "extra-change to (formelly h) during the merge" > d
934 934 $ hg ci -m "mBF-change-m-0 $case_desc - one way"
935 935 created new head
936 936 $ hg manifest --rev . --debug | grep " d"
937 937 1c334238bd42ec85c6a0d83fd1b2a898a6a3215d 644 d (no-changeset !)
938 938 cea2d99c0fde64672ef61953786fdff34f16e230 644 d (changeset !)
939 939
940 940 $ hg up 'desc("f-2")'
941 941 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
942 942 $ hg merge 'desc("b-1")'
943 943 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
944 944 (branch merge, don't forget to commit)
945 945 $ echo "extra-change to (formelly h) during the merge" > d
946 946 $ hg ci -m "mFB-change-m-0 $case_desc - the other way"
947 947 created new head
948 948 $ hg manifest --rev . --debug | grep " d"
949 949 1c334238bd42ec85c6a0d83fd1b2a898a6a3215d 644 d (no-changeset !)
950 950 cea2d99c0fde64672ef61953786fdff34f16e230 644 d (changeset !)
951 951 #if no-changeset
952 952 $ hg debugindex d | ../no-linkrev
953 953 rev linkrev nodeid p1 p2
954 954 0 * d8252ab2e760 000000000000 000000000000
955 955 1 * b004912a8510 000000000000 000000000000
956 956 2 * 7b79e2fe0c89 000000000000 000000000000
957 957 3 * 17ec97e60577 d8252ab2e760 000000000000
958 958 4 * 06dabf50734c b004912a8510 17ec97e60577
959 959 5 * 19c0e3924691 17ec97e60577 b004912a8510
960 960 6 * 89c873a01d97 7b79e2fe0c89 17ec97e60577
961 961 7 * d55cb4e9ef57 000000000000 000000000000
962 962 8 * 1c334238bd42 7b79e2fe0c89 000000000000
963 963 #else
964 964 $ hg debugindex d | ../no-linkrev
965 965 rev linkrev nodeid p1 p2
966 966 0 * ae258f702dfe 000000000000 000000000000
967 967 1 * b004912a8510 000000000000 000000000000
968 968 2 * 5cce88bf349f ae258f702dfe 000000000000
969 969 3 * cc269dd788c8 b004912a8510 5cce88bf349f
970 970 4 * 51c91a115080 5cce88bf349f b004912a8510
971 971 5 * cea2d99c0fde ae258f702dfe 000000000000
972 972 #endif
973 973 $ hg log -G --rev '::(desc("mBF-change-m")+desc("mFB-change-m"))'
974 974 @ mFB-change-m-0 merge with extra change - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
975 975 |\
976 976 +---o mBF-change-m-0 merge with extra change - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
977 977 | |/
978 978 | o f-2: rename i -> d
979 979 | |
980 980 | o f-1: rename h -> i
981 981 | |
982 982 o | b-1: b update
983 983 |/
984 984 o i-2: c -move-> d, s -move-> t
985 985 |
986 986 o i-1: a -move-> c, p -move-> s
987 987 |
988 988 o i-0 initial commit: a b h p q r
989 989
990 990
991 991 Subcase: restoring and untouched deleted file, while touching it
992 992 ````````````````````````````````````````````````````````````````
993 993
994 994 Merge:
995 995 - one removing a file (d)
996 996 - one leaving the file untouched
997 997 - the merge actively restore the file to the same content.
998 998
999 999 In this case, the file keep on living after the merge. So we should not drop its
1000 1000 copy tracing chain.
1001 1001
1002 1002 $ case_desc="merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge)"
1003 1003
1004 1004 $ hg up 'desc("c-1")'
1005 1005 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1006 1006 $ hg merge 'desc("b-1")'
1007 1007 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1008 1008 (branch merge, don't forget to commit)
1009 1009 $ hg revert --rev 'desc("b-1")' d
1010 1010 $ echo "new content for d after the revert" > d
1011 1011 $ hg ci -m "mCB-change-m-0 $case_desc - one way"
1012 1012 created new head
1013 1013 $ hg manifest --rev . --debug | grep " d"
1014 1014 e333780c17752a3b0dd15e3ad48aa4e5c745f621 644 d (no-changeset !)
1015 1015 4b540a18ad699234b2b2aa18cb69555ac9c4b1df 644 d (changeset !)
1016 1016
1017 1017 $ hg up 'desc("b-1")'
1018 1018 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1019 1019 $ hg merge 'desc("c-1")'
1020 1020 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1021 1021 (branch merge, don't forget to commit)
1022 1022 $ hg revert --rev 'desc("b-1")' d
1023 1023 $ echo "new content for d after the revert" > d
1024 1024 $ hg ci -m "mBC-change-m-0 $case_desc - the other way"
1025 1025 created new head
1026 1026 $ hg manifest --rev . --debug | grep " d"
1027 1027 e333780c17752a3b0dd15e3ad48aa4e5c745f621 644 d (no-changeset !)
1028 1028 4b540a18ad699234b2b2aa18cb69555ac9c4b1df 644 d (changeset !)
1029 1029
1030 1030
1031 1031 $ hg up null --quiet
1032 1032 $ hg log -G --rev '::(desc("mCB-change-m")+desc("mBC-change-m"))'
1033 1033 o mBC-change-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
1034 1034 |\
1035 1035 +---o mCB-change-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
1036 1036 | |/
1037 1037 | o c-1 delete d
1038 1038 | |
1039 1039 o | b-1: b update
1040 1040 |/
1041 1041 o i-2: c -move-> d, s -move-> t
1042 1042 |
1043 1043 o i-1: a -move-> c, p -move-> s
1044 1044 |
1045 1045 o i-0 initial commit: a b h p q r
1046 1046
1047 1047
1048 1048 Decision from previous merge are properly chained with later merge
1049 1049 ------------------------------------------------------------------
1050 1050
1051 1051 Subcase: chaining conflicting rename resolution
1052 1052 ```````````````````````````````````````````````
1053 1053
1054 1054 The "mAEm" and "mEAm" case create a rename tracking conflict on file 'f'. We
1055 1055 add more change on the respective branch and merge again. These second merge
1056 1056 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
1057 1057 about that file should stay unchanged.
1058 1058
1059 1059 We also touch J during some of the merge to check for unrelated change to new file during merge.
1060 1060
1061 1061 $ case_desc="chained merges (conflict -> simple) - same content everywhere"
1062 1062
1063 1063 (extra unrelated changes)
1064 1064
1065 1065 $ hg up 'desc("a-2")'
1066 1066 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1067 1067 $ echo j > unrelated-j
1068 1068 $ hg add unrelated-j
1069 1069 $ hg ci -m 'j-1: unrelated changes (based on the "a" series of changes)'
1070 1070 created new head
1071 1071
1072 1072 $ hg up 'desc("e-2")'
1073 1073 2 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
1074 1074 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
1075 1075 $ echo k > unrelated-k
1076 1076 $ hg add unrelated-k
1077 1077 $ hg ci -m 'k-1: unrelated changes (based on "e" changes)'
1078 1078 created new head
1079 1079
1080 1080 (merge variant 1)
1081 1081
1082 1082 $ hg up 'desc("mAEm")'
1083 1083 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
1084 1084 0 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
1085 1085 $ hg merge 'desc("k-1")'
1086 1086 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1087 1087 (branch merge, don't forget to commit)
1088 1088 $ hg ci -m "mAE,Km: $case_desc"
1089 1089
1090 1090 (merge variant 2)
1091 1091
1092 1092 $ hg up 'desc("k-1")'
1093 1093 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
1094 1094 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
1095 1095
1096 1096 $ hg merge 'desc("mAEm")'
1097 1097 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
1098 1098 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
1099 1099 (branch merge, don't forget to commit)
1100 1100 $ hg ci -m "mK,AEm: $case_desc"
1101 1101 created new head
1102 1102
1103 1103 (merge variant 3)
1104 1104
1105 1105 $ hg up 'desc("mEAm")'
1106 1106 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1107 1107 $ hg merge 'desc("j-1")'
1108 1108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1109 1109 (branch merge, don't forget to commit)
1110 1110 $ echo jj > unrelated-j
1111 1111 $ hg ci -m "mEA,Jm: $case_desc"
1112 1112
1113 1113 (merge variant 4)
1114 1114
1115 1115 $ hg up 'desc("j-1")'
1116 1116 3 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
1117 1117 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
1118 1118 $ hg merge 'desc("mEAm")'
1119 1119 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
1120 1120 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
1121 1121 (branch merge, don't forget to commit)
1122 1122 $ echo jj > unrelated-j
1123 1123 $ hg ci -m "mJ,EAm: $case_desc"
1124 1124 created new head
1125 1125
1126 1126
1127 1127 $ hg log -G --rev '::(desc("mAE,Km") + desc("mK,AEm") + desc("mEA,Jm") + desc("mJ,EAm"))'
1128 1128 @ mJ,EAm: chained merges (conflict -> simple) - same content everywhere
1129 1129 |\
1130 1130 +---o mEA,Jm: chained merges (conflict -> simple) - same content everywhere
1131 1131 | |/
1132 1132 | | o mK,AEm: chained merges (conflict -> simple) - same content everywhere
1133 1133 | | |\
1134 1134 | | +---o mAE,Km: chained merges (conflict -> simple) - same content everywhere
1135 1135 | | | |/
1136 1136 | | | o k-1: unrelated changes (based on "e" changes)
1137 1137 | | | |
1138 1138 | o | | j-1: unrelated changes (based on the "a" series of changes)
1139 1139 | | | |
1140 1140 o-----+ mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
1141 1141 |/ / /
1142 1142 | o / mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
1143 1143 |/|/
1144 1144 | o e-2 g -move-> f
1145 1145 | |
1146 1146 | o e-1 b -move-> g
1147 1147 | |
1148 1148 o | a-2: e -move-> f
1149 1149 | |
1150 1150 o | a-1: d -move-> e
1151 1151 |/
1152 1152 o i-2: c -move-> d, s -move-> t
1153 1153 |
1154 1154 o i-1: a -move-> c, p -move-> s
1155 1155 |
1156 1156 o i-0 initial commit: a b h p q r
1157 1157
1158 1158
1159 1159 Subcase: chaining conflicting rename resolution, with actual merging happening
1160 1160 ``````````````````````````````````````````````````````````````````````````````
1161 1161
1162 1162 The "mPQm" and "mQPm" case create a rename tracking conflict on file 't'. We
1163 1163 add more change on the respective branch and merge again. These second merge
1164 1164 does not involve the file 't' and the arbitration done within "mPQm" and "mQP"
1165 1165 about that file should stay unchanged.
1166 1166
1167 1167 $ case_desc="chained merges (conflict -> simple) - different content"
1168 1168
1169 1169 (extra unrelated changes)
1170 1170
1171 1171 $ hg up 'desc("p-2")'
1172 1172 3 files updated, 0 files merged, 3 files removed, 0 files unresolved
1173 1173 $ echo s > unrelated-s
1174 1174 $ hg add unrelated-s
1175 1175 $ hg ci -m 's-1: unrelated changes (based on the "p" series of changes)'
1176 1176 created new head
1177 1177
1178 1178 $ hg up 'desc("q-2")'
1179 1179 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
1180 1180 $ echo t > unrelated-t
1181 1181 $ hg add unrelated-t
1182 1182 $ hg ci -m 't-1: unrelated changes (based on "q" changes)'
1183 1183 created new head
1184 1184
1185 1185 (merge variant 1)
1186 1186
1187 1187 $ hg up 'desc("mPQm")'
1188 1188 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1189 1189 $ hg merge 'desc("t-1")'
1190 1190 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1191 1191 (branch merge, don't forget to commit)
1192 1192 $ hg ci -m "mPQ,Tm: $case_desc"
1193 1193
1194 1194 (merge variant 2)
1195 1195
1196 1196 $ hg up 'desc("t-1")'
1197 1197 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1198 1198
1199 1199 $ hg merge 'desc("mPQm")'
1200 1200 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1201 1201 (branch merge, don't forget to commit)
1202 1202 $ hg ci -m "mT,PQm: $case_desc"
1203 1203 created new head
1204 1204
1205 1205 (merge variant 3)
1206 1206
1207 1207 $ hg up 'desc("mQPm")'
1208 1208 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1209 1209 $ hg merge 'desc("s-1")'
1210 1210 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1211 1211 (branch merge, don't forget to commit)
1212 1212 $ hg ci -m "mQP,Sm: $case_desc"
1213 1213
1214 1214 (merge variant 4)
1215 1215
1216 1216 $ hg up 'desc("s-1")'
1217 1217 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1218 1218 $ hg merge 'desc("mQPm")'
1219 1219 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1220 1220 (branch merge, don't forget to commit)
1221 1221 $ hg ci -m "mS,QPm: $case_desc"
1222 1222 created new head
1223 1223 $ hg up null --quiet
1224 1224
1225 1225
1226 1226 $ hg log -G --rev '::(desc("mPQ,Tm") + desc("mT,PQm") + desc("mQP,Sm") + desc("mS,QPm"))'
1227 1227 o mS,QPm: chained merges (conflict -> simple) - different content
1228 1228 |\
1229 1229 +---o mQP,Sm: chained merges (conflict -> simple) - different content
1230 1230 | |/
1231 1231 | | o mT,PQm: chained merges (conflict -> simple) - different content
1232 1232 | | |\
1233 1233 | | +---o mPQ,Tm: chained merges (conflict -> simple) - different content
1234 1234 | | | |/
1235 1235 | | | o t-1: unrelated changes (based on "q" changes)
1236 1236 | | | |
1237 1237 | o | | s-1: unrelated changes (based on the "p" series of changes)
1238 1238 | | | |
1239 1239 o-----+ mQPm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - the other way
1240 1240 |/ / /
1241 1241 | o / mPQm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - one way
1242 1242 |/|/
1243 1243 | o q-2 w -move-> v
1244 1244 | |
1245 1245 | o q-1 r -move-> w
1246 1246 | |
1247 1247 o | p-2: u -move-> v
1248 1248 | |
1249 1249 o | p-1: t -move-> u
1250 1250 |/
1251 1251 o i-2: c -move-> d, s -move-> t
1252 1252 |
1253 1253 o i-1: a -move-> c, p -move-> s
1254 1254 |
1255 1255 o i-0 initial commit: a b h p q r
1256 1256
1257 1257
1258 1258 Subcase: chaining salvage information during a merge
1259 1259 ````````````````````````````````````````````````````
1260 1260
1261 1261 We add more change on the branch were the file was deleted. merging again
1262 1262 should preserve the fact eh file was salvaged.
1263 1263
1264 1264 $ case_desc="chained merges (salvaged -> simple) - same content (when the file exists)"
1265 1265
1266 1266 (creating the change)
1267 1267
1268 1268 $ hg up 'desc("c-1")'
1269 1269 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1270 1270 $ echo l > unrelated-l
1271 1271 $ hg add unrelated-l
1272 1272 $ hg ci -m 'l-1: unrelated changes (based on "c" changes)'
1273 1273 created new head
1274 1274
1275 1275 (Merge variant 1)
1276 1276
1277 1277 $ hg up 'desc("mBC-revert-m")'
1278 1278 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1279 1279 $ hg merge 'desc("l-1")'
1280 1280 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1281 1281 (branch merge, don't forget to commit)
1282 1282 $ hg ci -m "mBC+revert,Lm: $case_desc"
1283 1283
1284 1284 (Merge variant 2)
1285 1285
1286 1286 $ hg up 'desc("mCB-revert-m")'
1287 1287 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1288 1288 $ hg merge 'desc("l-1")'
1289 1289 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1290 1290 (branch merge, don't forget to commit)
1291 1291 $ hg ci -m "mCB+revert,Lm: $case_desc"
1292 1292
1293 1293 (Merge variant 3)
1294 1294
1295 1295 $ hg up 'desc("l-1")'
1296 1296 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1297 1297
1298 1298 $ hg merge 'desc("mBC-revert-m")'
1299 1299 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1300 1300 (branch merge, don't forget to commit)
1301 1301 $ hg ci -m "mL,BC+revertm: $case_desc"
1302 1302 created new head
1303 1303
1304 1304 (Merge variant 4)
1305 1305
1306 1306 $ hg up 'desc("l-1")'
1307 1307 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1308 1308
1309 1309 $ hg merge 'desc("mCB-revert-m")'
1310 1310 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1311 1311 (branch merge, don't forget to commit)
1312 1312 $ hg ci -m "mL,CB+revertm: $case_desc"
1313 1313 created new head
1314 1314
1315 1315 $ hg log -G --rev '::(desc("mBC+revert,Lm") + desc("mCB+revert,Lm") + desc("mL,BC+revertm") + desc("mL,CB+revertm"))'
1316 1316 @ mL,CB+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1317 1317 |\
1318 1318 | | o mL,BC+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1319 1319 | |/|
1320 1320 +-+---o mCB+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1321 1321 | | |
1322 1322 | +---o mBC+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1323 1323 | | |/
1324 1324 | o | l-1: unrelated changes (based on "c" changes)
1325 1325 | | |
1326 1326 | | o mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
1327 1327 | |/|
1328 1328 o---+ mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
1329 1329 |/ /
1330 1330 o | c-1 delete d
1331 1331 | |
1332 1332 | o b-1: b update
1333 1333 |/
1334 1334 o i-2: c -move-> d, s -move-> t
1335 1335 |
1336 1336 o i-1: a -move-> c, p -move-> s
1337 1337 |
1338 1338 o i-0 initial commit: a b h p q r
1339 1339
1340 1340
1341 1341
1342 1342 Subcase: chaining "merged" information during a merge
1343 1343 ``````````````````````````````````````````````````````
1344 1344
1345 1345 When a non-rename change are merged with a copy overwrite, the merge pick the copy source from (p1) as the reference. We should preserve this information in subsequent merges.
1346 1346
1347 1347 $ case_desc="chained merges (copy-overwrite -> simple) - same content"
1348 1348
1349 1349 (extra unrelated changes)
1350 1350
1351 1351 $ hg up 'desc("f-2")'
1352 1352 2 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
1353 1353 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
1354 1354 $ echo n > unrelated-n
1355 1355 $ hg add unrelated-n
1356 1356 $ hg ci -m 'n-1: unrelated changes (based on the "f" series of changes)'
1357 1357 created new head
1358 1358
1359 1359 $ hg up 'desc("g-1")'
1360 1360 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1361 1361 $ echo o > unrelated-o
1362 1362 $ hg add unrelated-o
1363 1363 $ hg ci -m 'o-1: unrelated changes (based on "g" changes)'
1364 1364 created new head
1365 1365
1366 1366 (merge variant 1)
1367 1367
1368 1368 $ hg up 'desc("mFGm")'
1369 1369 1 files updated, 0 files merged, 2 files removed, 0 files unresolved (no-changeset !)
1370 1370 0 files updated, 0 files merged, 2 files removed, 0 files unresolved (changeset !)
1371 1371 $ hg merge 'desc("o-1")'
1372 1372 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1373 1373 (branch merge, don't forget to commit)
1374 1374 $ hg ci -m "mFG,Om: $case_desc"
1375 1375
1376 1376 (merge variant 2)
1377 1377
1378 1378 $ hg up 'desc("o-1")'
1379 1379 2 files updated, 0 files merged, 0 files removed, 0 files unresolved (no-changeset !)
1380 1380 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (changeset !)
1381 1381 $ hg merge 'desc("FGm")'
1382 1382 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (no-changeset !)
1383 1383 0 files updated, 0 files merged, 1 files removed, 0 files unresolved (changeset !)
1384 1384 (branch merge, don't forget to commit)
1385 1385 $ hg ci -m "mO,FGm: $case_desc"
1386 1386 created new head
1387 1387
1388 1388 (merge variant 3)
1389 1389
1390 1390 $ hg up 'desc("mGFm")'
1391 1391 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1392 1392 $ hg merge 'desc("n-1")'
1393 1393 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1394 1394 (branch merge, don't forget to commit)
1395 1395 $ hg ci -m "mGF,Nm: $case_desc"
1396 1396
1397 1397 (merge variant 4)
1398 1398
1399 1399 $ hg up 'desc("n-1")'
1400 1400 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1401 1401 $ hg merge 'desc("mGFm")'
1402 1402 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1403 1403 (branch merge, don't forget to commit)
1404 1404 $ hg ci -m "mN,GFm: $case_desc"
1405 1405 created new head
1406 1406
1407 1407 $ hg log -G --rev '::(desc("mFG,Om") + desc("mO,FGm") + desc("mGF,Nm") + desc("mN,GFm"))'
1408 1408 @ mN,GFm: chained merges (copy-overwrite -> simple) - same content
1409 1409 |\
1410 1410 +---o mGF,Nm: chained merges (copy-overwrite -> simple) - same content
1411 1411 | |/
1412 1412 | | o mO,FGm: chained merges (copy-overwrite -> simple) - same content
1413 1413 | | |\
1414 1414 | | +---o mFG,Om: chained merges (copy-overwrite -> simple) - same content
1415 1415 | | | |/
1416 1416 | | | o o-1: unrelated changes (based on "g" changes)
1417 1417 | | | |
1418 1418 | o | | n-1: unrelated changes (based on the "f" series of changes)
1419 1419 | | | |
1420 1420 o-----+ mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
1421 1421 |/ / /
1422 1422 | o / mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
1423 1423 |/|/
1424 1424 | o g-1: update d
1425 1425 | |
1426 1426 o | f-2: rename i -> d
1427 1427 | |
1428 1428 o | f-1: rename h -> i
1429 1429 |/
1430 1430 o i-2: c -move-> d, s -move-> t
1431 1431 |
1432 1432 o i-1: a -move-> c, p -move-> s
1433 1433 |
1434 1434 o i-0 initial commit: a b h p q r
1435 1435
1436 1436
1437 1437 Subcase: chaining conflicting rename resolution, with extra change during the merge
1438 1438 ```````````````````````````````````````````````````````````````````````````````````
1439 1439
1440 1440 The "mEA-change-m-0" and "mAE-change-m-0" case create a rename tracking conflict on file 'f'. We
1441 1441 add more change on the respective branch and merge again. These second merge
1442 1442 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
1443 1443 about that file should stay unchanged.
1444 1444
1445 1445 $ case_desc="chained merges (conflict+change -> simple) - same content on both branch in the initial merge"
1446 1446
1447 1447
1448 1448 (merge variant 1)
1449 1449
1450 1450 $ hg up 'desc("mAE-change-m")'
1451 1451 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
1452 1452 $ hg merge 'desc("k-1")'
1453 1453 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1454 1454 (branch merge, don't forget to commit)
1455 1455 $ hg ci -m "mAE-change,Km: $case_desc"
1456 1456
1457 1457 (merge variant 2)
1458 1458
1459 1459 $ hg up 'desc("k-1")'
1460 1460 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1461 1461
1462 1462 $ hg merge 'desc("mAE-change-m")'
1463 1463 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1464 1464 (branch merge, don't forget to commit)
1465 1465 $ hg ci -m "mK,AE-change-m: $case_desc"
1466 1466 created new head
1467 1467
1468 1468 (merge variant 3)
1469 1469
1470 1470 $ hg up 'desc("mEA-change-m")'
1471 1471 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1472 1472 $ hg merge 'desc("j-1")'
1473 1473 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1474 1474 (branch merge, don't forget to commit)
1475 1475 $ hg ci -m "mEA-change,Jm: $case_desc"
1476 1476
1477 1477 (merge variant 4)
1478 1478
1479 1479 $ hg up 'desc("j-1")'
1480 1480 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1481 1481 $ hg merge 'desc("mEA-change-m")'
1482 1482 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1483 1483 (branch merge, don't forget to commit)
1484 1484 $ hg ci -m "mJ,EA-change-m: $case_desc"
1485 1485 created new head
1486 1486
1487 1487
1488 1488 $ hg log -G --rev '::(desc("mAE-change,Km") + desc("mK,AE-change-m") + desc("mEA-change,Jm") + desc("mJ,EA-change-m"))'
1489 1489 @ mJ,EA-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1490 1490 |\
1491 1491 +---o mEA-change,Jm: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1492 1492 | |/
1493 1493 | | o mK,AE-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1494 1494 | | |\
1495 1495 | | +---o mAE-change,Km: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1496 1496 | | | |/
1497 1497 | | | o k-1: unrelated changes (based on "e" changes)
1498 1498 | | | |
1499 1499 | o | | j-1: unrelated changes (based on the "a" series of changes)
1500 1500 | | | |
1501 1501 o-----+ mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
1502 1502 |/ / /
1503 1503 | o / mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
1504 1504 |/|/
1505 1505 | o e-2 g -move-> f
1506 1506 | |
1507 1507 | o e-1 b -move-> g
1508 1508 | |
1509 1509 o | a-2: e -move-> f
1510 1510 | |
1511 1511 o | a-1: d -move-> e
1512 1512 |/
1513 1513 o i-2: c -move-> d, s -move-> t
1514 1514 |
1515 1515 o i-1: a -move-> c, p -move-> s
1516 1516 |
1517 1517 o i-0 initial commit: a b h p q r
1518 1518
1519 1519
1520 1520 Summary of all created cases
1521 1521 ----------------------------
1522 1522
1523 1523 $ hg up --quiet null
1524 1524
1525 1525 (This exists to help keeping a compact list of the various cases we have built)
1526 1526
1527 1527 $ hg log -T '{desc|firstline}\n'| sort
1528 1528 a-1: d -move-> e
1529 1529 a-2: e -move-> f
1530 1530 b-1: b update
1531 1531 c-1 delete d
1532 1532 d-1 delete d
1533 1533 d-2 re-add d
1534 1534 e-1 b -move-> g
1535 1535 e-2 g -move-> f
1536 1536 f-1: rename h -> i
1537 1537 f-2: rename i -> d
1538 1538 g-1: update d
1539 1539 h-1: b -(move)-> d
1540 1540 i-0 initial commit: a b h p q r
1541 1541 i-1: a -move-> c, p -move-> s
1542 1542 i-2: c -move-> d, s -move-> t
1543 1543 j-1: unrelated changes (based on the "a" series of changes)
1544 1544 k-1: unrelated changes (based on "e" changes)
1545 1545 l-1: unrelated changes (based on "c" changes)
1546 1546 mABm-0 simple merge - A side: multiple renames, B side: unrelated update - the other way
1547 1547 mAE,Km: chained merges (conflict -> simple) - same content everywhere
1548 1548 mAE-change,Km: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1549 1549 mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
1550 1550 mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
1551 1551 mBAm-0 simple merge - A side: multiple renames, B side: unrelated update - one way
1552 1552 mBC+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1553 1553 mBC-change-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
1554 1554 mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
1555 1555 mBCm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - one way
1556 1556 mBCm-1 re-add d
1557 1557 mBDm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - one way
1558 1558 mBF-change-m-0 merge with extra change - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
1559 1559 mBFm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
1560 1560 mBRm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - one way
1561 1561 mCB+revert,Lm: chained merges (salvaged -> simple) - same content (when the file exists)
1562 1562 mCB-change-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
1563 1563 mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
1564 1564 mCBm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - the other way
1565 1565 mCBm-1 re-add d
1566 1566 mCGm-0 merge updated/deleted - revive the file (updated content) - one way
1567 1567 mCH-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - one way
1568 1568 mDBm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - the other way
1569 1569 mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
1570 1570 mEA,Jm: chained merges (conflict -> simple) - same content everywhere
1571 1571 mEA-change,Jm: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1572 1572 mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
1573 1573 mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
1574 1574 mFB-change-m-0 merge with extra change - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
1575 1575 mFBm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
1576 1576 mFG,Om: chained merges (copy-overwrite -> simple) - same content
1577 1577 mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
1578 1578 mGCm-0 merge updated/deleted - revive the file (updated content) - the other way
1579 1579 mGDm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - the other way
1580 1580 mGF,Nm: chained merges (copy-overwrite -> simple) - same content
1581 1581 mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
1582 1582 mHC-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - the other way
1583 1583 mJ,EA-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1584 1584 mJ,EAm: chained merges (conflict -> simple) - same content everywhere
1585 1585 mK,AE-change-m: chained merges (conflict+change -> simple) - same content on both branch in the initial merge
1586 1586 mK,AEm: chained merges (conflict -> simple) - same content everywhere
1587 1587 mL,BC+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1588 1588 mL,CB+revertm: chained merges (salvaged -> simple) - same content (when the file exists)
1589 1589 mN,GFm: chained merges (copy-overwrite -> simple) - same content
1590 1590 mO,FGm: chained merges (copy-overwrite -> simple) - same content
1591 1591 mPQ,Tm: chained merges (conflict -> simple) - different content
1592 1592 mPQm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - one way
1593 1593 mQP,Sm: chained merges (conflict -> simple) - different content
1594 1594 mQPm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - the other way
1595 1595 mRBm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - the other way
1596 1596 mS,QPm: chained merges (conflict -> simple) - different content
1597 1597 mT,PQm: chained merges (conflict -> simple) - different content
1598 1598 n-1: unrelated changes (based on the "f" series of changes)
1599 1599 o-1: unrelated changes (based on "g" changes)
1600 1600 p-1: t -move-> u
1601 1601 p-2: u -move-> v
1602 1602 q-1 r -move-> w
1603 1603 q-2 w -move-> v
1604 1604 r-1: rename r -> x
1605 1605 r-2: rename t -> x
1606 1606 s-1: unrelated changes (based on the "p" series of changes)
1607 1607 t-1: unrelated changes (based on "q" changes)
1608 1608
1609 1609
1610 1610 Test that sidedata computations during upgrades are correct
1611 1611 ===========================================================
1612 1612
1613 1613 We upgrade a repository that is not using sidedata (the filelog case) and
1614 1614 check that the same side data have been generated as if they were computed at
1615 1615 commit time.
1616 1616
1617 1617
1618 1618 #if upgraded
1619 1619 $ cat >> $HGRCPATH << EOF
1620 1620 > [format]
1621 1621 > exp-use-side-data = yes
1622 1622 > exp-use-copies-side-data-changeset = yes
1623 1623 > EOF
1624 1624 $ hg debugformat -v
1625 1625 format-variant repo config default
1626 1626 fncache: yes yes yes
1627 1627 dotencode: yes yes yes
1628 1628 generaldelta: yes yes yes
1629 1629 share-safe: no no no
1630 1630 sparserevlog: yes yes yes
1631 1631 persistent-nodemap: no no no
1632 1632 copies-sdc: no yes no
1633 1633 revlog-v2: no yes no
1634 1634 plain-cl-delta: yes yes yes
1635 1635 compression: * (glob)
1636 1636 compression-level: default default default
1637 1637 $ hg debugupgraderepo --run --quiet
1638 1638 upgrade will perform the following actions:
1639 1639
1640 1640 requirements
1641 1641 preserved: * (glob)
1642 1642 removed: revlogv1
1643 1643 added: exp-copies-sidedata-changeset, exp-revlogv2.2, exp-sidedata-flag
1644 1644
1645 1645 processed revlogs:
1646 1646 - all-filelogs
1647 1647 - changelog
1648 1648 - manifest
1649 1649
1650 1650 #endif
1651 1651
1652 1652 #if upgraded-parallel
1653 1653 $ cat >> $HGRCPATH << EOF
1654 1654 > [format]
1655 1655 > exp-use-side-data = yes
1656 1656 > exp-use-copies-side-data-changeset = yes
1657 1657 > [experimental]
1658 1658 > worker.repository-upgrade=yes
1659 1659 > [worker]
1660 1660 > enabled=yes
1661 1661 > numcpus=8
1662 1662 > EOF
1663 1663 $ hg debugformat -v
1664 1664 format-variant repo config default
1665 1665 fncache: yes yes yes
1666 1666 dotencode: yes yes yes
1667 1667 generaldelta: yes yes yes
1668 1668 share-safe: no no no
1669 1669 sparserevlog: yes yes yes
1670 1670 persistent-nodemap: no no no
1671 1671 copies-sdc: no yes no
1672 1672 revlog-v2: no yes no
1673 1673 plain-cl-delta: yes yes yes
1674 1674 compression: * (glob)
1675 1675 compression-level: default default default
1676 1676 $ hg debugupgraderepo --run --quiet
1677 1677 upgrade will perform the following actions:
1678 1678
1679 1679 requirements
1680 1680 preserved: * (glob)
1681 1681 removed: revlogv1
1682 1682 added: exp-copies-sidedata-changeset, exp-revlogv2.2, exp-sidedata-flag
1683 1683
1684 1684 processed revlogs:
1685 1685 - all-filelogs
1686 1686 - changelog
1687 1687 - manifest
1688 1688
1689 1689 #endif
1690 1690
1691 1691
1692 1692 #if no-compatibility no-filelog no-changeset
1693 1693
1694 1694 $ hg debugchangedfiles --compute 0
1695 1695 added : a, ;
1696 1696 added : b, ;
1697 1697 added : h, ;
1698 1698 added : p, ;
1699 1699 added : q, ;
1700 1700 added : r, ;
1701 1701
1702 1702 $ for rev in `hg log --rev 'all()' -T '{rev}\n'`; do
1703 1703 > case_id=`hg log -r $rev -T '{word(0, desc, ":")}\n'`
1704 1704 > echo "##### revision \"$case_id\" #####"
1705 1705 > hg debugsidedata -c -v -- $rev
1706 1706 > hg debugchangedfiles $rev
1707 1707 > done
1708 1708 ##### revision "i-0 initial commit" #####
1709 1709 1 sidedata entries
1710 1710 entry-0014 size 64
1711 1711 '\x00\x00\x00\x06\x04\x00\x00\x00\x01\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x00\x04\x00\x00\x00\x06\x00\x00\x00\x00abhpqr'
1712 1712 added : a, ;
1713 1713 added : b, ;
1714 1714 added : h, ;
1715 1715 added : p, ;
1716 1716 added : q, ;
1717 1717 added : r, ;
1718 1718 ##### revision "i-1" #####
1719 1719 1 sidedata entries
1720 1720 entry-0014 size 44
1721 1721 '\x00\x00\x00\x04\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00\x0c\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x02acps'
1722 1722 removed : a, ;
1723 1723 added p1: c, a;
1724 1724 removed : p, ;
1725 1725 added p1: s, p;
1726 1726 ##### revision "i-2" #####
1727 1727 1 sidedata entries
1728 1728 entry-0014 size 44
1729 1729 '\x00\x00\x00\x04\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00\x0c\x00\x00\x00\x03\x00\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x02cdst'
1730 1730 removed : c, ;
1731 1731 added p1: d, c;
1732 1732 removed : s, ;
1733 1733 added p1: t, s;
1734 1734 ##### revision "a-1" #####
1735 1735 1 sidedata entries
1736 1736 entry-0014 size 24
1737 1737 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00de'
1738 1738 removed : d, ;
1739 1739 added p1: e, d;
1740 1740 ##### revision "a-2" #####
1741 1741 1 sidedata entries
1742 1742 entry-0014 size 24
1743 1743 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00ef'
1744 1744 removed : e, ;
1745 1745 added p1: f, e;
1746 1746 ##### revision "b-1" #####
1747 1747 1 sidedata entries
1748 1748 entry-0014 size 14
1749 1749 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00b'
1750 1750 touched : b, ;
1751 1751 ##### revision "c-1 delete d" #####
1752 1752 1 sidedata entries
1753 1753 entry-0014 size 14
1754 1754 '\x00\x00\x00\x01\x0c\x00\x00\x00\x01\x00\x00\x00\x00d'
1755 1755 removed : d, ;
1756 1756 ##### revision "d-1 delete d" #####
1757 1757 1 sidedata entries
1758 1758 entry-0014 size 14
1759 1759 '\x00\x00\x00\x01\x0c\x00\x00\x00\x01\x00\x00\x00\x00d'
1760 1760 removed : d, ;
1761 1761 ##### revision "d-2 re-add d" #####
1762 1762 1 sidedata entries
1763 1763 entry-0014 size 14
1764 1764 '\x00\x00\x00\x01\x04\x00\x00\x00\x01\x00\x00\x00\x00d'
1765 1765 added : d, ;
1766 1766 ##### revision "e-1 b -move-> g" #####
1767 1767 1 sidedata entries
1768 1768 entry-0014 size 24
1769 1769 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00bg'
1770 1770 removed : b, ;
1771 1771 added p1: g, b;
1772 1772 ##### revision "e-2 g -move-> f" #####
1773 1773 1 sidedata entries
1774 1774 entry-0014 size 24
1775 1775 '\x00\x00\x00\x02\x06\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00fg'
1776 1776 added p1: f, g;
1777 1777 removed : g, ;
1778 1778 ##### revision "p-1" #####
1779 1779 1 sidedata entries
1780 1780 entry-0014 size 24
1781 1781 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00tu'
1782 1782 removed : t, ;
1783 1783 added p1: u, t;
1784 1784 ##### revision "p-2" #####
1785 1785 1 sidedata entries
1786 1786 entry-0014 size 24
1787 1787 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00uv'
1788 1788 removed : u, ;
1789 1789 added p1: v, u;
1790 1790 ##### revision "q-1 r -move-> w" #####
1791 1791 1 sidedata entries
1792 1792 entry-0014 size 24
1793 1793 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00rw'
1794 1794 removed : r, ;
1795 1795 added p1: w, r;
1796 1796 ##### revision "q-2 w -move-> v" #####
1797 1797 1 sidedata entries
1798 1798 entry-0014 size 24
1799 1799 '\x00\x00\x00\x02\x06\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00vw'
1800 1800 added p1: v, w;
1801 1801 removed : w, ;
1802 1802 ##### revision "mBAm-0 simple merge - A side" #####
1803 1803 1 sidedata entries
1804 1804 entry-0014 size 4
1805 1805 '\x00\x00\x00\x00'
1806 1806 ##### revision "mABm-0 simple merge - A side" #####
1807 1807 1 sidedata entries
1808 1808 entry-0014 size 4
1809 1809 '\x00\x00\x00\x00'
1810 1810 ##### revision "mBCm-0 simple merge - C side" #####
1811 1811 1 sidedata entries
1812 1812 entry-0014 size 4
1813 1813 '\x00\x00\x00\x00'
1814 1814 ##### revision "mBCm-1 re-add d" #####
1815 1815 1 sidedata entries
1816 1816 entry-0014 size 14
1817 1817 '\x00\x00\x00\x01\x04\x00\x00\x00\x01\x00\x00\x00\x00d'
1818 1818 added : d, ;
1819 1819 ##### revision "mCBm-0 simple merge - C side" #####
1820 1820 1 sidedata entries
1821 1821 entry-0014 size 4
1822 1822 '\x00\x00\x00\x00'
1823 1823 ##### revision "mCBm-1 re-add d" #####
1824 1824 1 sidedata entries
1825 1825 entry-0014 size 14
1826 1826 '\x00\x00\x00\x01\x04\x00\x00\x00\x01\x00\x00\x00\x00d'
1827 1827 added : d, ;
1828 1828 ##### revision "mBDm-0 simple merge - B side" #####
1829 1829 1 sidedata entries
1830 1830 entry-0014 size 4
1831 1831 '\x00\x00\x00\x00'
1832 1832 ##### revision "mDBm-0 simple merge - B side" #####
1833 1833 1 sidedata entries
1834 1834 entry-0014 size 4
1835 1835 '\x00\x00\x00\x00'
1836 1836 ##### revision "mAEm-0 merge with copies info on both side - A side" #####
1837 1837 1 sidedata entries
1838 1838 entry-0014 size 14
1839 1839 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1840 1840 merged : f, ;
1841 1841 ##### revision "mEAm-0 merge with copies info on both side - A side" #####
1842 1842 1 sidedata entries
1843 1843 entry-0014 size 14
1844 1844 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1845 1845 merged : f, ;
1846 1846 ##### revision "mPQm-0 merge with copies info on both side - P side" #####
1847 1847 1 sidedata entries
1848 1848 entry-0014 size 14
1849 1849 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00v'
1850 1850 merged : v, ;
1851 1851 ##### revision "mQPm-0 merge with copies info on both side - P side" #####
1852 1852 1 sidedata entries
1853 1853 entry-0014 size 14
1854 1854 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00v'
1855 1855 merged : v, ;
1856 1856 ##### revision "f-1" #####
1857 1857 1 sidedata entries
1858 1858 entry-0014 size 24
1859 1859 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00hi'
1860 1860 removed : h, ;
1861 1861 added p1: i, h;
1862 1862 ##### revision "f-2" #####
1863 1863 1 sidedata entries
1864 1864 entry-0014 size 24
1865 1865 '\x00\x00\x00\x02\x16\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00di'
1866 1866 touched p1: d, i;
1867 1867 removed : i, ;
1868 1868 ##### revision "mBFm-0 simple merge - B side" #####
1869 1869 1 sidedata entries
1870 1870 entry-0014 size 4
1871 1871 '\x00\x00\x00\x00'
1872 1872 ##### revision "mFBm-0 simple merge - B side" #####
1873 1873 1 sidedata entries
1874 1874 entry-0014 size 4
1875 1875 '\x00\x00\x00\x00'
1876 1876 ##### revision "r-1" #####
1877 1877 1 sidedata entries
1878 1878 entry-0014 size 24
1879 1879 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00rx'
1880 1880 removed : r, ;
1881 1881 added p1: x, r;
1882 1882 ##### revision "r-2" #####
1883 1883 1 sidedata entries
1884 1884 entry-0014 size 24
1885 1885 '\x00\x00\x00\x02\x16\x00\x00\x00\x01\x00\x00\x00\x01\x0c\x00\x00\x00\x02\x00\x00\x00\x00tx'
1886 1886 touched p1: t, x;
1887 1887 removed : x, ;
1888 1888 ##### revision "mBRm-0 simple merge - B side" #####
1889 1889 1 sidedata entries
1890 1890 entry-0014 size 4
1891 1891 '\x00\x00\x00\x00'
1892 1892 ##### revision "mRBm-0 simple merge - B side" #####
1893 1893 1 sidedata entries
1894 1894 entry-0014 size 4
1895 1895 '\x00\x00\x00\x00'
1896 1896 ##### revision "g-1" #####
1897 1897 1 sidedata entries
1898 1898 entry-0014 size 14
1899 1899 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00d'
1900 1900 touched : d, ;
1901 1901 ##### revision "mDGm-0 actual content merge, copies on one side - D side" #####
1902 1902 1 sidedata entries
1903 1903 entry-0014 size 14
1904 1904 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1905 1905 merged : d, ;
1906 1906 ##### revision "mGDm-0 actual content merge, copies on one side - D side" #####
1907 1907 1 sidedata entries
1908 1908 entry-0014 size 14
1909 1909 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1910 1910 merged : d, ;
1911 1911 ##### revision "mFGm-0 merge - G side" #####
1912 1912 1 sidedata entries
1913 1913 entry-0014 size 14
1914 1914 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1915 1915 merged : d, ;
1916 1916 ##### revision "mGFm-0 merge - G side" #####
1917 1917 1 sidedata entries
1918 1918 entry-0014 size 14
1919 1919 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d'
1920 1920 merged : d, ;
1921 1921 ##### revision "mCGm-0 merge updated/deleted - revive the file (updated content) - one way" #####
1922 1922 1 sidedata entries
1923 1923 entry-0014 size 14
1924 1924 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1925 1925 salvaged : d, ;
1926 1926 ##### revision "mGCm-0 merge updated/deleted - revive the file (updated content) - the other way" #####
1927 1927 1 sidedata entries
1928 1928 entry-0014 size 14
1929 1929 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1930 1930 salvaged : d, ;
1931 1931 ##### revision "mCB-revert-m-0 merge explicitely revive deleted file - B side" #####
1932 1932 1 sidedata entries
1933 1933 entry-0014 size 14
1934 1934 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1935 1935 salvaged : d, ;
1936 1936 ##### revision "mBC-revert-m-0 merge explicitely revive deleted file - B side" #####
1937 1937 1 sidedata entries
1938 1938 entry-0014 size 14
1939 1939 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1940 1940 salvaged : d, ;
1941 1941 ##### revision "h-1" #####
1942 1942 1 sidedata entries
1943 1943 entry-0014 size 24
1944 1944 '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00bd'
1945 1945 removed : b, ;
1946 1946 added p1: d, b;
1947 1947 ##### revision "mCH-delete-before-conflict-m-0 simple merge - C side" #####
1948 1948 1 sidedata entries
1949 1949 entry-0014 size 4
1950 1950 '\x00\x00\x00\x00'
1951 1951 ##### revision "mHC-delete-before-conflict-m-0 simple merge - C side" #####
1952 1952 1 sidedata entries
1953 1953 entry-0014 size 4
1954 1954 '\x00\x00\x00\x00'
1955 1955 ##### revision "mAE-change-m-0 merge with file update and copies info on both side - A side" #####
1956 1956 1 sidedata entries
1957 1957 entry-0014 size 14
1958 1958 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1959 1959 merged : f, ;
1960 1960 ##### revision "mEA-change-m-0 merge with file update and copies info on both side - A side" #####
1961 1961 1 sidedata entries
1962 1962 entry-0014 size 14
1963 1963 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00f'
1964 1964 merged : f, ;
1965 1965 ##### revision "mBF-change-m-0 merge with extra change - B side" #####
1966 1966 1 sidedata entries
1967 1967 entry-0014 size 14
1968 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00d' (no-upgraded no-upgraded-parallel !)
1969 touched : d, ; (no-upgraded no-upgraded-parallel !)
1970 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00d' (upgraded missing-correct-output !)
1971 touched : d, ; (upgraded missing-correct-output !)
1972 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d' (upgraded known-bad-output !)
1973 merged : d, ; (upgraded known-bad-output !)
1974 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00d' (upgraded-parallel missing-correct-output !)
1975 touched : d, ; (upgraded-parallel missing-correct-output !)
1976 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d' (upgraded-parallel known-bad-output !)
1977 merged : d, ; (upgraded-parallel known-bad-output !)
1968 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00d'
1969 touched : d, ;
1978 1970 ##### revision "mFB-change-m-0 merge with extra change - B side" #####
1979 1971 1 sidedata entries
1980 1972 entry-0014 size 14
1981 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00d' (no-upgraded no-upgraded-parallel !)
1982 touched : d, ; (no-upgraded no-upgraded-parallel !)
1983 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d' (upgraded-parallel known-bad-output !)
1984 merged : d, ; (upgraded-parallel known-bad-output !)
1985 '\x00\x00\x00\x01\x08\x00\x00\x00\x01\x00\x00\x00\x00d' (upgraded known-bad-output !)
1986 merged : d, ; (upgraded known-bad-output !)
1973 '\x00\x00\x00\x01\x14\x00\x00\x00\x01\x00\x00\x00\x00d'
1974 touched : d, ;
1987 1975 ##### revision "mCB-change-m-0 merge explicitely revive deleted file - B side" #####
1988 1976 1 sidedata entries
1989 1977 entry-0014 size 14
1990 1978 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1991 1979 salvaged : d, ;
1992 1980 ##### revision "mBC-change-m-0 merge explicitely revive deleted file - B side" #####
1993 1981 1 sidedata entries
1994 1982 entry-0014 size 14
1995 1983 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d'
1996 1984 salvaged : d, ;
1997 1985 ##### revision "j-1" #####
1998 1986 1 sidedata entries
1999 1987 entry-0014 size 24
2000 1988 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-j'
2001 1989 added : unrelated-j, ;
2002 1990 ##### revision "k-1" #####
2003 1991 1 sidedata entries
2004 1992 entry-0014 size 24
2005 1993 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-k'
2006 1994 added : unrelated-k, ;
2007 1995 ##### revision "mAE,Km" #####
2008 1996 1 sidedata entries
2009 1997 entry-0014 size 4
2010 1998 '\x00\x00\x00\x00'
2011 1999 ##### revision "mK,AEm" #####
2012 2000 1 sidedata entries
2013 2001 entry-0014 size 4
2014 2002 '\x00\x00\x00\x00'
2015 2003 ##### revision "mEA,Jm" #####
2016 2004 1 sidedata entries
2017 2005 entry-0014 size 24
2018 2006 '\x00\x00\x00\x01\x14\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-j'
2019 2007 touched : unrelated-j, ;
2020 2008 ##### revision "mJ,EAm" #####
2021 2009 1 sidedata entries
2022 2010 entry-0014 size 24
2023 2011 '\x00\x00\x00\x01\x14\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-j'
2024 2012 touched : unrelated-j, ;
2025 2013 ##### revision "s-1" #####
2026 2014 1 sidedata entries
2027 2015 entry-0014 size 24
2028 2016 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-s'
2029 2017 added : unrelated-s, ;
2030 2018 ##### revision "t-1" #####
2031 2019 1 sidedata entries
2032 2020 entry-0014 size 24
2033 2021 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-t'
2034 2022 added : unrelated-t, ;
2035 2023 ##### revision "mPQ,Tm" #####
2036 2024 1 sidedata entries
2037 2025 entry-0014 size 4
2038 2026 '\x00\x00\x00\x00'
2039 2027 ##### revision "mT,PQm" #####
2040 2028 1 sidedata entries
2041 2029 entry-0014 size 4
2042 2030 '\x00\x00\x00\x00'
2043 2031 ##### revision "mQP,Sm" #####
2044 2032 1 sidedata entries
2045 2033 entry-0014 size 4
2046 2034 '\x00\x00\x00\x00'
2047 2035 ##### revision "mS,QPm" #####
2048 2036 1 sidedata entries
2049 2037 entry-0014 size 4
2050 2038 '\x00\x00\x00\x00'
2051 2039 ##### revision "l-1" #####
2052 2040 1 sidedata entries
2053 2041 entry-0014 size 24
2054 2042 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-l'
2055 2043 added : unrelated-l, ;
2056 2044 ##### revision "mBC+revert,Lm" #####
2057 2045 1 sidedata entries
2058 2046 entry-0014 size 4
2059 2047 '\x00\x00\x00\x00'
2060 2048 ##### revision "mCB+revert,Lm" #####
2061 2049 1 sidedata entries
2062 2050 entry-0014 size 4
2063 2051 '\x00\x00\x00\x00'
2064 2052 ##### revision "mL,BC+revertm" #####
2065 2053 1 sidedata entries
2066 2054 entry-0014 size 4
2067 2055 '\x00\x00\x00\x00'
2068 2056 ##### revision "mL,CB+revertm" #####
2069 2057 1 sidedata entries
2070 2058 entry-0014 size 4
2071 2059 '\x00\x00\x00\x00'
2072 2060 ##### revision "n-1" #####
2073 2061 1 sidedata entries
2074 2062 entry-0014 size 24
2075 2063 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-n'
2076 2064 added : unrelated-n, ;
2077 2065 ##### revision "o-1" #####
2078 2066 1 sidedata entries
2079 2067 entry-0014 size 24
2080 2068 '\x00\x00\x00\x01\x04\x00\x00\x00\x0b\x00\x00\x00\x00unrelated-o'
2081 2069 added : unrelated-o, ;
2082 2070 ##### revision "mFG,Om" #####
2083 2071 1 sidedata entries
2084 2072 entry-0014 size 4
2085 2073 '\x00\x00\x00\x00'
2086 2074 ##### revision "mO,FGm" #####
2087 2075 1 sidedata entries
2088 2076 entry-0014 size 4
2089 2077 '\x00\x00\x00\x00'
2090 2078 ##### revision "mGF,Nm" #####
2091 2079 1 sidedata entries
2092 2080 entry-0014 size 4
2093 2081 '\x00\x00\x00\x00'
2094 2082 ##### revision "mN,GFm" #####
2095 2083 1 sidedata entries
2096 2084 entry-0014 size 4
2097 2085 '\x00\x00\x00\x00'
2098 2086 ##### revision "mAE-change,Km" #####
2099 2087 1 sidedata entries
2100 2088 entry-0014 size 4
2101 2089 '\x00\x00\x00\x00'
2102 2090 ##### revision "mK,AE-change-m" #####
2103 2091 1 sidedata entries
2104 2092 entry-0014 size 4
2105 2093 '\x00\x00\x00\x00'
2106 2094 ##### revision "mEA-change,Jm" #####
2107 2095 1 sidedata entries
2108 2096 entry-0014 size 4
2109 2097 '\x00\x00\x00\x00'
2110 2098 ##### revision "mJ,EA-change-m" #####
2111 2099 1 sidedata entries
2112 2100 entry-0014 size 4
2113 2101 '\x00\x00\x00\x00'
2114 2102
2115 2103 #endif
2116 2104
2117 2105
2118 2106 Test copy information chaining
2119 2107 ==============================
2120 2108
2121 2109 Check that matching only affect the destination and not intermediate path
2122 2110 -------------------------------------------------------------------------
2123 2111
2124 2112 The two status call should give the same value for f
2125 2113
2126 2114 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("a-2")'
2127 2115 A f
2128 2116 a
2129 2117 A t
2130 2118 p
2131 2119 R a
2132 2120 R p
2133 2121 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("a-2")' f
2134 2122 A f
2135 2123 a (no-changeset no-compatibility !)
2136 2124
2137 2125 merging with unrelated change does not interfere with the renames
2138 2126 ---------------------------------------------------------------
2139 2127
2140 2128 - rename on one side
2141 2129 - unrelated change on the other side
2142 2130
2143 2131 $ hg log -G --rev '::(desc("mABm")+desc("mBAm"))'
2144 2132 o mABm-0 simple merge - A side: multiple renames, B side: unrelated update - the other way
2145 2133 |\
2146 2134 +---o mBAm-0 simple merge - A side: multiple renames, B side: unrelated update - one way
2147 2135 | |/
2148 2136 | o b-1: b update
2149 2137 | |
2150 2138 o | a-2: e -move-> f
2151 2139 | |
2152 2140 o | a-1: d -move-> e
2153 2141 |/
2154 2142 o i-2: c -move-> d, s -move-> t
2155 2143 |
2156 2144 o i-1: a -move-> c, p -move-> s
2157 2145 |
2158 2146 o i-0 initial commit: a b h p q r
2159 2147
2160 2148
2161 2149 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mABm")'
2162 2150 A f
2163 2151 d
2164 2152 R d
2165 2153 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBAm")'
2166 2154 A f
2167 2155 d
2168 2156 R d
2169 2157 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mABm")'
2170 2158 M b
2171 2159 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mBAm")'
2172 2160 M b
2173 2161 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mABm")'
2174 2162 M b
2175 2163 A f
2176 2164 d
2177 2165 R d
2178 2166 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBAm")'
2179 2167 M b
2180 2168 A f
2181 2169 d
2182 2170 R d
2183 2171 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mABm")'
2184 2172 M b
2185 2173 A f
2186 2174 a
2187 2175 A t
2188 2176 p
2189 2177 R a
2190 2178 R p
2191 2179 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBAm")'
2192 2180 M b
2193 2181 A f
2194 2182 a
2195 2183 A t
2196 2184 p
2197 2185 R a
2198 2186 R p
2199 2187
2200 2188 merging with the side having a delete
2201 2189 -------------------------------------
2202 2190
2203 2191 case summary:
2204 2192 - one with change to an unrelated file
2205 2193 - one deleting the change
2206 2194 and recreate an unrelated file after the merge
2207 2195
2208 2196 $ hg log -G --rev '::(desc("mCBm")+desc("mBCm"))'
2209 2197 o mCBm-1 re-add d
2210 2198 |
2211 2199 o mCBm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - the other way
2212 2200 |\
2213 2201 | | o mBCm-1 re-add d
2214 2202 | | |
2215 2203 +---o mBCm-0 simple merge - C side: delete a file with copies history , B side: unrelated update - one way
2216 2204 | |/
2217 2205 | o c-1 delete d
2218 2206 | |
2219 2207 o | b-1: b update
2220 2208 |/
2221 2209 o i-2: c -move-> d, s -move-> t
2222 2210 |
2223 2211 o i-1: a -move-> c, p -move-> s
2224 2212 |
2225 2213 o i-0 initial commit: a b h p q r
2226 2214
2227 2215 - comparing from the merge
2228 2216
2229 2217 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBCm-0")'
2230 2218 R d
2231 2219 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCBm-0")'
2232 2220 R d
2233 2221 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBCm-0")'
2234 2222 M b
2235 2223 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCBm-0")'
2236 2224 M b
2237 2225 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBCm-0")'
2238 2226 M b
2239 2227 R d
2240 2228 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mCBm-0")'
2241 2229 M b
2242 2230 R d
2243 2231 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBCm-0")'
2244 2232 M b
2245 2233 A t
2246 2234 p
2247 2235 R a
2248 2236 R p
2249 2237 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCBm-0")'
2250 2238 M b
2251 2239 A t
2252 2240 p
2253 2241 R a
2254 2242 R p
2255 2243
2256 2244 - comparing with the merge children re-adding the file
2257 2245
2258 2246 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBCm-1")'
2259 2247 M d
2260 2248 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCBm-1")'
2261 2249 M d
2262 2250 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBCm-1")'
2263 2251 M b
2264 2252 A d
2265 2253 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCBm-1")'
2266 2254 M b
2267 2255 A d
2268 2256 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBCm-1")'
2269 2257 M b
2270 2258 M d
2271 2259 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mCBm-1")'
2272 2260 M b
2273 2261 M d
2274 2262 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBCm-1")'
2275 2263 M b
2276 2264 A d
2277 2265 A t
2278 2266 p
2279 2267 R a
2280 2268 R p
2281 2269 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCBm-1")'
2282 2270 M b
2283 2271 A d
2284 2272 A t
2285 2273 p
2286 2274 R a
2287 2275 R p
2288 2276
2289 2277 Comparing with a merge re-adding the file afterward
2290 2278 ---------------------------------------------------
2291 2279
2292 2280 Merge:
2293 2281 - one with change to an unrelated file
2294 2282 - one deleting and recreating the change
2295 2283
2296 2284 $ hg log -G --rev '::(desc("mDBm")+desc("mBDm"))'
2297 2285 o mDBm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - the other way
2298 2286 |\
2299 2287 +---o mBDm-0 simple merge - B side: unrelated update, D side: delete and recreate a file (with different content) - one way
2300 2288 | |/
2301 2289 | o d-2 re-add d
2302 2290 | |
2303 2291 | o d-1 delete d
2304 2292 | |
2305 2293 o | b-1: b update
2306 2294 |/
2307 2295 o i-2: c -move-> d, s -move-> t
2308 2296 |
2309 2297 o i-1: a -move-> c, p -move-> s
2310 2298 |
2311 2299 o i-0 initial commit: a b h p q r
2312 2300
2313 2301 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBDm-0")'
2314 2302 M d
2315 2303 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mDBm-0")'
2316 2304 M d
2317 2305 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mBDm-0")'
2318 2306 M b
2319 2307 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mDBm-0")'
2320 2308 M b
2321 2309 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mBDm-0")'
2322 2310 M b
2323 2311 M d
2324 2312 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mDBm-0")'
2325 2313 M b
2326 2314 M d
2327 2315
2328 2316 The bugs makes recorded copy is different depending of where we started the merge from since
2329 2317
2330 2318 $ hg manifest --debug --rev 'desc("mBDm-0")' | grep '644 d'
2331 2319 b004912a8510032a0350a74daa2803dadfb00e12 644 d
2332 2320 $ hg manifest --debug --rev 'desc("mDBm-0")' | grep '644 d'
2333 2321 b004912a8510032a0350a74daa2803dadfb00e12 644 d
2334 2322
2335 2323 $ hg manifest --debug --rev 'desc("d-2")' | grep '644 d'
2336 2324 b004912a8510032a0350a74daa2803dadfb00e12 644 d
2337 2325 $ hg manifest --debug --rev 'desc("b-1")' | grep '644 d'
2338 2326 d8252ab2e760b0d4e5288fd44cbd15a0fa567e16 644 d (no-changeset !)
2339 2327 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 d (changeset !)
2340 2328 $ hg debugindex d | head -n 4 | ../no-linkrev
2341 2329 rev linkrev nodeid p1 p2
2342 2330 0 * d8252ab2e760 000000000000 000000000000 (no-changeset !)
2343 2331 0 * ae258f702dfe 000000000000 000000000000 (changeset !)
2344 2332 1 * b004912a8510 000000000000 000000000000
2345 2333 2 * 7b79e2fe0c89 000000000000 000000000000 (no-changeset !)
2346 2334 2 * 5cce88bf349f ae258f702dfe 000000000000 (changeset !)
2347 2335
2348 2336 Log output should not include a merge commit as it did not happen
2349 2337
2350 2338 $ hg log -Gfr 'desc("mBDm-0")' d
2351 2339 o d-2 re-add d
2352 2340 |
2353 2341 ~
2354 2342
2355 2343 $ hg log -Gfr 'desc("mDBm-0")' d
2356 2344 o d-2 re-add d
2357 2345 |
2358 2346 ~
2359 2347
2360 2348 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBDm-0")'
2361 2349 M b
2362 2350 A d
2363 2351 A t
2364 2352 p
2365 2353 R a
2366 2354 R p
2367 2355 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mDBm-0")'
2368 2356 M b
2369 2357 A d
2370 2358 A t
2371 2359 p
2372 2360 R a
2373 2361 R p
2374 2362
2375 2363
2376 2364 Comparing with a merge with colliding rename
2377 2365 --------------------------------------------
2378 2366
2379 2367 Subcase: new copy information on both side
2380 2368 ``````````````````````````````````````````
2381 2369
2382 2370 - the "e-" branch renaming b to f (through 'g')
2383 2371 - the "a-" branch renaming d to f (through e)
2384 2372
2385 2373 $ hg log -G --rev '::(desc("mAEm")+desc("mEAm"))'
2386 2374 o mEAm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - the other way
2387 2375 |\
2388 2376 +---o mAEm-0 merge with copies info on both side - A side: rename d to f, E side: b to f, (same content for f) - one way
2389 2377 | |/
2390 2378 | o e-2 g -move-> f
2391 2379 | |
2392 2380 | o e-1 b -move-> g
2393 2381 | |
2394 2382 o | a-2: e -move-> f
2395 2383 | |
2396 2384 o | a-1: d -move-> e
2397 2385 |/
2398 2386 o i-2: c -move-> d, s -move-> t
2399 2387 |
2400 2388 o i-1: a -move-> c, p -move-> s
2401 2389 |
2402 2390 o i-0 initial commit: a b h p q r
2403 2391
2404 2392 #if no-changeset
2405 2393 $ hg manifest --debug --rev 'desc("mAEm-0")' | grep '644 f'
2406 2394 2ff93c643948464ee1f871867910ae43a45b0bea 644 f
2407 2395 $ hg manifest --debug --rev 'desc("mEAm-0")' | grep '644 f'
2408 2396 2ff93c643948464ee1f871867910ae43a45b0bea 644 f
2409 2397 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
2410 2398 b76eb76580df486c3d51d63c5c210d4dd43a8ac7 644 f
2411 2399 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
2412 2400 e8825b386367b29fec957283a80bb47b47483fe1 644 f
2413 2401 $ hg debugindex f | ../no-linkrev
2414 2402 rev linkrev nodeid p1 p2
2415 2403 0 * b76eb76580df 000000000000 000000000000
2416 2404 1 * e8825b386367 000000000000 000000000000
2417 2405 2 * 2ff93c643948 b76eb76580df e8825b386367
2418 2406 3 * 2f649fba7eb2 b76eb76580df e8825b386367
2419 2407 4 * 774e7c1637d5 e8825b386367 b76eb76580df
2420 2408 #else
2421 2409 $ hg manifest --debug --rev 'desc("mAEm-0")' | grep '644 f'
2422 2410 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2423 2411 $ hg manifest --debug --rev 'desc("mEAm-0")' | grep '644 f'
2424 2412 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2425 2413 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
2426 2414 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2427 2415 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
2428 2416 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
2429 2417 $ hg debugindex f | ../no-linkrev
2430 2418 rev linkrev nodeid p1 p2
2431 2419 0 * ae258f702dfe 000000000000 000000000000
2432 2420 1 * d3613c1ec831 ae258f702dfe 000000000000
2433 2421 2 * 05e03c868bbc ae258f702dfe 000000000000
2434 2422 #endif
2435 2423
2436 2424 # Here the filelog based implementation is not looking at the rename
2437 2425 # information (because the file exist on both side). However the changelog
2438 2426 # based on works fine. We have different output.
2439 2427
2440 2428 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mAEm-0")'
2441 2429 M f (no-changeset !)
2442 2430 b (no-filelog no-changeset !)
2443 2431 R b
2444 2432 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mEAm-0")'
2445 2433 M f (no-changeset !)
2446 2434 b (no-filelog no-changeset !)
2447 2435 R b
2448 2436 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mAEm-0")'
2449 2437 M f (no-changeset !)
2450 2438 d (no-filelog no-changeset !)
2451 2439 R d
2452 2440 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mEAm-0")'
2453 2441 M f (no-changeset !)
2454 2442 d (no-filelog no-changeset !)
2455 2443 R d
2456 2444 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("a-2")'
2457 2445 A f
2458 2446 d
2459 2447 R d
2460 2448 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("e-2")'
2461 2449 A f
2462 2450 b
2463 2451 R b
2464 2452
2465 2453 # From here, we run status against revision where both source file exists.
2466 2454 #
2467 2455 # The filelog based implementation picks an arbitrary side based on revision
2468 2456 # numbers. So the same side "wins" whatever the parents order is. This is
2469 2457 # sub-optimal because depending on revision numbers means the result can be
2470 2458 # different from one repository to the next.
2471 2459 #
2472 2460 # The changeset based algorithm use the parent order to break tie on conflicting
2473 2461 # information and will have a different order depending on who is p1 and p2.
2474 2462 # That order is stable accross repositories. (data from p1 prevails)
2475 2463
2476 2464 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mAEm-0")'
2477 2465 A f
2478 2466 d
2479 2467 R b
2480 2468 R d
2481 2469 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mEAm-0")'
2482 2470 A f
2483 2471 d (filelog !)
2484 2472 b (no-filelog !)
2485 2473 R b
2486 2474 R d
2487 2475 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAEm-0")'
2488 2476 A f
2489 2477 a
2490 2478 A t
2491 2479 p
2492 2480 R a
2493 2481 R b
2494 2482 R p
2495 2483 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEAm-0")'
2496 2484 A f
2497 2485 a (filelog !)
2498 2486 b (no-filelog !)
2499 2487 A t
2500 2488 p
2501 2489 R a
2502 2490 R b
2503 2491 R p
2504 2492
2505 2493
2506 2494 Subcase: existing copy information overwritten on one branch
2507 2495 ````````````````````````````````````````````````````````````
2508 2496
2509 2497 Note:
2510 2498 | In this case, one of the merge wrongly record a merge while there is none.
2511 2499 | This lead to bad copy tracing information to be dug up.
2512 2500
2513 2501
2514 2502 Merge:
2515 2503 - one with change to an unrelated file (b)
2516 2504 - one overwriting a file (d) with a rename (from h to i to d)
2517 2505
2518 2506 $ hg log -G --rev '::(desc("mBFm")+desc("mFBm"))'
2519 2507 o mFBm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
2520 2508 |\
2521 2509 +---o mBFm-0 simple merge - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
2522 2510 | |/
2523 2511 | o f-2: rename i -> d
2524 2512 | |
2525 2513 | o f-1: rename h -> i
2526 2514 | |
2527 2515 o | b-1: b update
2528 2516 |/
2529 2517 o i-2: c -move-> d, s -move-> t
2530 2518 |
2531 2519 o i-1: a -move-> c, p -move-> s
2532 2520 |
2533 2521 o i-0 initial commit: a b h p q r
2534 2522
2535 2523 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBFm-0")'
2536 2524 M b
2537 2525 A d
2538 2526 h
2539 2527 A t
2540 2528 p
2541 2529 R a
2542 2530 R h
2543 2531 R p
2544 2532 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFBm-0")'
2545 2533 M b
2546 2534 A d
2547 2535 h
2548 2536 A t
2549 2537 p
2550 2538 R a
2551 2539 R h
2552 2540 R p
2553 2541 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBFm-0")'
2554 2542 M d (no-changeset !)
2555 2543 h (no-filelog no-changeset !)
2556 2544 R h
2557 2545 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mBFm-0")'
2558 2546 M b
2559 2547 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mBFm-0")'
2560 2548 M b
2561 2549 M d (no-changeset !)
2562 2550 i (no-filelog no-changeset !)
2563 2551 R i
2564 2552 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mFBm-0")'
2565 2553 M d (no-changeset !)
2566 2554 h (no-filelog no-changeset !)
2567 2555 R h
2568 2556 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mFBm-0")'
2569 2557 M b
2570 2558 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mFBm-0")'
2571 2559 M b
2572 2560 M d (no-changeset !)
2573 2561 i (no-filelog no-changeset !)
2574 2562 R i
2575 2563
2576 2564 #if no-changeset
2577 2565 $ hg log -Gfr 'desc("mBFm-0")' d
2578 2566 o f-2: rename i -> d
2579 2567 |
2580 2568 o f-1: rename h -> i
2581 2569 :
2582 2570 o i-0 initial commit: a b h p q r
2583 2571
2584 2572 #else
2585 2573 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2586 2574 $ hg log -Gfr 'desc("mBFm-0")' d
2587 2575 o i-2: c -move-> d, s -move-> t
2588 2576 |
2589 2577 ~
2590 2578 #endif
2591 2579
2592 2580 #if no-changeset
2593 2581 $ hg log -Gfr 'desc("mFBm-0")' d
2594 2582 o f-2: rename i -> d
2595 2583 |
2596 2584 o f-1: rename h -> i
2597 2585 :
2598 2586 o i-0 initial commit: a b h p q r
2599 2587
2600 2588 #else
2601 2589 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2602 2590 $ hg log -Gfr 'desc("mFBm-0")' d
2603 2591 o i-2: c -move-> d, s -move-> t
2604 2592 |
2605 2593 ~
2606 2594 #endif
2607 2595
2608 2596
2609 2597 Subcase: existing copy information overwritten on one branch, with different content)
2610 2598 `````````````````````````````````````````````````````````````````````````````````````
2611 2599
2612 2600 Merge:
2613 2601 - one with change to an unrelated file (b)
2614 2602 - one overwriting a file (t) with a rename (from r to x to t), v content is not the same as on the other branch
2615 2603
2616 2604 $ hg log -G --rev '::(desc("mBRm")+desc("mRBm"))'
2617 2605 o mRBm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - the other way
2618 2606 |\
2619 2607 +---o mBRm-0 simple merge - B side: unrelated change, R side: overwrite d with a copy (from r->x->t) different content - one way
2620 2608 | |/
2621 2609 | o r-2: rename t -> x
2622 2610 | |
2623 2611 | o r-1: rename r -> x
2624 2612 | |
2625 2613 o | b-1: b update
2626 2614 |/
2627 2615 o i-2: c -move-> d, s -move-> t
2628 2616 |
2629 2617 o i-1: a -move-> c, p -move-> s
2630 2618 |
2631 2619 o i-0 initial commit: a b h p q r
2632 2620
2633 2621 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBRm-0")'
2634 2622 M b
2635 2623 A d
2636 2624 a
2637 2625 A t
2638 2626 r
2639 2627 R a
2640 2628 R p
2641 2629 R r
2642 2630 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mRBm-0")'
2643 2631 M b
2644 2632 A d
2645 2633 a
2646 2634 A t
2647 2635 r
2648 2636 R a
2649 2637 R p
2650 2638 R r
2651 2639 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBRm-0")'
2652 2640 M t
2653 2641 r (no-filelog !)
2654 2642 R r
2655 2643 $ hg status --copies --rev 'desc("r-2")' --rev 'desc("mBRm-0")'
2656 2644 M b
2657 2645 $ hg status --copies --rev 'desc("r-1")' --rev 'desc("mBRm-0")'
2658 2646 M b
2659 2647 M t
2660 2648 x (no-filelog !)
2661 2649 R x
2662 2650 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mRBm-0")'
2663 2651 M t
2664 2652 r (no-filelog !)
2665 2653 R r
2666 2654 $ hg status --copies --rev 'desc("r-2")' --rev 'desc("mRBm-0")'
2667 2655 M b
2668 2656 $ hg status --copies --rev 'desc("r-1")' --rev 'desc("mRBm-0")'
2669 2657 M b
2670 2658 M t
2671 2659 x (no-filelog !)
2672 2660 R x
2673 2661
2674 2662 #if no-changeset
2675 2663 $ hg log -Gfr 'desc("mBRm-0")' d
2676 2664 o i-2: c -move-> d, s -move-> t
2677 2665 |
2678 2666 o i-1: a -move-> c, p -move-> s
2679 2667 |
2680 2668 o i-0 initial commit: a b h p q r
2681 2669
2682 2670 #else
2683 2671 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2684 2672 $ hg log -Gfr 'desc("mBRm-0")' d
2685 2673 o i-2: c -move-> d, s -move-> t
2686 2674 |
2687 2675 ~
2688 2676 #endif
2689 2677
2690 2678 #if no-changeset
2691 2679 $ hg log -Gfr 'desc("mRBm-0")' d
2692 2680 o i-2: c -move-> d, s -move-> t
2693 2681 |
2694 2682 o i-1: a -move-> c, p -move-> s
2695 2683 |
2696 2684 o i-0 initial commit: a b h p q r
2697 2685
2698 2686 #else
2699 2687 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2700 2688 $ hg log -Gfr 'desc("mRBm-0")' d
2701 2689 o i-2: c -move-> d, s -move-> t
2702 2690 |
2703 2691 ~
2704 2692 #endif
2705 2693
2706 2694 Subcase: reset of the copy history on one side
2707 2695 ``````````````````````````````````````````````
2708 2696
2709 2697 Merge:
2710 2698 - one with change to a file
2711 2699 - one deleting and recreating the file
2712 2700
2713 2701 Unlike in the 'BD/DB' cases, an actual merge happened here. So we should
2714 2702 consider history and rename on both branch of the merge.
2715 2703
2716 2704 $ hg log -G --rev '::(desc("mDGm")+desc("mGDm"))'
2717 2705 o mGDm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - the other way
2718 2706 |\
2719 2707 +---o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2720 2708 | |/
2721 2709 | o g-1: update d
2722 2710 | |
2723 2711 o | d-2 re-add d
2724 2712 | |
2725 2713 o | d-1 delete d
2726 2714 |/
2727 2715 o i-2: c -move-> d, s -move-> t
2728 2716 |
2729 2717 o i-1: a -move-> c, p -move-> s
2730 2718 |
2731 2719 o i-0 initial commit: a b h p q r
2732 2720
2733 2721 One side of the merge have a long history with rename. The other side of the
2734 2722 merge point to a new file with a smaller history. Each side is "valid".
2735 2723
2736 2724 (and again the filelog based algorithm only explore one, with a pick based on
2737 2725 revision numbers)
2738 2726
2739 2727 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mDGm-0")'
2740 2728 A d
2741 2729 a (filelog !)
2742 2730 A t
2743 2731 p
2744 2732 R a
2745 2733 R p
2746 2734 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGDm-0")'
2747 2735 A d
2748 2736 a
2749 2737 A t
2750 2738 p
2751 2739 R a
2752 2740 R p
2753 2741 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mDGm-0")'
2754 2742 M d
2755 2743 $ hg status --copies --rev 'desc("d-2")' --rev 'desc("mGDm-0")'
2756 2744 M d
2757 2745 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mDGm-0")'
2758 2746 M d
2759 2747 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mGDm-0")'
2760 2748 M d
2761 2749
2762 2750 #if no-changeset
2763 2751 $ hg log -Gfr 'desc("mDGm-0")' d
2764 2752 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2765 2753 |\
2766 2754 | o g-1: update d
2767 2755 | |
2768 2756 o | d-2 re-add d
2769 2757 |/
2770 2758 o i-2: c -move-> d, s -move-> t
2771 2759 |
2772 2760 o i-1: a -move-> c, p -move-> s
2773 2761 |
2774 2762 o i-0 initial commit: a b h p q r
2775 2763
2776 2764 #else
2777 2765 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2778 2766 $ hg log -Gfr 'desc("mDGm-0")' d
2779 2767 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2780 2768 |\
2781 2769 | o g-1: update d
2782 2770 | |
2783 2771 o | d-2 re-add d
2784 2772 |/
2785 2773 o i-2: c -move-> d, s -move-> t
2786 2774 |
2787 2775 ~
2788 2776 #endif
2789 2777
2790 2778
2791 2779 #if no-changeset
2792 2780 $ hg log -Gfr 'desc("mDGm-0")' d
2793 2781 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2794 2782 |\
2795 2783 | o g-1: update d
2796 2784 | |
2797 2785 o | d-2 re-add d
2798 2786 |/
2799 2787 o i-2: c -move-> d, s -move-> t
2800 2788 |
2801 2789 o i-1: a -move-> c, p -move-> s
2802 2790 |
2803 2791 o i-0 initial commit: a b h p q r
2804 2792
2805 2793 #else
2806 2794 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2807 2795 $ hg log -Gfr 'desc("mDGm-0")' d
2808 2796 o mDGm-0 actual content merge, copies on one side - D side: delete and re-add (different content), G side: update content - one way
2809 2797 |\
2810 2798 | o g-1: update d
2811 2799 | |
2812 2800 o | d-2 re-add d
2813 2801 |/
2814 2802 o i-2: c -move-> d, s -move-> t
2815 2803 |
2816 2804 ~
2817 2805 #endif
2818 2806
2819 2807 Subcase: merging a change to a file with a "copy overwrite" to that file from another branch
2820 2808 ````````````````````````````````````````````````````````````````````````````````````````````
2821 2809
2822 2810 Merge:
2823 2811 - one with change to a file (d)
2824 2812 - one overwriting that file with a rename (from h to i, to d)
2825 2813
2826 2814 This case is similar to BF/FB, but an actual merge happens, so both side of the
2827 2815 history are relevant.
2828 2816
2829 2817
2830 2818 $ hg log -G --rev '::(desc("mGFm")+desc("mFGm"))'
2831 2819 o mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
2832 2820 |\
2833 2821 +---o mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
2834 2822 | |/
2835 2823 | o g-1: update d
2836 2824 | |
2837 2825 o | f-2: rename i -> d
2838 2826 | |
2839 2827 o | f-1: rename h -> i
2840 2828 |/
2841 2829 o i-2: c -move-> d, s -move-> t
2842 2830 |
2843 2831 o i-1: a -move-> c, p -move-> s
2844 2832 |
2845 2833 o i-0 initial commit: a b h p q r
2846 2834
2847 2835
2848 2836 Note:
2849 2837 | In this case, the merge get conflicting information since on one side we have
2850 2838 | "a -> c -> d". and one the other one we have "h -> i -> d".
2851 2839 |
2852 2840 | The current code arbitrarily pick one side depending the ordering of the merged hash:
2853 2841
2854 2842 In this case, the file hash from "f-2" is lower, so it will be `p1` of the resulting filenode its copy tracing information will win (and trace back to "h"):
2855 2843
2856 2844 Details on this hash ordering pick:
2857 2845
2858 2846 $ hg manifest --debug 'desc("g-1")' | egrep 'd$'
2859 2847 17ec97e605773eb44a117d1136b3849bcdc1924f 644 d (no-changeset !)
2860 2848 5cce88bf349f7c742bb440f2c53f81db9c294279 644 d (changeset !)
2861 2849 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("g-1")' d
2862 2850 A d
2863 2851 a (no-changeset no-compatibility !)
2864 2852
2865 2853 $ hg manifest --debug 'desc("f-2")' | egrep 'd$'
2866 2854 7b79e2fe0c8924e0e598a82f048a7b024afa4d96 644 d (no-changeset !)
2867 2855 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 d (changeset !)
2868 2856 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("f-2")' d
2869 2857 A d
2870 2858 h (no-changeset no-compatibility !)
2871 2859
2872 2860 Copy tracing data on the resulting merge:
2873 2861
2874 2862 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFGm-0")'
2875 2863 A d
2876 2864 h (no-filelog !)
2877 2865 a (filelog !)
2878 2866 A t
2879 2867 p
2880 2868 R a
2881 2869 R h
2882 2870 R p
2883 2871 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGFm-0")'
2884 2872 A d
2885 2873 a (no-changeset !)
2886 2874 h (changeset !)
2887 2875 A t
2888 2876 p
2889 2877 R a
2890 2878 R h
2891 2879 R p
2892 2880 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mFGm-0")'
2893 2881 M d
2894 2882 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mGFm-0")'
2895 2883 M d
2896 2884 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mFGm-0")'
2897 2885 M d
2898 2886 i (no-filelog !)
2899 2887 R i
2900 2888 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mGFm-0")'
2901 2889 M d
2902 2890 i (no-filelog !)
2903 2891 R i
2904 2892 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mFGm-0")'
2905 2893 M d (no-changeset !)
2906 2894 h (no-filelog no-changeset !)
2907 2895 R h
2908 2896 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mGFm-0")'
2909 2897 M d (no-changeset !)
2910 2898 h (no-filelog no-changeset !)
2911 2899 R h
2912 2900
2913 2901 #if no-changeset
2914 2902 $ hg log -Gfr 'desc("mFGm-0")' d
2915 2903 o mFGm-0 merge - G side: content change, F side: copy overwrite, no content change - one way
2916 2904 |\
2917 2905 | o g-1: update d
2918 2906 | |
2919 2907 o | f-2: rename i -> d
2920 2908 | |
2921 2909 o | f-1: rename h -> i
2922 2910 |/
2923 2911 o i-2: c -move-> d, s -move-> t
2924 2912 |
2925 2913 o i-1: a -move-> c, p -move-> s
2926 2914 |
2927 2915 o i-0 initial commit: a b h p q r
2928 2916
2929 2917 #else
2930 2918 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2931 2919 $ hg log -Gfr 'desc("mFGm-0")' d
2932 2920 o g-1: update d
2933 2921 |
2934 2922 o i-2: c -move-> d, s -move-> t
2935 2923 |
2936 2924 ~
2937 2925 #endif
2938 2926
2939 2927 #if no-changeset
2940 2928 $ hg log -Gfr 'desc("mGFm-0")' d
2941 2929 o mGFm-0 merge - G side: content change, F side: copy overwrite, no content change - the other way
2942 2930 |\
2943 2931 | o g-1: update d
2944 2932 | |
2945 2933 o | f-2: rename i -> d
2946 2934 | |
2947 2935 o | f-1: rename h -> i
2948 2936 |/
2949 2937 o i-2: c -move-> d, s -move-> t
2950 2938 |
2951 2939 o i-1: a -move-> c, p -move-> s
2952 2940 |
2953 2941 o i-0 initial commit: a b h p q r
2954 2942
2955 2943 #else
2956 2944 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
2957 2945 $ hg log -Gfr 'desc("mGFm-0")' d
2958 2946 o g-1: update d
2959 2947 |
2960 2948 o i-2: c -move-> d, s -move-> t
2961 2949 |
2962 2950 ~
2963 2951 #endif
2964 2952
2965 2953 Subcase: new copy information on both side with an actual merge happening
2966 2954 `````````````````````````````````````````````````````````````````````````
2967 2955
2968 2956 - the "p-" branch renaming 't' to 'v' (through 'u')
2969 2957 - the "q-" branch renaming 'r' to 'v' (through 'w')
2970 2958
2971 2959
2972 2960 $ hg log -G --rev '::(desc("mPQm")+desc("mQPm"))'
2973 2961 o mQPm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - the other way
2974 2962 |\
2975 2963 +---o mPQm-0 merge with copies info on both side - P side: rename t to v, Q side: r to v, (different content) - one way
2976 2964 | |/
2977 2965 | o q-2 w -move-> v
2978 2966 | |
2979 2967 | o q-1 r -move-> w
2980 2968 | |
2981 2969 o | p-2: u -move-> v
2982 2970 | |
2983 2971 o | p-1: t -move-> u
2984 2972 |/
2985 2973 o i-2: c -move-> d, s -move-> t
2986 2974 |
2987 2975 o i-1: a -move-> c, p -move-> s
2988 2976 |
2989 2977 o i-0 initial commit: a b h p q r
2990 2978
2991 2979
2992 2980 #if no-changeset
2993 2981 $ hg manifest --debug --rev 'desc("mPQm-0")' | grep '644 v'
2994 2982 0946c662ef16e4e67397fd717389eb6693d41749 644 v
2995 2983 $ hg manifest --debug --rev 'desc("mQPm-0")' | grep '644 v'
2996 2984 0db3aad7fcc1ec27fab57060e327b9e864ea0cc9 644 v
2997 2985 $ hg manifest --debug --rev 'desc("p-2")' | grep '644 v'
2998 2986 3f91841cd75cadc9a1f1b4e7c1aa6d411f76032e 644 v
2999 2987 $ hg manifest --debug --rev 'desc("q-2")' | grep '644 v'
3000 2988 c43c088b811fd27983c0a9aadf44f3343cd4cd7e 644 v
3001 2989 $ hg debugindex v | ../no-linkrev
3002 2990 rev linkrev nodeid p1 p2
3003 2991 0 * 3f91841cd75c 000000000000 000000000000
3004 2992 1 * c43c088b811f 000000000000 000000000000
3005 2993 2 * 0946c662ef16 3f91841cd75c c43c088b811f
3006 2994 3 * 0db3aad7fcc1 c43c088b811f 3f91841cd75c
3007 2995 #else
3008 2996 $ hg manifest --debug --rev 'desc("mPQm-0")' | grep '644 v'
3009 2997 65fde9f6e4d4da23b3f610e07b53673ea9541d75 644 v
3010 2998 $ hg manifest --debug --rev 'desc("mQPm-0")' | grep '644 v'
3011 2999 a098dda6413aecf154eefc976afc38b295acb7e5 644 v
3012 3000 $ hg manifest --debug --rev 'desc("p-2")' | grep '644 v'
3013 3001 5aed6a8dbff0301328c08360d24354d3d064cf0d 644 v
3014 3002 $ hg manifest --debug --rev 'desc("q-2")' | grep '644 v'
3015 3003 a38b2fa170219750dac9bc7d19df831f213ba708 644 v
3016 3004 $ hg debugindex v | ../no-linkrev
3017 3005 rev linkrev nodeid p1 p2
3018 3006 0 * 5aed6a8dbff0 000000000000 000000000000
3019 3007 1 * a38b2fa17021 000000000000 000000000000
3020 3008 2 * 65fde9f6e4d4 5aed6a8dbff0 a38b2fa17021
3021 3009 3 * a098dda6413a a38b2fa17021 5aed6a8dbff0
3022 3010 #endif
3023 3011
3024 3012 # Here the filelog based implementation is not looking at the rename
3025 3013 # information (because the file exist on both side). However the changelog
3026 3014 # based on works fine. We have different output.
3027 3015
3028 3016 $ hg status --copies --rev 'desc("p-2")' --rev 'desc("mPQm-0")'
3029 3017 M v
3030 3018 r (no-filelog !)
3031 3019 R r
3032 3020 $ hg status --copies --rev 'desc("p-2")' --rev 'desc("mQPm-0")'
3033 3021 M v
3034 3022 r (no-filelog !)
3035 3023 R r
3036 3024 $ hg status --copies --rev 'desc("q-2")' --rev 'desc("mPQm-0")'
3037 3025 M v
3038 3026 t (no-filelog !)
3039 3027 R t
3040 3028 $ hg status --copies --rev 'desc("q-2")' --rev 'desc("mQPm-0")'
3041 3029 M v
3042 3030 t (no-filelog !)
3043 3031 R t
3044 3032 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("p-2")'
3045 3033 A v
3046 3034 t
3047 3035 R t
3048 3036 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("q-2")'
3049 3037 A v
3050 3038 r
3051 3039 R r
3052 3040
3053 3041 # From here, we run status against revision where both source file exists.
3054 3042 #
3055 3043 # The filelog based implementation picks an arbitrary side based on revision
3056 3044 # numbers. So the same side "wins" whatever the parents order is. This is
3057 3045 # sub-optimal because depending on revision numbers means the result can be
3058 3046 # different from one repository to the next.
3059 3047 #
3060 3048 # The changeset based algorithm use the parent order to break tie on conflicting
3061 3049 # information and will have a different order depending on who is p1 and p2.
3062 3050 # That order is stable accross repositories. (data from p1 prevails)
3063 3051
3064 3052 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mPQm-0")'
3065 3053 A v
3066 3054 t
3067 3055 R r
3068 3056 R t
3069 3057 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mQPm-0")'
3070 3058 A v
3071 3059 t (filelog !)
3072 3060 r (no-filelog !)
3073 3061 R r
3074 3062 R t
3075 3063 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mPQm-0")'
3076 3064 A d
3077 3065 a
3078 3066 A v
3079 3067 r (filelog !)
3080 3068 p (no-filelog !)
3081 3069 R a
3082 3070 R p
3083 3071 R r
3084 3072 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mQPm-0")'
3085 3073 A d
3086 3074 a
3087 3075 A v
3088 3076 r
3089 3077 R a
3090 3078 R p
3091 3079 R r
3092 3080
3093 3081
3094 3082 Comparing with merging with a deletion (and keeping the file)
3095 3083 -------------------------------------------------------------
3096 3084
3097 3085 Merge:
3098 3086 - one removing a file (d)
3099 3087 - one updating that file
3100 3088 - the merge keep the modified version of the file (canceling the delete)
3101 3089
3102 3090 In this case, the file keep on living after the merge. So we should not drop its
3103 3091 copy tracing chain.
3104 3092
3105 3093 $ hg log -G --rev '::(desc("mCGm")+desc("mGCm"))'
3106 3094 o mGCm-0 merge updated/deleted - revive the file (updated content) - the other way
3107 3095 |\
3108 3096 +---o mCGm-0 merge updated/deleted - revive the file (updated content) - one way
3109 3097 | |/
3110 3098 | o g-1: update d
3111 3099 | |
3112 3100 o | c-1 delete d
3113 3101 |/
3114 3102 o i-2: c -move-> d, s -move-> t
3115 3103 |
3116 3104 o i-1: a -move-> c, p -move-> s
3117 3105 |
3118 3106 o i-0 initial commit: a b h p q r
3119 3107
3120 3108
3121 3109 'a' is the copy source of 'd'
3122 3110
3123 3111 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCGm-0")'
3124 3112 A d
3125 3113 a (no-compatibility no-changeset !)
3126 3114 A t
3127 3115 p
3128 3116 R a
3129 3117 R p
3130 3118 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGCm-0")'
3131 3119 A d
3132 3120 a (no-compatibility no-changeset !)
3133 3121 A t
3134 3122 p
3135 3123 R a
3136 3124 R p
3137 3125 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCGm-0")'
3138 3126 A d
3139 3127 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mGCm-0")'
3140 3128 A d
3141 3129 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mCGm-0")'
3142 3130 $ hg status --copies --rev 'desc("g-1")' --rev 'desc("mGCm-0")'
3143 3131
3144 3132
3145 3133 Comparing with merge restoring an untouched deleted file
3146 3134 --------------------------------------------------------
3147 3135
3148 3136 Merge:
3149 3137 - one removing a file (d)
3150 3138 - one leaving the file untouched
3151 3139 - the merge actively restore the file to the same content.
3152 3140
3153 3141 In this case, the file keep on living after the merge. So we should not drop its
3154 3142 copy tracing chain.
3155 3143
3156 3144 $ hg log -G --rev '::(desc("mCB-revert-m")+desc("mBC-revert-m"))'
3157 3145 o mBC-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
3158 3146 |\
3159 3147 +---o mCB-revert-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
3160 3148 | |/
3161 3149 | o c-1 delete d
3162 3150 | |
3163 3151 o | b-1: b update
3164 3152 |/
3165 3153 o i-2: c -move-> d, s -move-> t
3166 3154 |
3167 3155 o i-1: a -move-> c, p -move-> s
3168 3156 |
3169 3157 o i-0 initial commit: a b h p q r
3170 3158
3171 3159
3172 3160 'a' is the the copy source of 'd'
3173 3161
3174 3162 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB-revert-m-0")'
3175 3163 M b
3176 3164 A d
3177 3165 a (no-compatibility no-changeset !)
3178 3166 A t
3179 3167 p
3180 3168 R a
3181 3169 R p
3182 3170 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC-revert-m-0")'
3183 3171 M b
3184 3172 A d
3185 3173 a (no-compatibility no-changeset !)
3186 3174 A t
3187 3175 p
3188 3176 R a
3189 3177 R p
3190 3178 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCB-revert-m-0")'
3191 3179 M b
3192 3180 A d
3193 3181 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBC-revert-m-0")'
3194 3182 M b
3195 3183 A d
3196 3184 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCB-revert-m-0")'
3197 3185 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBC-revert-m-0")'
3198 3186
3199 3187
3200 3188 Merging a branch where a rename was deleted with a branch where the same file was renamed
3201 3189 ------------------------------------------------------------------------------------------
3202 3190
3203 3191 Create a "conflicting" merge where `d` get removed on one branch before its
3204 3192 rename information actually conflict with the other branch.
3205 3193
3206 3194 (the copy information from the branch that was not deleted should win).
3207 3195
3208 3196 $ hg log -G --rev '::(desc("mCH-delete-before-conflict-m")+desc("mHC-delete-before-conflict-m"))'
3209 3197 o mHC-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - the other way
3210 3198 |\
3211 3199 +---o mCH-delete-before-conflict-m-0 simple merge - C side: d is the results of renames then deleted, H side: d is result of another rename (same content as the other branch) - one way
3212 3200 | |/
3213 3201 | o h-1: b -(move)-> d
3214 3202 | |
3215 3203 o | c-1 delete d
3216 3204 | |
3217 3205 o | i-2: c -move-> d, s -move-> t
3218 3206 | |
3219 3207 o | i-1: a -move-> c, p -move-> s
3220 3208 |/
3221 3209 o i-0 initial commit: a b h p q r
3222 3210
3223 3211
3224 3212 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCH-delete-before-conflict-m")'
3225 3213 A d
3226 3214 b (no-compatibility no-changeset !)
3227 3215 A t
3228 3216 p
3229 3217 R a
3230 3218 R b
3231 3219 R p
3232 3220 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mHC-delete-before-conflict-m")'
3233 3221 A d
3234 3222 b
3235 3223 A t
3236 3224 p
3237 3225 R a
3238 3226 R b
3239 3227 R p
3240 3228 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCH-delete-before-conflict-m")'
3241 3229 A d
3242 3230 b
3243 3231 R b
3244 3232 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mHC-delete-before-conflict-m")'
3245 3233 A d
3246 3234 b
3247 3235 R b
3248 3236 $ hg status --copies --rev 'desc("h-1")' --rev 'desc("mCH-delete-before-conflict-m")'
3249 3237 A t
3250 3238 p
3251 3239 R a
3252 3240 R p
3253 3241 $ hg status --copies --rev 'desc("h-1")' --rev 'desc("mHC-delete-before-conflict-m")'
3254 3242 A t
3255 3243 p
3256 3244 R a
3257 3245 R p
3258 3246
3259 3247 Variant of previous with extra changes introduced by the merge
3260 3248 --------------------------------------------------------------
3261 3249
3262 3250 (see case declaration for details)
3263 3251
3264 3252 Subcase: merge has same initial content on both side, but merge introduced a change
3265 3253 ```````````````````````````````````````````````````````````````````````````````````
3266 3254
3267 3255 - the "e-" branch renaming b to f (through 'g')
3268 3256 - the "a-" branch renaming d to f (through e)
3269 3257 - the merge add new change to b
3270 3258
3271 3259 $ hg log -G --rev '::(desc("mAE-change-m")+desc("mEA-change-m"))'
3272 3260 o mEA-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - the other way
3273 3261 |\
3274 3262 +---o mAE-change-m-0 merge with file update and copies info on both side - A side: rename d to f, E side: b to f, (same content for f in parent) - one way
3275 3263 | |/
3276 3264 | o e-2 g -move-> f
3277 3265 | |
3278 3266 | o e-1 b -move-> g
3279 3267 | |
3280 3268 o | a-2: e -move-> f
3281 3269 | |
3282 3270 o | a-1: d -move-> e
3283 3271 |/
3284 3272 o i-2: c -move-> d, s -move-> t
3285 3273 |
3286 3274 o i-1: a -move-> c, p -move-> s
3287 3275 |
3288 3276 o i-0 initial commit: a b h p q r
3289 3277
3290 3278 #if no-changeset
3291 3279 $ hg manifest --debug --rev 'desc("mAE-change-m-0")' | grep '644 f'
3292 3280 2f649fba7eb284e720d02b61f0546fcef694c045 644 f
3293 3281 $ hg manifest --debug --rev 'desc("mEA-change-m-0")' | grep '644 f'
3294 3282 774e7c1637d536b99e2d8ef16fd731f87a82bd09 644 f
3295 3283 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
3296 3284 b76eb76580df486c3d51d63c5c210d4dd43a8ac7 644 f
3297 3285 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
3298 3286 e8825b386367b29fec957283a80bb47b47483fe1 644 f
3299 3287 $ hg debugindex f | ../no-linkrev
3300 3288 rev linkrev nodeid p1 p2
3301 3289 0 * b76eb76580df 000000000000 000000000000
3302 3290 1 * e8825b386367 000000000000 000000000000
3303 3291 2 * 2ff93c643948 b76eb76580df e8825b386367
3304 3292 3 * 2f649fba7eb2 b76eb76580df e8825b386367
3305 3293 4 * 774e7c1637d5 e8825b386367 b76eb76580df
3306 3294 #else
3307 3295 $ hg manifest --debug --rev 'desc("mAE-change-m-0")' | grep '644 f'
3308 3296 d3613c1ec8310a812ac4268fd853ac576b6caea5 644 f
3309 3297 $ hg manifest --debug --rev 'desc("mEA-change-m-0")' | grep '644 f'
3310 3298 05e03c868bbcab4a649cb33a238d7aa07398a469 644 f
3311 3299 $ hg manifest --debug --rev 'desc("a-2")' | grep '644 f'
3312 3300 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
3313 3301 $ hg manifest --debug --rev 'desc("e-2")' | grep '644 f'
3314 3302 ae258f702dfeca05bf9b6a22a97a4b5645570f11 644 f
3315 3303 $ hg debugindex f | ../no-linkrev
3316 3304 rev linkrev nodeid p1 p2
3317 3305 0 * ae258f702dfe 000000000000 000000000000
3318 3306 1 * d3613c1ec831 ae258f702dfe 000000000000
3319 3307 2 * 05e03c868bbc ae258f702dfe 000000000000
3320 3308 #endif
3321 3309
3322 3310 # Here the filelog based implementation is not looking at the rename
3323 3311 # information (because the file exist on both side). However the changelog
3324 3312 # based on works fine. We have different output.
3325 3313
3326 3314 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mAE-change-m-0")'
3327 3315 M f
3328 3316 b (no-filelog !)
3329 3317 R b
3330 3318 $ hg status --copies --rev 'desc("a-2")' --rev 'desc("mEA-change-m-0")'
3331 3319 M f
3332 3320 b (no-filelog !)
3333 3321 R b
3334 3322 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mAE-change-m-0")'
3335 3323 M f
3336 3324 d (no-filelog !)
3337 3325 R d
3338 3326 $ hg status --copies --rev 'desc("e-2")' --rev 'desc("mEA-change-m-0")'
3339 3327 M f
3340 3328 d (no-filelog !)
3341 3329 R d
3342 3330 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("a-2")'
3343 3331 A f
3344 3332 d
3345 3333 R d
3346 3334 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("e-2")'
3347 3335 A f
3348 3336 b
3349 3337 R b
3350 3338
3351 3339 # From here, we run status against revision where both source file exists.
3352 3340 #
3353 3341 # The filelog based implementation picks an arbitrary side based on revision
3354 3342 # numbers. So the same side "wins" whatever the parents order is. This is
3355 3343 # sub-optimal because depending on revision numbers means the result can be
3356 3344 # different from one repository to the next.
3357 3345 #
3358 3346 # The changeset based algorithm use the parent order to break tie on conflicting
3359 3347 # information and will have a different order depending on who is p1 and p2.
3360 3348 # That order is stable accross repositories. (data from p1 prevails)
3361 3349
3362 3350 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mAE-change-m-0")'
3363 3351 A f
3364 3352 d
3365 3353 R b
3366 3354 R d
3367 3355 $ hg status --copies --rev 'desc("i-2")' --rev 'desc("mEA-change-m-0")'
3368 3356 A f
3369 3357 d (filelog !)
3370 3358 b (no-filelog !)
3371 3359 R b
3372 3360 R d
3373 3361 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE-change-m-0")'
3374 3362 A f
3375 3363 a
3376 3364 A t
3377 3365 p
3378 3366 R a
3379 3367 R b
3380 3368 R p
3381 3369 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA-change-m-0")'
3382 3370 A f
3383 3371 a (filelog !)
3384 3372 b (no-filelog !)
3385 3373 A t
3386 3374 p
3387 3375 R a
3388 3376 R b
3389 3377 R p
3390 3378
3391 3379
3392 3380 Subcase: merge overwrite common copy information, but with extra change during the merge
3393 3381 ```````````````````````````````````````````````````````````````````````````````````
3394 3382
3395 3383 Merge:
3396 3384 - one with change to an unrelated file (b)
3397 3385 - one overwriting a file (d) with a rename (from h to i to d)
3398 3386
3399 3387 $ hg log -G --rev '::(desc("mBF-change-m")+desc("mFB-change-m"))'
3400 3388 o mFB-change-m-0 merge with extra change - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
3401 3389 |\
3402 3390 +---o mBF-change-m-0 merge with extra change - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
3403 3391 | |/
3404 3392 | o f-2: rename i -> d
3405 3393 | |
3406 3394 | o f-1: rename h -> i
3407 3395 | |
3408 3396 o | b-1: b update
3409 3397 |/
3410 3398 o i-2: c -move-> d, s -move-> t
3411 3399 |
3412 3400 o i-1: a -move-> c, p -move-> s
3413 3401 |
3414 3402 o i-0 initial commit: a b h p q r
3415 3403
3416 3404 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBF-change-m-0")'
3417 3405 M b
3418 3406 A d
3419 3407 h (filelog !)
3420 3408 h (sidedata !)
3421 a (upgraded known-bad-output !)
3422 h (upgraded missing-correct-output !)
3423 a (upgraded-parallel known-bad-output !)
3424 h (upgraded-parallel missing-correct-output !)
3409 h (upgraded !)
3410 h (upgraded-parallel !)
3425 3411 h (changeset !)
3426 3412 h (compatibility !)
3427 3413 A t
3428 3414 p
3429 3415 R a
3430 3416 R h
3431 3417 R p
3432 3418 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFB-change-m-0")'
3433 3419 M b
3434 3420 A d
3435 3421 h
3436 3422 A t
3437 3423 p
3438 3424 R a
3439 3425 R h
3440 3426 R p
3441 3427 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBF-change-m-0")'
3442 3428 M d
3443 3429 h (no-filelog !)
3444 3430 R h
3445 3431 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mBF-change-m-0")'
3446 3432 M b
3447 3433 M d
3448 3434 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mBF-change-m-0")'
3449 3435 M b
3450 3436 M d
3451 3437 i (no-filelog !)
3452 3438 R i
3453 3439 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mFB-change-m-0")'
3454 3440 M d
3455 3441 h (no-filelog !)
3456 3442 R h
3457 3443 $ hg status --copies --rev 'desc("f-2")' --rev 'desc("mFB-change-m-0")'
3458 3444 M b
3459 3445 M d
3460 3446 $ hg status --copies --rev 'desc("f-1")' --rev 'desc("mFB-change-m-0")'
3461 3447 M b
3462 3448 M d
3463 3449 i (no-filelog !)
3464 3450 R i
3465 3451
3466 3452 #if no-changeset
3467 3453 $ hg log -Gfr 'desc("mBF-change-m-0")' d
3468 3454 o mBF-change-m-0 merge with extra change - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
3469 3455 |\
3470 3456 o : f-2: rename i -> d
3471 3457 | :
3472 3458 o : f-1: rename h -> i
3473 3459 :/
3474 3460 o i-0 initial commit: a b h p q r
3475 3461
3476 3462 #else
3477 3463 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
3478 3464 $ hg log -Gfr 'desc("mBF-change-m-0")' d
3479 3465 o mBF-change-m-0 merge with extra change - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - one way
3480 3466 :
3481 3467 o i-2: c -move-> d, s -move-> t
3482 3468 |
3483 3469 ~
3484 3470 #endif
3485 3471
3486 3472 #if no-changeset
3487 3473 $ hg log -Gfr 'desc("mFB-change-m-0")' d
3488 3474 o mFB-change-m-0 merge with extra change - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
3489 3475 |\
3490 3476 o : f-2: rename i -> d
3491 3477 | :
3492 3478 o : f-1: rename h -> i
3493 3479 :/
3494 3480 o i-0 initial commit: a b h p q r
3495 3481
3496 3482 #else
3497 3483 BROKEN: `hg log --follow <file>` relies on filelog metadata to work
3498 3484 $ hg log -Gfr 'desc("mFB-change-m-0")' d
3499 3485 o mFB-change-m-0 merge with extra change - B side: unrelated change, F side: overwrite d with a copy (from h->i->d) - the other way
3500 3486 :
3501 3487 o i-2: c -move-> d, s -move-> t
3502 3488 |
3503 3489 ~
3504 3490 #endif
3505 3491
3506 3492
3507 3493 Subcase: restoring and untouched deleted file, while touching it
3508 3494 ````````````````````````````````````````````````````````````````
3509 3495
3510 3496 Merge:
3511 3497 - one removing a file (d)
3512 3498 - one leaving the file untouched
3513 3499 - the merge actively restore the file to the same content.
3514 3500
3515 3501 In this case, the file keep on living after the merge. So we should not drop its
3516 3502 copy tracing chain.
3517 3503
3518 3504 $ hg log -G --rev '::(desc("mCB-change-m")+desc("mBC-change-m"))'
3519 3505 o mBC-change-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - the other way
3520 3506 |\
3521 3507 +---o mCB-change-m-0 merge explicitely revive deleted file - B side: unrelated change, C side: delete d (restored by merge) - one way
3522 3508 | |/
3523 3509 | o c-1 delete d
3524 3510 | |
3525 3511 o | b-1: b update
3526 3512 |/
3527 3513 o i-2: c -move-> d, s -move-> t
3528 3514 |
3529 3515 o i-1: a -move-> c, p -move-> s
3530 3516 |
3531 3517 o i-0 initial commit: a b h p q r
3532 3518
3533 3519
3534 3520 'a' is the the copy source of 'd'
3535 3521
3536 3522 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB-change-m-0")'
3537 3523 M b
3538 3524 A d
3539 3525 a (no-compatibility no-changeset !)
3540 3526 A t
3541 3527 p
3542 3528 R a
3543 3529 R p
3544 3530 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC-change-m-0")'
3545 3531 M b
3546 3532 A d
3547 3533 a (no-compatibility no-changeset !)
3548 3534 A t
3549 3535 p
3550 3536 R a
3551 3537 R p
3552 3538 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCB-change-m-0")'
3553 3539 M b
3554 3540 A d
3555 3541 $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mBC-change-m-0")'
3556 3542 M b
3557 3543 A d
3558 3544 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCB-change-m-0")'
3559 3545 M d
3560 3546 $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBC-change-m-0")'
3561 3547 M d
3562 3548
3563 3549
3564 3550 Decision from previous merge are properly chained with later merge
3565 3551 ------------------------------------------------------------------
3566 3552
3567 3553
3568 3554 Subcase: chaining conflicting rename resolution
3569 3555 ```````````````````````````````````````````````
3570 3556
3571 3557 The "mAEm" and "mEAm" case create a rename tracking conflict on file 'f'. We
3572 3558 add more change on the respective branch and merge again. These second merge
3573 3559 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
3574 3560 about that file should stay unchanged.
3575 3561
3576 3562 The result from mAEm is the same for the subsequent merge:
3577 3563
3578 3564 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAEm")' f
3579 3565 A f
3580 3566 a (filelog !)
3581 3567 a (sidedata !)
3582 3568 a (upgraded !)
3583 3569 a (upgraded-parallel !)
3584 3570
3585 3571 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE,Km")' f
3586 3572 A f
3587 3573 a (filelog !)
3588 3574 a (sidedata !)
3589 3575 a (upgraded !)
3590 3576 a (upgraded-parallel !)
3591 3577
3592 3578 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mK,AEm")' f
3593 3579 A f
3594 3580 a (filelog !)
3595 3581 a (sidedata !)
3596 3582 a (upgraded !)
3597 3583 a (upgraded-parallel !)
3598 3584
3599 3585
3600 3586 The result from mEAm is the same for the subsequent merge:
3601 3587
3602 3588 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEAm")' f
3603 3589 A f
3604 3590 a (filelog !)
3605 3591 b (sidedata !)
3606 3592 b (upgraded !)
3607 3593 b (upgraded-parallel !)
3608 3594
3609 3595 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA,Jm")' f
3610 3596 A f
3611 3597 a (filelog !)
3612 3598 b (sidedata !)
3613 3599 b (upgraded !)
3614 3600 b (upgraded-parallel !)
3615 3601
3616 3602 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mJ,EAm")' f
3617 3603 A f
3618 3604 a (filelog !)
3619 3605 b (sidedata !)
3620 3606 b (upgraded !)
3621 3607 b (upgraded-parallel !)
3622 3608
3623 3609 Subcase: chaining conflicting rename resolution
3624 3610 ```````````````````````````````````````````````
3625 3611
3626 3612 The "mPQm" and "mQPm" case create a rename tracking conflict on file 'v'. We
3627 3613 add more change on the respective branch and merge again. These second merge
3628 3614 does not involve the file 'v' and the arbitration done within "mPQm" and "mQP"
3629 3615 about that file should stay unchanged.
3630 3616
3631 3617 The result from mPQm is the same for the subsequent merge:
3632 3618
3633 3619 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mPQm")' v
3634 3620 A v
3635 3621 r (filelog !)
3636 3622 p (sidedata !)
3637 3623 p (upgraded !)
3638 3624 p (upgraded-parallel !)
3639 3625
3640 3626 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mPQ,Tm")' v
3641 3627 A v
3642 3628 r (filelog !)
3643 3629 p (sidedata !)
3644 3630 p (upgraded !)
3645 3631 p (upgraded-parallel !)
3646 3632
3647 3633 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mT,PQm")' v
3648 3634 A v
3649 3635 r (filelog !)
3650 3636 p (sidedata !)
3651 3637 p (upgraded !)
3652 3638 p (upgraded-parallel !)
3653 3639
3654 3640
3655 3641 The result from mQPm is the same for the subsequent merge:
3656 3642
3657 3643 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mQPm")' v
3658 3644 A v
3659 3645 r (no-changeset no-compatibility !)
3660 3646
3661 3647 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mQP,Sm")' v
3662 3648 A v
3663 3649 r (no-changeset no-compatibility !)
3664 3650
3665 3651 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mS,QPm")' v
3666 3652 A v
3667 3653 r (filelog !)
3668 3654 r (sidedata !)
3669 3655 r (upgraded !)
3670 3656 r (upgraded-parallel !)
3671 3657
3672 3658
3673 3659 Subcase: chaining salvage information during a merge
3674 3660 ````````````````````````````````````````````````````
3675 3661
3676 3662 We add more change on the branch were the file was deleted. merging again
3677 3663 should preserve the fact eh file was salvaged.
3678 3664
3679 3665 reference output:
3680 3666
3681 3667 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB-revert-m-0")'
3682 3668 M b
3683 3669 A d
3684 3670 a (no-changeset no-compatibility !)
3685 3671 A t
3686 3672 p
3687 3673 R a
3688 3674 R p
3689 3675 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC-revert-m-0")'
3690 3676 M b
3691 3677 A d
3692 3678 a (no-changeset no-compatibility !)
3693 3679 A t
3694 3680 p
3695 3681 R a
3696 3682 R p
3697 3683
3698 3684 chained output
3699 3685 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBC+revert,Lm")'
3700 3686 M b
3701 3687 A d
3702 3688 a (no-changeset no-compatibility !)
3703 3689 A t
3704 3690 p
3705 3691 A unrelated-l
3706 3692 R a
3707 3693 R p
3708 3694 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCB+revert,Lm")'
3709 3695 M b
3710 3696 A d
3711 3697 a (no-changeset no-compatibility !)
3712 3698 A t
3713 3699 p
3714 3700 A unrelated-l
3715 3701 R a
3716 3702 R p
3717 3703 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mL,BC+revertm")'
3718 3704 M b
3719 3705 A d
3720 3706 a (no-changeset no-compatibility !)
3721 3707 A t
3722 3708 p
3723 3709 A unrelated-l
3724 3710 R a
3725 3711 R p
3726 3712 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mL,CB+revertm")'
3727 3713 M b
3728 3714 A d
3729 3715 a (no-changeset no-compatibility !)
3730 3716 A t
3731 3717 p
3732 3718 A unrelated-l
3733 3719 R a
3734 3720 R p
3735 3721
3736 3722 Subcase: chaining "merged" information during a merge
3737 3723 ``````````````````````````````````````````````````````
3738 3724
3739 3725 When a non-rename change are merged with a copy overwrite, the merge pick the copy source from (p1) as the reference. We should preserve this information in subsequent merges.
3740 3726
3741 3727
3742 3728 reference output:
3743 3729
3744 3730 (for details about the filelog pick, check the mFGm/mGFm case)
3745 3731
3746 3732 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFGm")' d
3747 3733 A d
3748 3734 a (filelog !)
3749 3735 h (sidedata !)
3750 3736 h (upgraded !)
3751 3737 h (upgraded-parallel !)
3752 3738 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGFm")' d
3753 3739 A d
3754 3740 a (filelog !)
3755 3741 a (sidedata !)
3756 3742 a (upgraded !)
3757 3743 a (upgraded-parallel !)
3758 3744
3759 3745 Chained output
3760 3746
3761 3747 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mO,FGm")' d
3762 3748 A d
3763 3749 a (filelog !)
3764 3750 h (sidedata !)
3765 3751 h (upgraded !)
3766 3752 h (upgraded-parallel !)
3767 3753 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFG,Om")' d
3768 3754 A d
3769 3755 a (filelog !)
3770 3756 h (sidedata !)
3771 3757 h (upgraded !)
3772 3758 h (upgraded-parallel !)
3773 3759
3774 3760
3775 3761 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGF,Nm")' d
3776 3762 A d
3777 3763 a (no-changeset no-compatibility !)
3778 3764 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mN,GFm")' d
3779 3765 A d
3780 3766 a (no-changeset no-compatibility !)
3781 3767
3782 3768
3783 3769 Subcase: chaining conflicting rename resolution, with extra change during the merge
3784 3770 ```````````````````````````````````````````````````````````````````````````````````
3785 3771
3786 3772 The "mAEm" and "mEAm" case create a rename tracking conflict on file 'f'. We
3787 3773 add more change on the respective branch and merge again. These second merge
3788 3774 does not involve the file 'f' and the arbitration done within "mAEm" and "mEA"
3789 3775 about that file should stay unchanged.
3790 3776
3791 3777 The result from mAEm is the same for the subsequent merge:
3792 3778
3793 3779 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE-change-m")' f
3794 3780 A f
3795 3781 a (filelog !)
3796 3782 a (sidedata !)
3797 3783 a (upgraded !)
3798 3784 a (upgraded-parallel !)
3799 3785
3800 3786 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAE-change,Km")' f
3801 3787 A f
3802 3788 a (filelog !)
3803 3789 a (sidedata !)
3804 3790 a (upgraded !)
3805 3791 a (upgraded-parallel !)
3806 3792
3807 3793 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mK,AE-change-m")' f
3808 3794 A f
3809 3795 a (no-changeset no-compatibility !)
3810 3796
3811 3797
3812 3798 The result from mEAm is the same for the subsequent merge:
3813 3799
3814 3800 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA-change-m")' f
3815 3801 A f
3816 3802 a (filelog !)
3817 3803 b (sidedata !)
3818 3804 b (upgraded !)
3819 3805 b (upgraded-parallel !)
3820 3806
3821 3807 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEA-change,Jm")' f
3822 3808 A f
3823 3809 a (filelog !)
3824 3810 b (sidedata !)
3825 3811 b (upgraded !)
3826 3812 b (upgraded-parallel !)
3827 3813
3828 3814 $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mJ,EA-change-m")' f
3829 3815 A f
3830 3816 a (filelog !)
3831 3817 b (sidedata !)
3832 3818 b (upgraded !)
3833 3819 b (upgraded-parallel !)
General Comments 0
You need to be logged in to leave comments. Login now