Show More
@@ -108,6 +108,25 b' def _revsetdestrebase(repo, subset, x):' | |||
|
108 | 108 | sourceset = revset.getset(repo, smartset.fullreposet(repo), x) |
|
109 | 109 | return subset & smartset.baseset([_destrebase(repo, sourceset)]) |
|
110 | 110 | |
|
111 | @revsetpredicate('_destautoorphanrebase') | |
|
112 | def _revsetdestautoorphanrebase(repo, subset, x): | |
|
113 | """automatic rebase destination for a single orphan revision""" | |
|
114 | unfi = repo.unfiltered() | |
|
115 | obsoleted = unfi.revs('obsolete()') | |
|
116 | ||
|
117 | src = revset.getset(repo, subset, x).first() | |
|
118 | ||
|
119 | # Empty src or already obsoleted - Do not return a destination | |
|
120 | if not src or src in obsoleted: | |
|
121 | return smartset.baseset() | |
|
122 | dests = destutil.orphanpossibledestination(repo, src) | |
|
123 | if len(dests) > 1: | |
|
124 | raise error.Abort( | |
|
125 | _("ambiguous automatic rebase: %r could end up on any of %r") % ( | |
|
126 | src, dests)) | |
|
127 | # We have zero or one destination, so we can just return here. | |
|
128 | return smartset.baseset(dests) | |
|
129 | ||
|
111 | 130 | def _ctxdesc(ctx): |
|
112 | 131 | """short description for a context""" |
|
113 | 132 | desc = '%d:%s "%s"' % (ctx.rev(), ctx, |
@@ -651,7 +670,10 b' class rebaseruntime(object):' | |||
|
651 | 670 | ('i', 'interactive', False, _('(DEPRECATED)')), |
|
652 | 671 | ('t', 'tool', '', _('specify merge tool')), |
|
653 | 672 | ('c', 'continue', False, _('continue an interrupted rebase')), |
|
654 |
('a', 'abort', False, _('abort an interrupted rebase')) |
|
|
673 | ('a', 'abort', False, _('abort an interrupted rebase')), | |
|
674 | ('', 'auto-orphans', '', _('automatically rebase orphan revisions ' | |
|
675 | 'in the specified revset (EXPERIMENTAL)')), | |
|
676 | ] + | |
|
655 | 677 | cmdutil.formatteropts, |
|
656 | 678 | _('[-s REV | -b REV] [-d REV] [OPTION]')) |
|
657 | 679 | def rebase(ui, repo, **opts): |
@@ -783,6 +805,15 b' def rebase(ui, repo, **opts):' | |||
|
783 | 805 | # fail the entire transaction.) |
|
784 | 806 | inmemory = False |
|
785 | 807 | |
|
808 | if opts.get('auto_orphans'): | |
|
809 | for key in opts: | |
|
810 | if key != 'auto_orphans' and opts.get(key): | |
|
811 | raise error.Abort(_('--auto-orphans is incompatible with %s') % | |
|
812 | ('--' + key)) | |
|
813 | userrevs = list(repo.revs(opts.get('auto_orphans'))) | |
|
814 | opts['rev'] = [revsetlang.formatspec('%ld and orphan()', userrevs)] | |
|
815 | opts['dest'] = '_destautoorphanrebase(SRC)' | |
|
816 | ||
|
786 | 817 | if inmemory: |
|
787 | 818 | try: |
|
788 | 819 | # in-memory merge doesn't support conflicts, so if we hit any, abort |
@@ -16,6 +16,39 b' from . import (' | |||
|
16 | 16 | stack |
|
17 | 17 | ) |
|
18 | 18 | |
|
19 | def orphanpossibledestination(repo, rev): | |
|
20 | """Return all changesets that may be a new parent for orphan `rev`. | |
|
21 | ||
|
22 | This function works fine on non-orphan revisions, it's just silly | |
|
23 | because there's no destination implied by obsolete markers, so | |
|
24 | it'll return nothing. | |
|
25 | """ | |
|
26 | tonode = repo.changelog.node | |
|
27 | parents = repo.changelog.parentrevs | |
|
28 | torev = repo.changelog.rev | |
|
29 | dest = set() | |
|
30 | tovisit = list(parents(rev)) | |
|
31 | while tovisit: | |
|
32 | r = tovisit.pop() | |
|
33 | succsets = obsutil.successorssets(repo, tonode(r)) | |
|
34 | if not succsets: | |
|
35 | # if there are no successors for r, r was probably pruned | |
|
36 | # and we should walk up to r's parents to try and find | |
|
37 | # some successors. | |
|
38 | tovisit.extend(parents(r)) | |
|
39 | else: | |
|
40 | # We should probably pick only one destination from split | |
|
41 | # (case where '1 < len(ss)'), This could be the currently | |
|
42 | # tipmost, but the correct result is less clear when | |
|
43 | # results of the split have been moved such that they | |
|
44 | # reside on multiple branches. | |
|
45 | for ss in succsets: | |
|
46 | for n in ss: | |
|
47 | dr = torev(n) | |
|
48 | if dr != -1: | |
|
49 | dest.add(dr) | |
|
50 | return dest | |
|
51 | ||
|
19 | 52 | def _destupdateobs(repo, clean): |
|
20 | 53 | """decide of an update destination from obsolescence markers""" |
|
21 | 54 | node = None |
@@ -482,7 +482,34 b' Test that rewriting leaving instability ' | |||
|
482 | 482 | |/ |
|
483 | 483 | o 0:cd010b8cd998 A |
|
484 | 484 | |
|
485 | $ cd .. | |
|
486 | $ cp -R hidden stabilize | |
|
487 | $ cd stabilize | |
|
488 | $ hg rebase --auto-orphans '0::' -d 10 | |
|
489 | abort: --auto-orphans is incompatible with --dest | |
|
490 | [255] | |
|
491 | $ hg rebase --auto-orphans '0::' | |
|
492 | rebasing 9:cf44d2f5a9f4 "D" | |
|
493 | $ hg log -G | |
|
494 | o 12:7e3935feaa68 D | |
|
495 | | | |
|
496 | o 11:0d8f238b634c C | |
|
497 | | | |
|
498 | o 10:7c6027df6a99 B | |
|
499 | | | |
|
500 | @ 7:02de42196ebe H | |
|
501 | | | |
|
502 | | o 6:eea13746799a G | |
|
503 | |/| | |
|
504 | o | 5:24b6387c8c8c F | |
|
505 | | | | |
|
506 | | o 4:9520eea781bc E | |
|
507 | |/ | |
|
508 | o 0:cd010b8cd998 A | |
|
509 | ||
|
485 | 510 | |
|
511 | $ cd ../hidden | |
|
512 | $ rm -r ../stabilize | |
|
486 | 513 | |
|
487 | 514 | Test multiple root handling |
|
488 | 515 | ------------------------------------ |
General Comments 0
You need to be logged in to leave comments.
Login now