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