diff -r 5d6ee2494f63 -r 100fdc84670f hgext/rebase.py --- a/hgext/rebase.py Wed Jan 16 05:21:11 2013 +0100 +++ b/hgext/rebase.py Thu Jan 17 00:35:01 2013 +0100 @@ -574,9 +574,9 @@ merge.update(repo, repo[originalwd].rev(), False, True, False) rebased = filter(lambda x: x > -1 and x != target, state.values()) if rebased: - strippoint = min(rebased) + strippoints = [c.node() for c in repo.set('roots(%ld)', rebased)] # no backup of rebased cset versions needed - repair.strip(repo.ui, repo, repo[strippoint].node()) + repair.strip(repo.ui, repo, strippoints) clearstatus(repo) repo.ui.warn(_('rebase aborted\n')) return 0 @@ -599,65 +599,65 @@ roots = list(repo.set('roots(%ld)', rebaseset)) if not roots: raise util.Abort(_('no matching revisions')) - if len(roots) > 1: - raise util.Abort(_("can't rebase multiple roots")) - root = roots[0] - - commonbase = root.ancestor(dest) - if commonbase == root: - raise util.Abort(_('source is ancestor of destination')) - if commonbase == dest: - samebranch = root.branch() == dest.branch() - if not collapse and samebranch and root in dest.children(): - repo.ui.debug('source is a child of destination\n') - return None + roots.sort() + state = {} + detachset = set() + for root in roots: + commonbase = root.ancestor(dest) + if commonbase == root: + raise util.Abort(_('source is ancestor of destination')) + if commonbase == dest: + samebranch = root.branch() == dest.branch() + if not collapse and samebranch and root in dest.children(): + repo.ui.debug('source is a child of destination\n') + return None - repo.ui.debug('rebase onto %d starting from %d\n' % (dest, root)) - state = dict.fromkeys(rebaseset, nullrev) - # Rebase tries to turn into a parent of while - # preserving the number of parents of rebased changesets: - # - # - A changeset with a single parent will always be rebased as a - # changeset with a single parent. - # - # - A merge will be rebased as merge unless its parents are both - # ancestors of or are themselves in the rebased set and - # pruned while rebased. - # - # If one parent of is an ancestor of , the rebased - # version of this parent will be . This is always true with - # --base option. - # - # Otherwise, we need to *replace* the original parents with - # . This "detaches" the rebased set from its former location - # and rebases it onto . Changes introduced by ancestors of - # not common with (the detachset, marked as - # nullmerge) are "removed" from the rebased changesets. - # - # - If has a single parent, set it to . - # - # - If is a merge, we cannot decide which parent to - # replace, the rebase operation is not clearly defined. - # - # The table below sums up this behavior: - # - # +--------------------+----------------------+-------------------------+ - # | | one parent | merge | - # +--------------------+----------------------+-------------------------+ - # | parent in :: | new parent is | parents in :: are | - # | | | remapped to | - # +--------------------+----------------------+-------------------------+ - # | unrelated source | new parent is | ambiguous, abort | - # +--------------------+----------------------+-------------------------+ - # - # The actual abort is handled by `defineparents` - if len(root.parents()) <= 1: - # ancestors of not ancestors of - detachset = repo.changelog.findmissingrevs([commonbase.rev()], - [root.rev()]) - state.update(dict.fromkeys(detachset, nullmerge)) - # detachset can have root, and we definitely want to rebase that - state[root.rev()] = nullrev + repo.ui.debug('rebase onto %d starting from %s\n' % (dest, roots)) + state.update(dict.fromkeys(rebaseset, nullrev)) + # Rebase tries to turn into a parent of while + # preserving the number of parents of rebased changesets: + # + # - A changeset with a single parent will always be rebased as a + # changeset with a single parent. + # + # - A merge will be rebased as merge unless its parents are both + # ancestors of or are themselves in the rebased set and + # pruned while rebased. + # + # If one parent of is an ancestor of , the rebased + # version of this parent will be . This is always true with + # --base option. + # + # Otherwise, we need to *replace* the original parents with + # . This "detaches" the rebased set from its former location + # and rebases it onto . Changes introduced by ancestors of + # not common with (the detachset, marked as + # nullmerge) are "removed" from the rebased changesets. + # + # - If has a single parent, set it to . + # + # - If is a merge, we cannot decide which parent to + # replace, the rebase operation is not clearly defined. + # + # The table below sums up this behavior: + # + # +------------------+----------------------+-------------------------+ + # | | one parent | merge | + # +------------------+----------------------+-------------------------+ + # | parent in | new parent is | parents in :: are | + # | :: | | remapped to | + # +------------------+----------------------+-------------------------+ + # | unrelated source | new parent is | ambiguous, abort | + # +------------------+----------------------+-------------------------+ + # + # The actual abort is handled by `defineparents` + if len(root.parents()) <= 1: + # ancestors of not ancestors of + detachset.update(repo.changelog.findmissingrevs([commonbase.rev()], + [root.rev()])) + for r in detachset: + if r not in state: + state[r] = nullmerge return repo['.'].rev(), dest.rev(), state def clearrebased(ui, repo, state, collapsedas=None): @@ -677,12 +677,16 @@ else: rebased = [rev for rev in state if state[rev] != nullmerge] if rebased: - if set(repo.changelog.descendants([min(rebased)])) - set(state): - ui.warn(_("warning: new changesets detected " - "on source branch, not stripping\n")) - else: + stripped = [] + for root in repo.set('roots(%ld)', rebased): + if set(repo.changelog.descendants([root.rev()])) - set(state): + ui.warn(_("warning: new changesets detected " + "on source branch, not stripping\n")) + else: + stripped.append(root.node()) + if stripped: # backup the old csets by default - repair.strip(ui, repo, repo[min(rebased)].node(), "all") + repair.strip(ui, repo, stripped, "all") def pullrebase(orig, ui, repo, *args, **opts):