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