Mercurial > hg-stable
comparison 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 |
comparison
equal
deleted
inserted
replaced
46833:47c251a14525 | 46834:535de0e34a79 |
---|---|
359 self.obsolete_with_successor_in_rebase_set, | 359 self.obsolete_with_successor_in_rebase_set, |
360 ) = _compute_obsolete_sets(self.repo, obsoleteset, self.destmap) | 360 ) = _compute_obsolete_sets(self.repo, obsoleteset, self.destmap) |
361 skippedset = set(self.obsolete_with_successor_in_destination) | 361 skippedset = set(self.obsolete_with_successor_in_destination) |
362 skippedset.update(self.obsolete_with_successor_in_rebase_set) | 362 skippedset.update(self.obsolete_with_successor_in_rebase_set) |
363 _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset) | 363 _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset) |
364 allowdivergence = self.ui.configbool( | |
365 b'experimental', b'evolution.allowdivergence' | |
366 ) | |
367 if allowdivergence: | |
368 self.obsolete_with_successor_in_rebase_set = set() | |
369 else: | |
370 for rev in self.repo.revs( | |
371 b'descendants(%ld) and not %ld', | |
372 self.obsolete_with_successor_in_rebase_set, | |
373 self.obsolete_with_successor_in_rebase_set, | |
374 ): | |
375 self.state.pop(rev, None) | |
376 self.destmap.pop(rev, None) | |
364 | 377 |
365 def _prepareabortorcontinue( | 378 def _prepareabortorcontinue( |
366 self, isabort, backup=True, suppwarns=False, dryrun=False, confirm=False | 379 self, isabort, backup=True, suppwarns=False, dryrun=False, confirm=False |
367 ): | 380 ): |
368 self.resume = True | 381 self.resume = True |
491 ) | 504 ) |
492 | 505 |
493 def progress(ctx): | 506 def progress(ctx): |
494 p.increment(item=(b"%d:%s" % (ctx.rev(), ctx))) | 507 p.increment(item=(b"%d:%s" % (ctx.rev(), ctx))) |
495 | 508 |
496 allowdivergence = self.ui.configbool( | |
497 b'experimental', b'evolution.allowdivergence' | |
498 ) | |
499 for subset in sortsource(self.destmap): | 509 for subset in sortsource(self.destmap): |
500 sortedrevs = self.repo.revs(b'sort(%ld, -topo)', subset) | 510 sortedrevs = self.repo.revs(b'sort(%ld, -topo)', subset) |
501 if not allowdivergence: | |
502 sortedrevs -= self.repo.revs( | |
503 b'descendants(%ld) and not %ld', | |
504 self.obsolete_with_successor_in_rebase_set, | |
505 self.obsolete_with_successor_in_rebase_set, | |
506 ) | |
507 for rev in sortedrevs: | 511 for rev in sortedrevs: |
508 self._rebasenode(tr, rev, allowdivergence, progress) | 512 self._rebasenode(tr, rev, progress) |
509 p.complete() | 513 p.complete() |
510 ui.note(_(b'rebase merging completed\n')) | 514 ui.note(_(b'rebase merging completed\n')) |
511 | 515 |
512 def _concludenode(self, rev, editor, commitmsg=None): | 516 def _concludenode(self, rev, editor, commitmsg=None): |
513 """Commit the wd changes with parents p1 and p2. | 517 """Commit the wd changes with parents p1 and p2. |
565 date=date, | 569 date=date, |
566 ) | 570 ) |
567 | 571 |
568 return newnode | 572 return newnode |
569 | 573 |
570 def _rebasenode(self, tr, rev, allowdivergence, progressfn): | 574 def _rebasenode(self, tr, rev, progressfn): |
571 repo, ui, opts = self.repo, self.ui, self.opts | 575 repo, ui, opts = self.repo, self.ui, self.opts |
572 ctx = repo[rev] | 576 ctx = repo[rev] |
573 desc = _ctxdesc(ctx) | 577 desc = _ctxdesc(ctx) |
574 if self.state[rev] == rev: | 578 if self.state[rev] == rev: |
575 ui.status(_(b'already rebased %s\n') % desc) | 579 ui.status(_(b'already rebased %s\n') % desc) |
576 elif ( | 580 elif rev in self.obsolete_with_successor_in_rebase_set: |
577 not allowdivergence | |
578 and rev in self.obsolete_with_successor_in_rebase_set | |
579 ): | |
580 msg = ( | 581 msg = ( |
581 _( | 582 _( |
582 b'note: not rebasing %s and its descendants as ' | 583 b'note: not rebasing %s and its descendants as ' |
583 b'this would cause divergence\n' | 584 b'this would cause divergence\n' |
584 ) | 585 ) |