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