Mercurial > hg
comparison mercurial/copies.py @ 44199:7f8bdee0034e
copies: define a type to return from mergecopies()
We'll soon return two instances of many of the dicts from
`copies.mergecopies()`. That will mean that we need to return 9
different dicts, which is clearly not manageable. This patch instead
encapsulates the 4 dicts we'll duplicate in a new type. For now, we
still just return one instance of it (plus the separate `diverge`
dict).
Differential Revision: https://phab.mercurial-scm.org/D7989
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Wed, 22 Jan 2020 14:35:30 -0800 |
parents | 17e12938f8e7 |
children | fa9ad1da2e77 |
comparison
equal
deleted
inserted
replaced
44198:8ad263c3a358 | 44199:7f8bdee0034e |
---|---|
450 revision 4, and if user have copytrace disabled, we prints the following | 450 revision 4, and if user have copytrace disabled, we prints the following |
451 message: | 451 message: |
452 | 452 |
453 ```other changed <file> which local deleted``` | 453 ```other changed <file> which local deleted``` |
454 | 454 |
455 Returns five dicts: "copy", "movewithdir", "diverge", "renamedelete" and | 455 Returns a tuple where: |
456 "dirmove". | 456 |
457 | 457 "branch_copies" an instance of branch_copies. |
458 "copy" is a mapping from destination name -> source name, | |
459 where source is in c1 and destination is in c2 or vice-versa. | |
460 | |
461 "movewithdir" is a mapping from source name -> destination name, | |
462 where the file at source present in one context but not the other | |
463 needs to be moved to destination by the merge process, because the | |
464 other context moved the directory it is in. | |
465 | 458 |
466 "diverge" is a mapping of source name -> list of destination names | 459 "diverge" is a mapping of source name -> list of destination names |
467 for divergent renames. | 460 for divergent renames. |
468 | 461 |
469 "renamedelete" is a mapping of source name -> list of destination | |
470 names for files deleted in c1 that were renamed in c2 or vice-versa. | |
471 | |
472 "dirmove" is a mapping of detected source dir -> destination dir renames. | |
473 This is needed for handling changes to new files previously grafted into | |
474 renamed directories. | |
475 | |
476 This function calls different copytracing algorithms based on config. | 462 This function calls different copytracing algorithms based on config. |
477 """ | 463 """ |
478 # avoid silly behavior for update from empty dir | 464 # avoid silly behavior for update from empty dir |
479 if not c1 or not c2 or c1 == c2: | 465 if not c1 or not c2 or c1 == c2: |
480 return {}, {}, {}, {}, {} | 466 return branch_copies(), {} |
481 | 467 |
482 narrowmatch = c1.repo().narrowmatch() | 468 narrowmatch = c1.repo().narrowmatch() |
483 | 469 |
484 # avoid silly behavior for parent -> working dir | 470 # avoid silly behavior for parent -> working dir |
485 if c2.node() is None and c1.node() == repo.dirstate.p1(): | 471 if c2.node() is None and c1.node() == repo.dirstate.p1(): |
486 return _dirstatecopies(repo, narrowmatch), {}, {}, {}, {} | 472 return branch_copies(_dirstatecopies(repo, narrowmatch)), {} |
487 | 473 |
488 copytracing = repo.ui.config(b'experimental', b'copytrace') | 474 copytracing = repo.ui.config(b'experimental', b'copytrace') |
489 if stringutil.parsebool(copytracing) is False: | 475 if stringutil.parsebool(copytracing) is False: |
490 # stringutil.parsebool() returns None when it is unable to parse the | 476 # stringutil.parsebool() returns None when it is unable to parse the |
491 # value, so we should rely on making sure copytracing is on such cases | 477 # value, so we should rely on making sure copytracing is on such cases |
492 return {}, {}, {}, {}, {} | 478 return branch_copies(), {} |
493 | 479 |
494 if usechangesetcentricalgo(repo): | 480 if usechangesetcentricalgo(repo): |
495 # The heuristics don't make sense when we need changeset-centric algos | 481 # The heuristics don't make sense when we need changeset-centric algos |
496 return _fullcopytracing(repo, c1, c2, base) | 482 return _fullcopytracing(repo, c1, c2, base) |
497 | 483 |
546 # dst not added on side 2 (handle as regular | 532 # dst not added on side 2 (handle as regular |
547 # "both created" case in manifestmerge otherwise) | 533 # "both created" case in manifestmerge otherwise) |
548 copy[dst] = src | 534 copy[dst] = src |
549 | 535 |
550 | 536 |
537 class branch_copies(object): | |
538 """Information about copies made on one side of a merge/graft. | |
539 | |
540 "copy" is a mapping from destination name -> source name, | |
541 where source is in c1 and destination is in c2 or vice-versa. | |
542 | |
543 "movewithdir" is a mapping from source name -> destination name, | |
544 where the file at source present in one context but not the other | |
545 needs to be moved to destination by the merge process, because the | |
546 other context moved the directory it is in. | |
547 | |
548 "renamedelete" is a mapping of source name -> list of destination | |
549 names for files deleted in c1 that were renamed in c2 or vice-versa. | |
550 | |
551 "dirmove" is a mapping of detected source dir -> destination dir renames. | |
552 This is needed for handling changes to new files previously grafted into | |
553 renamed directories. | |
554 """ | |
555 | |
556 def __init__( | |
557 self, copy=None, renamedelete=None, dirmove=None, movewithdir=None | |
558 ): | |
559 self.copy = {} if copy is None else copy | |
560 self.renamedelete = {} if renamedelete is None else renamedelete | |
561 self.dirmove = {} if dirmove is None else dirmove | |
562 self.movewithdir = {} if movewithdir is None else movewithdir | |
563 | |
564 | |
551 def _fullcopytracing(repo, c1, c2, base): | 565 def _fullcopytracing(repo, c1, c2, base): |
552 """ The full copytracing algorithm which finds all the new files that were | 566 """ The full copytracing algorithm which finds all the new files that were |
553 added from merge base up to the top commit and for each file it checks if | 567 added from merge base up to the top commit and for each file it checks if |
554 this file was copied from another file. | 568 this file was copied from another file. |
555 | 569 |
562 | 576 |
563 copies1 = pathcopies(base, c1) | 577 copies1 = pathcopies(base, c1) |
564 copies2 = pathcopies(base, c2) | 578 copies2 = pathcopies(base, c2) |
565 | 579 |
566 if not (copies1 or copies2): | 580 if not (copies1 or copies2): |
567 return {}, {}, {}, {}, {} | 581 return branch_copies(), {} |
568 | 582 |
569 inversecopies1 = {} | 583 inversecopies1 = {} |
570 inversecopies2 = {} | 584 inversecopies2 = {} |
571 for dst, src in copies1.items(): | 585 for dst, src in copies1.items(): |
572 inversecopies1.setdefault(src, []).append(dst) | 586 inversecopies1.setdefault(src, []).append(dst) |
670 copy1.update(copy2) | 684 copy1.update(copy2) |
671 renamedelete1.update(renamedelete2) | 685 renamedelete1.update(renamedelete2) |
672 movewithdir1.update(movewithdir2) | 686 movewithdir1.update(movewithdir2) |
673 dirmove1.update(dirmove2) | 687 dirmove1.update(dirmove2) |
674 | 688 |
675 return copy1, movewithdir1, diverge, renamedelete1, dirmove1 | 689 return branch_copies(copy1, renamedelete1, dirmove1, movewithdir1), diverge |
676 | 690 |
677 | 691 |
678 def _dir_renames(repo, ctx, copy, fullcopy, addedfiles): | 692 def _dir_renames(repo, ctx, copy, fullcopy, addedfiles): |
679 """Finds moved directories and files that should move with them. | 693 """Finds moved directories and files that should move with them. |
680 | 694 |
844 # if there are a few related copies then we'll merge | 858 # if there are a few related copies then we'll merge |
845 # changes into all of them. This matches the behaviour | 859 # changes into all of them. This matches the behaviour |
846 # of upstream copytracing | 860 # of upstream copytracing |
847 copies[candidate] = f | 861 copies[candidate] = f |
848 | 862 |
849 return copies, {}, {}, {}, {} | 863 return branch_copies(copies), {} |
850 | 864 |
851 | 865 |
852 def _related(f1, f2): | 866 def _related(f1, f2): |
853 """return True if f1 and f2 filectx have a common ancestor | 867 """return True if f1 and f2 filectx have a common ancestor |
854 | 868 |