Mercurial > public > mercurial-scm > hg-stable
diff hgext/rebase.py @ 46834:535de0e34a79
rebase: filter out descendants of divergence-causing commits earlier
`hg rebase` treats obsolete commits differently depending what has
happened to the commit:
1) Obsolete commit without non-obsolete successors: Skipped, and a
note is printed ("it has no successor").
2) Obsolete commit with a successor in the destination (ancestor of
it): Skipped, and a note is printed ("already in destination").
3) Obsolete commit with a successor in the rebase set: The commit and
its descendants are skipped, and a note is printed ("not rebasing
<commit> and its descendants as this would cause divergence"), unless
`allowdivergence` config set.
4) Obsolete commit with a successor elsewhere: Error ("this rebase
will cause divergences"), unless `allowdivergence` config set.
Before this patch, we did all those checks up front, except for (3),
which was checked later. The later check consisted of two parts: 1)
filtering out of descendants, and 2) conditionally printing message if
the `allowdivergence` config was not set. This patch makes it so we do
the filtering early.
A consequence of filtering out divergence-causing commits earlier is
that we rebase commits in slightly different order, which has some
impact on tests.
Differential Revision: https://phab.mercurial-scm.org/D10249
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Fri, 19 Mar 2021 22:52:59 -0700 |
parents | 47c251a14525 |
children | c2438f2f635c |
line wrap: on
line diff
--- a/hgext/rebase.py Fri Mar 19 10:34:16 2021 -0700 +++ b/hgext/rebase.py Fri Mar 19 22:52:59 2021 -0700 @@ -361,6 +361,19 @@ skippedset = set(self.obsolete_with_successor_in_destination) skippedset.update(self.obsolete_with_successor_in_rebase_set) _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset) + allowdivergence = self.ui.configbool( + b'experimental', b'evolution.allowdivergence' + ) + if allowdivergence: + self.obsolete_with_successor_in_rebase_set = set() + else: + for rev in self.repo.revs( + b'descendants(%ld) and not %ld', + self.obsolete_with_successor_in_rebase_set, + self.obsolete_with_successor_in_rebase_set, + ): + self.state.pop(rev, None) + self.destmap.pop(rev, None) def _prepareabortorcontinue( self, isabort, backup=True, suppwarns=False, dryrun=False, confirm=False @@ -493,19 +506,10 @@ def progress(ctx): p.increment(item=(b"%d:%s" % (ctx.rev(), ctx))) - allowdivergence = self.ui.configbool( - b'experimental', b'evolution.allowdivergence' - ) for subset in sortsource(self.destmap): sortedrevs = self.repo.revs(b'sort(%ld, -topo)', subset) - if not allowdivergence: - sortedrevs -= self.repo.revs( - b'descendants(%ld) and not %ld', - self.obsolete_with_successor_in_rebase_set, - self.obsolete_with_successor_in_rebase_set, - ) for rev in sortedrevs: - self._rebasenode(tr, rev, allowdivergence, progress) + self._rebasenode(tr, rev, progress) p.complete() ui.note(_(b'rebase merging completed\n')) @@ -567,16 +571,13 @@ return newnode - def _rebasenode(self, tr, rev, allowdivergence, progressfn): + def _rebasenode(self, tr, rev, progressfn): repo, ui, opts = self.repo, self.ui, self.opts ctx = repo[rev] desc = _ctxdesc(ctx) if self.state[rev] == rev: ui.status(_(b'already rebased %s\n') % desc) - elif ( - not allowdivergence - and rev in self.obsolete_with_successor_in_rebase_set - ): + elif rev in self.obsolete_with_successor_in_rebase_set: msg = ( _( b'note: not rebasing %s and its descendants as '