Show More
@@ -508,12 +508,12 b' class rebaseruntime(object):' | |||||
508 | ui.note(_("update back to initial working directory parent\n")) |
|
508 | ui.note(_("update back to initial working directory parent\n")) | |
509 | hg.updaterepo(repo, newwd, False) |
|
509 | hg.updaterepo(repo, newwd, False) | |
510 |
|
510 | |||
|
511 | collapsedas = None | |||
511 | if not self.keepf: |
|
512 | if not self.keepf: | |
512 | collapsedas = None |
|
|||
513 | if self.collapsef: |
|
513 | if self.collapsef: | |
514 | collapsedas = newnode |
|
514 | collapsedas = newnode | |
515 |
|
|
515 | clearrebased(ui, repo, self.dest, self.state, self.skipped, | |
516 |
|
|
516 | collapsedas, self.keepf) | |
517 |
|
517 | |||
518 | clearstatus(repo) |
|
518 | clearstatus(repo) | |
519 | clearcollapsemsg(repo) |
|
519 | clearcollapsemsg(repo) | |
@@ -1354,32 +1354,30 b' def buildstate(repo, dest, rebaseset, co' | |||||
1354 | state[r] = revprecursor |
|
1354 | state[r] = revprecursor | |
1355 | return originalwd, dest.rev(), state |
|
1355 | return originalwd, dest.rev(), state | |
1356 |
|
1356 | |||
1357 | def clearrebased(ui, repo, dest, state, skipped, collapsedas=None): |
|
1357 | def clearrebased(ui, repo, dest, state, skipped, collapsedas=None, keepf=False): | |
1358 | """dispose of rebased revision at the end of the rebase |
|
1358 | """dispose of rebased revision at the end of the rebase | |
1359 |
|
1359 | |||
1360 | If `collapsedas` is not None, the rebase was a collapse whose result if the |
|
1360 | If `collapsedas` is not None, the rebase was a collapse whose result if the | |
1361 |
`collapsedas` node. |
|
1361 | `collapsedas` node. | |
|
1362 | ||||
|
1363 | If `keepf` is not True, the rebase has --keep set and no nodes should be | |||
|
1364 | removed (but bookmarks still need to be moved). | |||
|
1365 | """ | |||
1362 | tonode = repo.changelog.node |
|
1366 | tonode = repo.changelog.node | |
1363 | # Move bookmark of skipped nodes to destination. This cannot be handled |
|
1367 | replacements = {} | |
1364 | # by scmutil.cleanupnodes since it will treat rev as removed (no successor) |
|
1368 | moves = {} | |
1365 | # and move bookmark backwards. |
|
|||
1366 | bmchanges = [(name, tonode(max(adjustdest(repo, rev, dest, state)))) |
|
|||
1367 | for rev in skipped |
|
|||
1368 | for name in repo.nodebookmarks(tonode(rev))] |
|
|||
1369 | if bmchanges: |
|
|||
1370 | with repo.transaction('rebase') as tr: |
|
|||
1371 | repo._bookmarks.applychanges(repo, tr, bmchanges) |
|
|||
1372 | mapping = {} |
|
|||
1373 | for rev, newrev in sorted(state.items()): |
|
1369 | for rev, newrev in sorted(state.items()): | |
1374 | if newrev >= 0 and newrev != rev: |
|
1370 | if newrev >= 0 and newrev != rev: | |
1375 | if rev in skipped: |
|
1371 | oldnode = tonode(rev) | |
1376 | succs = () |
|
1372 | newnode = collapsedas or tonode(newrev) | |
1377 | elif collapsedas is not None: |
|
1373 | moves[oldnode] = newnode | |
1378 | succs = (collapsedas,) |
|
1374 | if not keepf: | |
1379 |
|
|
1375 | if rev in skipped: | |
1380 |
succs = ( |
|
1376 | succs = () | |
1381 | mapping[tonode(rev)] = succs |
|
1377 | else: | |
1382 | scmutil.cleanupnodes(repo, mapping, 'rebase') |
|
1378 | succs = (newnode,) | |
|
1379 | replacements[oldnode] = succs | |||
|
1380 | scmutil.cleanupnodes(repo, replacements, 'rebase', moves) | |||
1383 |
|
1381 | |||
1384 | def pullrebase(orig, ui, repo, *args, **opts): |
|
1382 | def pullrebase(orig, ui, repo, *args, **opts): | |
1385 | 'Call rebase after pull if the latter has been invoked with --rebase' |
|
1383 | 'Call rebase after pull if the latter has been invoked with --rebase' |
@@ -576,23 +576,34 b' class _containsnode(object):' | |||||
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 |
|
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. | |||
|
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() | |
@@ -646,10 +657,13 b' def cleanupnodes(repo, replacements, ope' | |||||
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 |
|
|
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: |
@@ -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" (tip bisect) |
|
212 | rebasing 7:325c16001345 "bisect3" (tip bisect) | |
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 |
|
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 |
|
64 | | o 4 E | |
65 | | | |
|
65 | | | | |
66 |
| o 3 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, |
General Comments 0
You need to be logged in to leave comments.
Login now