Mercurial > public > mercurial-scm > hg
comparison mercurial/scmutil.py @ 34354:2f427b57bf90 stable 4.3.3
rebase: move bookmarks with --keep (issue5682)
This is a regression caused by 3b7cb3d17137. We have documented the behavior
in rebase help:
Rebase will destroy original commits unless you use "--keep". It will
also move your bookmarks (even if you do).
So let's restore the old behavior.
It is done by changing `scmutil.cleanupnodes` to accept more information so
a node could have different "movement destination" from "successors". It
also helps simplifying the callsite as a side effect - the special bookmark
movement logic in rebase is removed.
Differential Revision: https://phab.mercurial-scm.org/D727
author | Jun Wu <quark@fb.com> |
---|---|
date | Mon, 18 Sep 2017 10:54:00 -0700 |
parents | 2dbd6d259cd2 |
children | f61f5af5ed31 |
comparison
equal
deleted
inserted
replaced
34353:2dbd6d259cd2 | 34354:2f427b57bf90 |
---|---|
574 self._revcontains = revcontainer.__contains__ | 574 self._revcontains = revcontainer.__contains__ |
575 | 575 |
576 def __contains__(self, node): | 576 def __contains__(self, node): |
577 return self._revcontains(self._torev(node)) | 577 return self._revcontains(self._torev(node)) |
578 | 578 |
579 def cleanupnodes(repo, replacements, operation): | 579 def cleanupnodes(repo, replacements, operation, moves=None): |
580 """do common cleanups when old nodes are replaced by new nodes | 580 """do common cleanups when old nodes are replaced by new nodes |
581 | 581 |
582 That includes writing obsmarkers or stripping nodes, and moving bookmarks. | 582 That includes writing obsmarkers or stripping nodes, and moving bookmarks. |
583 (we might also want to move working directory parent in the future) | 583 (we might also want to move working directory parent in the future) |
584 | |
585 By default, bookmark moves are calculated automatically from 'replacements', | |
586 but 'moves' can be used to override that. Also, 'moves' may include | |
587 additional bookmark moves that should not have associated obsmarkers. | |
584 | 588 |
585 replacements is {oldnode: [newnode]} or a iterable of nodes if they do not | 589 replacements is {oldnode: [newnode]} or a iterable of nodes if they do not |
586 have replacements. operation is a string, like "rebase". | 590 have replacements. operation is a string, like "rebase". |
587 """ | 591 """ |
592 if not replacements and not moves: | |
593 return | |
594 | |
595 # translate mapping's other forms | |
588 if not util.safehasattr(replacements, 'items'): | 596 if not util.safehasattr(replacements, 'items'): |
589 replacements = {n: () for n in replacements} | 597 replacements = {n: () for n in replacements} |
590 | 598 |
591 # Calculate bookmark movements | 599 # Calculate bookmark movements |
592 moves = {} | 600 if moves is None: |
601 moves = {} | |
593 # Unfiltered repo is needed since nodes in replacements might be hidden. | 602 # Unfiltered repo is needed since nodes in replacements might be hidden. |
594 unfi = repo.unfiltered() | 603 unfi = repo.unfiltered() |
595 for oldnode, newnodes in replacements.items(): | 604 for oldnode, newnodes in replacements.items(): |
605 if oldnode in moves: | |
606 continue | |
596 if len(newnodes) > 1: | 607 if len(newnodes) > 1: |
597 # usually a split, take the one with biggest rev number | 608 # usually a split, take the one with biggest rev number |
598 newnode = next(unfi.set('max(%ln)', newnodes)).node() | 609 newnode = next(unfi.set('max(%ln)', newnodes)).node() |
599 elif len(newnodes) == 0: | 610 elif len(newnodes) == 0: |
600 # move bookmark backwards | 611 # move bookmark backwards |
644 torev = unfi.changelog.rev | 655 torev = unfi.changelog.rev |
645 sortfunc = lambda ns: torev(ns[0]) | 656 sortfunc = lambda ns: torev(ns[0]) |
646 rels = [(unfi[n], tuple(unfi[m] for m in s)) | 657 rels = [(unfi[n], tuple(unfi[m] for m in s)) |
647 for n, s in sorted(replacements.items(), key=sortfunc) | 658 for n, s in sorted(replacements.items(), key=sortfunc) |
648 if s or not isobs(n)] | 659 if s or not isobs(n)] |
649 obsolete.createmarkers(repo, rels, operation=operation) | 660 if rels: |
661 obsolete.createmarkers(repo, rels, operation=operation) | |
650 else: | 662 else: |
651 from . import repair # avoid import cycle | 663 from . import repair # avoid import cycle |
652 repair.delayedstrip(repo.ui, repo, list(replacements), operation) | 664 tostrip = list(replacements) |
665 if tostrip: | |
666 repair.delayedstrip(repo.ui, repo, tostrip, operation) | |
653 | 667 |
654 def addremove(repo, matcher, prefix, opts=None, dry_run=None, similarity=None): | 668 def addremove(repo, matcher, prefix, opts=None, dry_run=None, similarity=None): |
655 if opts is None: | 669 if opts is None: |
656 opts = {} | 670 opts = {} |
657 m = matcher | 671 m = matcher |