Mercurial > hg
comparison mercurial/scmutil.py @ 34367:f61f5af5ed31
merge with stable
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Sat, 30 Sep 2017 07:52:48 -0700 |
parents | 255c761a52db 2f427b57bf90 |
children | 7757cc48b766 |
comparison
equal
deleted
inserted
replaced
34366:d00910b286cd | 34367:f61f5af5ed31 |
---|---|
592 self._revcontains = revcontainer.__contains__ | 592 self._revcontains = revcontainer.__contains__ |
593 | 593 |
594 def __contains__(self, node): | 594 def __contains__(self, node): |
595 return self._revcontains(self._torev(node)) | 595 return self._revcontains(self._torev(node)) |
596 | 596 |
597 def cleanupnodes(repo, mapping, operation): | 597 def cleanupnodes(repo, replacements, operation, moves=None): |
598 """do common cleanups when old nodes are replaced by new nodes | 598 """do common cleanups when old nodes are replaced by new nodes |
599 | 599 |
600 That includes writing obsmarkers or stripping nodes, and moving bookmarks. | 600 That includes writing obsmarkers or stripping nodes, and moving bookmarks. |
601 (we might also want to move working directory parent in the future) | 601 (we might also want to move working directory parent in the future) |
602 | 602 |
603 mapping is {oldnode: [newnode]} or a iterable of nodes if they do not have | 603 By default, bookmark moves are calculated automatically from 'replacements', |
604 replacements. operation is a string, like "rebase". | 604 but 'moves' can be used to override that. Also, 'moves' may include |
605 additional bookmark moves that should not have associated obsmarkers. | |
606 | |
607 replacements is {oldnode: [newnode]} or a iterable of nodes if they do not | |
608 have replacements. operation is a string, like "rebase". | |
605 """ | 609 """ |
606 if not util.safehasattr(mapping, 'items'): | 610 if not replacements and not moves: |
607 mapping = {n: () for n in mapping} | 611 return |
612 | |
613 # translate mapping's other forms | |
614 if not util.safehasattr(replacements, 'items'): | |
615 replacements = {n: () for n in replacements} | |
616 | |
617 # Calculate bookmark movements | |
618 if moves is None: | |
619 moves = {} | |
620 # Unfiltered repo is needed since nodes in replacements might be hidden. | |
621 unfi = repo.unfiltered() | |
622 for oldnode, newnodes in replacements.items(): | |
623 if oldnode in moves: | |
624 continue | |
625 if len(newnodes) > 1: | |
626 # usually a split, take the one with biggest rev number | |
627 newnode = next(unfi.set('max(%ln)', newnodes)).node() | |
628 elif len(newnodes) == 0: | |
629 # move bookmark backwards | |
630 roots = list(unfi.set('max((::%n) - %ln)', oldnode, | |
631 list(replacements))) | |
632 if roots: | |
633 newnode = roots[0].node() | |
634 else: | |
635 newnode = nullid | |
636 else: | |
637 newnode = newnodes[0] | |
638 moves[oldnode] = newnode | |
608 | 639 |
609 with repo.transaction('cleanup') as tr: | 640 with repo.transaction('cleanup') as tr: |
610 # Move bookmarks | 641 # Move bookmarks |
611 bmarks = repo._bookmarks | 642 bmarks = repo._bookmarks |
612 bmarkchanges = [] | 643 bmarkchanges = [] |
613 allnewnodes = [n for ns in mapping.values() for n in ns] | 644 allnewnodes = [n for ns in replacements.values() for n in ns] |
614 for oldnode, newnodes in mapping.items(): | 645 for oldnode, newnode in moves.items(): |
615 oldbmarks = repo.nodebookmarks(oldnode) | 646 oldbmarks = repo.nodebookmarks(oldnode) |
616 if not oldbmarks: | 647 if not oldbmarks: |
617 continue | 648 continue |
618 from . import bookmarks # avoid import cycle | 649 from . import bookmarks # avoid import cycle |
619 if len(newnodes) > 1: | |
620 # usually a split, take the one with biggest rev number | |
621 newnode = next(repo.set('max(%ln)', newnodes)).node() | |
622 elif len(newnodes) == 0: | |
623 # move bookmark backwards | |
624 roots = list(repo.set('max((::%n) - %ln)', oldnode, | |
625 list(mapping))) | |
626 if roots: | |
627 newnode = roots[0].node() | |
628 else: | |
629 newnode = nullid | |
630 else: | |
631 newnode = newnodes[0] | |
632 repo.ui.debug('moving bookmarks %r from %s to %s\n' % | 650 repo.ui.debug('moving bookmarks %r from %s to %s\n' % |
633 (oldbmarks, hex(oldnode), hex(newnode))) | 651 (oldbmarks, hex(oldnode), hex(newnode))) |
634 # Delete divergent bookmarks being parents of related newnodes | 652 # Delete divergent bookmarks being parents of related newnodes |
635 deleterevs = repo.revs('parents(roots(%ln & (::%n))) - parents(%n)', | 653 deleterevs = repo.revs('parents(roots(%ln & (::%n))) - parents(%n)', |
636 allnewnodes, newnode, oldnode) | 654 allnewnodes, newnode, oldnode) |
649 # without a successor, skip that obssolete request since it's | 667 # without a successor, skip that obssolete request since it's |
650 # unnecessary. That's the "if s or not isobs(n)" check below. | 668 # unnecessary. That's the "if s or not isobs(n)" check below. |
651 # Also sort the node in topology order, that might be useful for | 669 # Also sort the node in topology order, that might be useful for |
652 # some obsstore logic. | 670 # some obsstore logic. |
653 # NOTE: the filtering and sorting might belong to createmarkers. | 671 # NOTE: the filtering and sorting might belong to createmarkers. |
654 # Unfiltered repo is needed since nodes in mapping might be hidden. | |
655 unfi = repo.unfiltered() | |
656 isobs = unfi.obsstore.successors.__contains__ | 672 isobs = unfi.obsstore.successors.__contains__ |
657 torev = unfi.changelog.rev | 673 torev = unfi.changelog.rev |
658 sortfunc = lambda ns: torev(ns[0]) | 674 sortfunc = lambda ns: torev(ns[0]) |
659 rels = [(unfi[n], tuple(unfi[m] for m in s)) | 675 rels = [(unfi[n], tuple(unfi[m] for m in s)) |
660 for n, s in sorted(mapping.items(), key=sortfunc) | 676 for n, s in sorted(replacements.items(), key=sortfunc) |
661 if s or not isobs(n)] | 677 if s or not isobs(n)] |
662 obsolete.createmarkers(repo, rels, operation=operation) | 678 if rels: |
679 obsolete.createmarkers(repo, rels, operation=operation) | |
663 else: | 680 else: |
664 from . import repair # avoid import cycle | 681 from . import repair # avoid import cycle |
665 repair.delayedstrip(repo.ui, repo, list(mapping), operation) | 682 tostrip = list(replacements) |
683 if tostrip: | |
684 repair.delayedstrip(repo.ui, repo, tostrip, operation) | |
666 | 685 |
667 def addremove(repo, matcher, prefix, opts=None, dry_run=None, similarity=None): | 686 def addremove(repo, matcher, prefix, opts=None, dry_run=None, similarity=None): |
668 if opts is None: | 687 if opts is None: |
669 opts = {} | 688 opts = {} |
670 m = matcher | 689 m = matcher |