##// END OF EJS Templates
merge with stable
Martin von Zweigbergk -
r34366:f61f5af5 merge default
parent child Browse files
Show More
@@ -547,12 +547,12 b' class rebaseruntime(object):'
547 ui.note(_("update back to initial working directory parent\n"))
547 ui.note(_("update back to initial working directory parent\n"))
548 hg.updaterepo(repo, newwd, False)
548 hg.updaterepo(repo, newwd, False)
549
549
550 collapsedas = None
550 if not self.keepf:
551 if not self.keepf:
551 collapsedas = None
552 if self.collapsef:
552 if self.collapsef:
553 collapsedas = newnode
553 collapsedas = newnode
554 clearrebased(ui, repo, self.destmap, self.state, self.skipped,
554 clearrebased(ui, repo, self.destmap, self.state, self.skipped,
555 collapsedas)
555 collapsedas, self.keepf)
556
556
557 clearstatus(repo)
557 clearstatus(repo)
558 clearcollapsemsg(repo)
558 clearcollapsemsg(repo)
@@ -1516,32 +1516,31 b' def buildstate(repo, destmap, collapse):'
1516 state[rev] = rev
1516 state[rev] = rev
1517 return originalwd, destmap, state
1517 return originalwd, destmap, state
1518
1518
1519 def clearrebased(ui, repo, destmap, state, skipped, collapsedas=None):
1519 def clearrebased(ui, repo, destmap, state, skipped, collapsedas=None,
1520 keepf=False):
1520 """dispose of rebased revision at the end of the rebase
1521 """dispose of rebased revision at the end of the rebase
1521
1522
1522 If `collapsedas` is not None, the rebase was a collapse whose result if the
1523 If `collapsedas` is not None, the rebase was a collapse whose result if the
1523 `collapsedas` node."""
1524 `collapsedas` node.
1525
1526 If `keepf` is not True, the rebase has --keep set and no nodes should be
1527 removed (but bookmarks still need to be moved).
1528 """
1524 tonode = repo.changelog.node
1529 tonode = repo.changelog.node
1525 # Move bookmark of skipped nodes to destination. This cannot be handled
1530 replacements = {}
1526 # by scmutil.cleanupnodes since it will treat rev as removed (no successor)
1531 moves = {}
1527 # and move bookmark backwards.
1528 bmchanges = [(name, tonode(state[rev]))
1529 for rev in skipped
1530 for name in repo.nodebookmarks(tonode(rev))]
1531 if bmchanges:
1532 with repo.transaction('rebase') as tr:
1533 repo._bookmarks.applychanges(repo, tr, bmchanges)
1534 mapping = {}
1535 for rev, newrev in sorted(state.items()):
1532 for rev, newrev in sorted(state.items()):
1536 if newrev >= 0 and newrev != rev:
1533 if newrev >= 0 and newrev != rev:
1537 if rev in skipped:
1534 oldnode = tonode(rev)
1538 succs = ()
1535 newnode = collapsedas or tonode(newrev)
1539 elif collapsedas is not None:
1536 moves[oldnode] = newnode
1540 succs = (collapsedas,)
1537 if not keepf:
1541 else:
1538 if rev in skipped:
1542 succs = (tonode(newrev),)
1539 succs = ()
1543 mapping[tonode(rev)] = succs
1540 else:
1544 scmutil.cleanupnodes(repo, mapping, 'rebase')
1541 succs = (newnode,)
1542 replacements[oldnode] = succs
1543 scmutil.cleanupnodes(repo, replacements, 'rebase', moves)
1545
1544
1546 def pullrebase(orig, ui, repo, *args, **opts):
1545 def pullrebase(orig, ui, repo, *args, **opts):
1547 'Call rebase after pull if the latter has been invoked with --rebase'
1546 'Call rebase after pull if the latter has been invoked with --rebase'
@@ -594,41 +594,59 b' class _containsnode(object):'
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
@@ -651,18 +669,19 b' def cleanupnodes(repo, mapping, operatio'
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:
@@ -1488,7 +1488,7 b' class ui(object):'
1488
1488
1489 def _progclear(self):
1489 def _progclear(self):
1490 """clear progress bar output if any. use it before any output"""
1490 """clear progress bar output if any. use it before any output"""
1491 if '_progbar' not in vars(self): # nothing loaded yet
1491 if not haveprogbar(): # nothing loaded yet
1492 return
1492 return
1493 if self._progbar is not None and self._progbar.printed:
1493 if self._progbar is not None and self._progbar.printed:
1494 self._progbar.clear()
1494 self._progbar.clear()
@@ -1792,3 +1792,6 b' def getprogbar(ui):'
1792 # this is how the extension used to work but feel free to rework it.
1792 # this is how the extension used to work but feel free to rework it.
1793 _progresssingleton = progress.progbar(ui)
1793 _progresssingleton = progress.progbar(ui)
1794 return _progresssingleton
1794 return _progresssingleton
1795
1796 def haveprogbar():
1797 return _progresssingleton is not None
@@ -1,6 +1,7 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > rebase=
3 > rebase=
4 > drawdag=$TESTDIR/drawdag.py
4 >
5 >
5 > [phases]
6 > [phases]
6 > publish=False
7 > publish=False
@@ -210,3 +211,35 b' as --rev arguments (issue3950)'
210 rebasing 6:f677a2907404 "bisect2"
211 rebasing 6:f677a2907404 "bisect2"
211 rebasing 7:325c16001345 "bisect3" (bisect tip)
212 rebasing 7:325c16001345 "bisect3" (bisect tip)
212 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/345c90f326a4-b4840586-rebase.hg (glob)
213 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/345c90f326a4-b4840586-rebase.hg (glob)
214
215 Bookmark and working parent get moved even if --keep is set (issue5682)
216
217 $ hg init $TESTTMP/book-keep
218 $ cd $TESTTMP/book-keep
219 $ hg debugdrawdag <<'EOS'
220 > B C
221 > |/
222 > A
223 > EOS
224 $ eval `hg tags -T 'hg bookmark -ir {node} {tag};\n' | grep -v tip`
225 $ rm .hg/localtags
226 $ hg up -q B
227 $ hg tglog
228 o 2: 'C' bookmarks: C
229 |
230 | @ 1: 'B' bookmarks: B
231 |/
232 o 0: 'A' bookmarks: A
233
234 $ hg rebase -r B -d C --keep
235 rebasing 1:112478962961 "B" (B)
236 $ hg tglog
237 @ 3: 'B' bookmarks: B
238 |
239 o 2: 'C' bookmarks: C
240 |
241 | o 1: 'B' bookmarks:
242 |/
243 o 0: 'A' bookmarks: A
244
245
@@ -47,7 +47,7 b''
47 |/
47 |/
48 o 0 A
48 o 0 A
49
49
50 With --keep, bookmark should not move
50 With --keep, bookmark should move
51
51
52 $ hg rebase -r 3+4 -d E --keep
52 $ hg rebase -r 3+4 -d E --keep
53 rebasing 3:e7b3f00ed42e "D" (BOOK-D)
53 rebasing 3:e7b3f00ed42e "D" (BOOK-D)
@@ -55,15 +55,15 b' With --keep, bookmark should not move'
55 rebasing 4:69a34c08022a "E" (BOOK-E)
55 rebasing 4:69a34c08022a "E" (BOOK-E)
56 note: rebase of 4:69a34c08022a created no changes to commit
56 note: rebase of 4:69a34c08022a created no changes to commit
57 $ hg log -G -T '{rev} {desc} {bookmarks}'
57 $ hg log -G -T '{rev} {desc} {bookmarks}'
58 o 7 E
58 o 7 E BOOK-D BOOK-E
59 |
59 |
60 o 6 D
60 o 6 D
61 |
61 |
62 | o 5 F BOOK-F
62 | o 5 F BOOK-F
63 | |
63 | |
64 | o 4 E BOOK-E
64 | o 4 E
65 | |
65 | |
66 | o 3 D BOOK-D
66 | o 3 D
67 | |
67 | |
68 | o 2 C BOOK-C
68 | o 2 C BOOK-C
69 | |
69 | |
@@ -71,6 +71,11 b' With --keep, bookmark should not move'
71 |/
71 |/
72 o 0 A
72 o 0 A
73
73
74 Move D and E back for the next test
75
76 $ hg bookmark BOOK-D -fqir 3
77 $ hg bookmark BOOK-E -fqir 4
78
74 Bookmark is usually an indication of a head. For changes that are introduced by
79 Bookmark is usually an indication of a head. For changes that are introduced by
75 an ancestor of bookmark B, after moving B to B-NEW, the changes are ideally
80 an ancestor of bookmark B, after moving B to B-NEW, the changes are ideally
76 still introduced by an ancestor of changeset on B-NEW. In the below case,
81 still introduced by an ancestor of changeset on B-NEW. In the below case,
@@ -63,6 +63,14 b" Preparing the 'main' repo which depends "
63 \r (no-eol) (esc)
63 \r (no-eol) (esc)
64 \r (no-eol) (esc)
64 \r (no-eol) (esc)
65 updating [===========================================>] 3/3\r (no-eol) (esc)
65 updating [===========================================>] 3/3\r (no-eol) (esc)
66 \r (no-eol) (esc)
67 \r (no-eol) (esc)
68 linking [ <=> ] 1\r (no-eol) (esc)
69 linking [ <=> ] 2\r (no-eol) (esc)
70 linking [ <=> ] 3\r (no-eol) (esc)
71 linking [ <=> ] 4\r (no-eol) (esc)
72 linking [ <=> ] 5\r (no-eol) (esc)
73 linking [ <=> ] 6\r (no-eol) (esc)
66 updating [===========================================>] 1/1\r (no-eol) (esc)
74 updating [===========================================>] 1/1\r (no-eol) (esc)
67 \r (no-eol) (esc)
75 \r (no-eol) (esc)
68 updating to branch default
76 updating to branch default
@@ -154,7 +162,25 b' Clone main'
154 \r (no-eol) (esc)
162 \r (no-eol) (esc)
155 \r (no-eol) (esc)
163 \r (no-eol) (esc)
156 updating [===========================================>] 3/3\r (no-eol) (esc)
164 updating [===========================================>] 3/3\r (no-eol) (esc)
165 \r (no-eol) (esc)
166 \r (no-eol) (esc)
167 linking [ <=> ] 1\r (no-eol) (esc)
168 linking [ <=> ] 2\r (no-eol) (esc)
169 linking [ <=> ] 3\r (no-eol) (esc)
170 linking [ <=> ] 4\r (no-eol) (esc)
171 linking [ <=> ] 5\r (no-eol) (esc)
172 linking [ <=> ] 6\r (no-eol) (esc)
173 linking [ <=> ] 7\r (no-eol) (esc)
174 linking [ <=> ] 8\r (no-eol) (esc)
157 updating [===========================================>] 3/3\r (no-eol) (esc)
175 updating [===========================================>] 3/3\r (no-eol) (esc)
176 \r (no-eol) (esc)
177 \r (no-eol) (esc)
178 linking [ <=> ] 1\r (no-eol) (esc)
179 linking [ <=> ] 2\r (no-eol) (esc)
180 linking [ <=> ] 3\r (no-eol) (esc)
181 linking [ <=> ] 4\r (no-eol) (esc)
182 linking [ <=> ] 5\r (no-eol) (esc)
183 linking [ <=> ] 6\r (no-eol) (esc)
158 updating [===========================================>] 1/1\r (no-eol) (esc)
184 updating [===========================================>] 1/1\r (no-eol) (esc)
159 \r (no-eol) (esc)
185 \r (no-eol) (esc)
160 updating to branch default
186 updating to branch default
General Comments 0
You need to be logged in to leave comments. Login now