Show More
@@ -165,7 +165,27 b' def rebase(ui, repo, **opts):' | |||
|
165 | 165 | raise util.Abort(_('cannot specify a base with detach')) |
|
166 | 166 | |
|
167 | 167 | cmdutil.bailifchanged(repo) |
|
168 | result = buildstate(repo, destf, srcf, basef, detachf) | |
|
168 | ||
|
169 | if not destf: | |
|
170 | # Destination defaults to the latest revision in the current branch | |
|
171 | branch = repo[None].branch() | |
|
172 | dest = repo[branch] | |
|
173 | else: | |
|
174 | dest = repo[destf] | |
|
175 | ||
|
176 | if srcf: | |
|
177 | revsetargs = ('(%s)::', srcf) | |
|
178 | else: | |
|
179 | base = basef or '.' | |
|
180 | revsetargs = ('(children(ancestor(%s, %d)) and ::(%s))::', | |
|
181 | base, dest, base) | |
|
182 | ||
|
183 | rebaseset = [c.rev() for c in repo.set(*revsetargs)] | |
|
184 | if rebaseset: | |
|
185 | result = buildstate(repo, dest, rebaseset, detachf) | |
|
186 | else: | |
|
187 | repo.ui.debug(_('base is ancestor of destination')) | |
|
188 | result = None | |
|
169 | 189 | if not result: |
|
170 | 190 | # Empty state built, nothing to rebase |
|
171 | 191 | ui.status(_('nothing to rebase\n')) |
@@ -507,71 +527,47 b' def abort(repo, originalwd, target, stat' | |||
|
507 | 527 | repo.ui.warn(_('rebase aborted\n')) |
|
508 | 528 | return 0 |
|
509 | 529 | |
|
510 |
def buildstate(repo, dest, |
|
|
511 |
'Define which revisions are going to be rebased and where |
|
|
512 | targetancestors = set() | |
|
513 | detachset = set() | |
|
530 | def buildstate(repo, dest, rebaseset, detach): | |
|
531 | '''Define which revisions are going to be rebased and where | |
|
514 | 532 |
|
|
515 | if not dest: | |
|
516 | # Destination defaults to the latest revision in the current branch | |
|
517 | branch = repo[None].branch() | |
|
518 | dest = repo[branch].rev() | |
|
519 | else: | |
|
520 | dest = repo[dest].rev() | |
|
533 | repo: repo | |
|
534 | dest: context | |
|
535 | rebaseset: set of rev | |
|
536 | detach: boolean''' | |
|
521 | 537 | |
|
522 | 538 | # This check isn't strictly necessary, since mq detects commits over an |
|
523 | 539 | # applied patch. But it prevents messing up the working directory when |
|
524 | 540 | # a partially completed rebase is blocked by mq. |
|
525 |
if 'qtip' in repo.tags() and ( |
|
|
541 | if 'qtip' in repo.tags() and (dest.node() in | |
|
526 | 542 | [s.node for s in repo.mq.applied]): |
|
527 | 543 | raise util.Abort(_('cannot rebase onto an applied mq patch')) |
|
528 | 544 | |
|
529 | if src: | |
|
530 | commonbase = repo[src].ancestor(repo[dest]) | |
|
531 | if commonbase == repo[src]: | |
|
532 |
|
|
|
533 | if commonbase == repo[dest]: | |
|
534 | samebranch = repo[src].branch() == repo[dest].branch() | |
|
535 | if samebranch and repo[src] in repo[dest].children(): | |
|
536 | raise util.Abort(_('source is a child of destination')) | |
|
537 | # rebase on ancestor, force detach | |
|
538 | detach = True | |
|
539 | source = repo[src].rev() | |
|
540 | if detach: | |
|
541 | # We need to keep track of source's ancestors up to the common base | |
|
542 | srcancestors = set(repo.changelog.ancestors(source)) | |
|
543 | baseancestors = set(repo.changelog.ancestors(commonbase.rev())) | |
|
544 | detachset = srcancestors - baseancestors | |
|
545 | detachset.discard(commonbase.rev()) | |
|
546 | else: | |
|
547 | if base: | |
|
548 | cwd = repo[base].rev() | |
|
549 | else: | |
|
550 | cwd = repo['.'].rev() | |
|
545 | detachset = set() | |
|
546 | roots = list(repo.set('roots(%ld)', rebaseset)) | |
|
547 | if not roots: | |
|
548 | raise util.Abort( _('no matching revisions')) | |
|
549 | if len(roots) > 1: | |
|
550 | raise util.Abort( _("can't rebase multiple roots")) | |
|
551 | root = roots[0] | |
|
551 | 552 | |
|
552 | if cwd == dest: | |
|
553 | repo.ui.debug('source and destination are the same\n') | |
|
554 | return None | |
|
555 | ||
|
556 | targetancestors = set(repo.changelog.ancestors(dest)) | |
|
557 | if cwd in targetancestors: | |
|
558 |
|
|
|
559 |
|
|
|
553 | commonbase = root.ancestor(dest) | |
|
554 | if commonbase == root: | |
|
555 | raise util.Abort(_('source is ancestor of destination')) | |
|
556 | if commonbase == dest: | |
|
557 | samebranch = root.branch() == dest.branch() | |
|
558 | if samebranch and root in dest.children(): | |
|
559 | repo.ui.debug(_('source is a child of destination')) | |
|
560 | return None | |
|
561 | # rebase on ancestor, force detach | |
|
562 | detach = True | |
|
563 | if detach: | |
|
564 | detachset = [c.rev() for c in repo.set('::%d - ::%d - %d', | |
|
565 | root, commonbase, root)] | |
|
560 | 566 | |
|
561 | cwdancestors = set(repo.changelog.ancestors(cwd)) | |
|
562 | if dest in cwdancestors: | |
|
563 | repo.ui.debug('source is descendant of destination\n') | |
|
564 | return None | |
|
565 | ||
|
566 | cwdancestors.add(cwd) | |
|
567 | rebasingbranch = cwdancestors - targetancestors | |
|
568 | source = min(rebasingbranch) | |
|
569 | ||
|
570 | repo.ui.debug('rebase onto %d starting from %d\n' % (dest, source)) | |
|
571 | state = dict.fromkeys(repo.changelog.descendants(source), nullrev) | |
|
567 | repo.ui.debug('rebase onto %d starting from %d\n' % (dest, root)) | |
|
568 | state = dict.fromkeys(rebaseset, nullrev) | |
|
572 | 569 | state.update(dict.fromkeys(detachset, nullmerge)) |
|
573 | state[source] = nullrev | |
|
574 | return repo['.'].rev(), repo[dest].rev(), state | |
|
570 | return repo['.'].rev(), dest.rev(), state | |
|
575 | 571 | |
|
576 | 572 | def pullrebase(orig, ui, repo, *args, **opts): |
|
577 | 573 | 'Call rebase after pull if the latter has been invoked with --rebase' |
@@ -74,12 +74,12 b' Rebasing B onto H:' | |||
|
74 | 74 | $ cd .. |
|
75 | 75 | |
|
76 | 76 | |
|
77 |
Rebasing |
|
|
77 | Rebasing E onto H: | |
|
78 | 78 | |
|
79 | 79 | $ hg clone -q -u . a a2 |
|
80 | 80 | $ cd a2 |
|
81 | 81 | |
|
82 |
$ hg rebase -- |
|
|
82 | $ hg rebase --source 4 --collapse | |
|
83 | 83 | saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob) |
|
84 | 84 | |
|
85 | 85 | $ hg tglog |
@@ -115,7 +115,7 b' Rebasing G onto H with custom message:' | |||
|
115 | 115 | abort: message can only be specified with collapse |
|
116 | 116 | [255] |
|
117 | 117 | |
|
118 |
$ hg rebase -- |
|
|
118 | $ hg rebase --source 4 --collapse -m 'custom message' | |
|
119 | 119 | saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob) |
|
120 | 120 | |
|
121 | 121 | $ hg tglog |
@@ -51,8 +51,8 b' These fail:' | |||
|
51 | 51 | $ cd a1 |
|
52 | 52 | |
|
53 | 53 | $ hg rebase -s 8 -d 7 |
|
54 | abort: source is a child of destination | |
|
55 |
[ |
|
|
54 | nothing to rebase | |
|
55 | [1] | |
|
56 | 56 | |
|
57 | 57 | $ hg rebase --continue --abort |
|
58 | 58 | abort: cannot use both abort and continue |
@@ -76,7 +76,7 b' These fail:' | |||
|
76 | 76 | |
|
77 | 77 | $ hg up -q 7 |
|
78 | 78 | |
|
79 | $ hg rebase | |
|
79 | $ hg rebase --traceback | |
|
80 | 80 | nothing to rebase |
|
81 | 81 | [1] |
|
82 | 82 |
General Comments 0
You need to be logged in to leave comments.
Login now