rebase: do not consider extincts for divergence detection (issue5782)
Extinct obsolete changesets cannot cause divergence upon rebase. We
compute these obsoletes without a non-obsolete successor (extincts) in
_computeobsoletenotrebased() and then filter them out from the set of
obsolete revisions to rebase before getting into _checkobsrebase() to
check for divergence candidates.
--- a/hgext/rebase.py Fri Feb 09 21:45:16 2018 +0100
+++ b/hgext/rebase.py Fri Feb 09 22:49:20 2018 +0100
@@ -312,10 +312,13 @@
if not self.ui.configbool('experimental', 'rebaseskipobsolete'):
return
obsoleteset = set(obsoleterevs)
- self.obsoletenotrebased, self.obsoletewithoutsuccessorindestination = \
- _computeobsoletenotrebased(self.repo, obsoleteset, destmap)
+ (self.obsoletenotrebased,
+ self.obsoletewithoutsuccessorindestination,
+ obsoleteextinctsuccessors) = _computeobsoletenotrebased(
+ self.repo, obsoleteset, destmap)
skippedset = set(self.obsoletenotrebased)
skippedset.update(self.obsoletewithoutsuccessorindestination)
+ skippedset.update(obsoleteextinctsuccessors)
_checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
def _prepareabortorcontinue(self, isabort):
@@ -1221,7 +1224,7 @@
`rebaseobsrevs`: set of obsolete revision in source
`rebaseobsskipped`: set of revisions from source skipped because they have
- successors in destination
+ successors in destination or no non-obsolete successor.
"""
# Obsolete node with successors not in dest leads to divergence
divergenceok = ui.configbool('experimental',
@@ -1786,13 +1789,18 @@
`obsoletewithoutsuccessorindestination` is a set with obsolete revisions
without a successor in destination.
+
+ `obsoleteextinctsuccessors` is a set of obsolete revisions with only
+ obsolete successors.
"""
obsoletenotrebased = {}
obsoletewithoutsuccessorindestination = set([])
+ obsoleteextinctsuccessors = set([])
assert repo.filtername is None
cl = repo.changelog
nodemap = cl.nodemap
+ extinctnodes = set(cl.node(r) for r in repo.revs('extinct()'))
for srcrev in rebaseobsrevs:
srcnode = cl.node(srcrev)
destnode = cl.node(destmap[srcrev])
@@ -1800,6 +1808,9 @@
successors = list(obsutil.allsuccessors(repo.obsstore, [srcnode]))
# obsutil.allsuccessors includes node itself
successors.remove(srcnode)
+ if set(successors).issubset(extinctnodes):
+ # all successors are extinct
+ obsoleteextinctsuccessors.add(srcrev)
if not successors:
# no successor
obsoletenotrebased[srcrev] = None
@@ -1817,7 +1828,11 @@
if any(nodemap[s] in destmap for s in successors):
obsoletewithoutsuccessorindestination.add(srcrev)
- return obsoletenotrebased, obsoletewithoutsuccessorindestination
+ return (
+ obsoletenotrebased,
+ obsoletewithoutsuccessorindestination,
+ obsoleteextinctsuccessors,
+ )
def summaryhook(ui, repo):
if not repo.vfs.exists('rebasestate'):
--- a/tests/test-rebase-obsolete.t Fri Feb 09 21:45:16 2018 +0100
+++ b/tests/test-rebase-obsolete.t Fri Feb 09 22:49:20 2018 +0100
@@ -1244,10 +1244,6 @@
o 0:b173517d0057 a
$ hg rebase -d 0 -r 2
- abort: this rebase will cause divergences from: a82ac2b38757
- (to force the rebase please set experimental.evolution.allowdivergence=True)
- [255]
- $ hg rebase -d 0 -r 2 --config experimental.evolution.allowdivergence=True
rebasing 2:a82ac2b38757 "c" (c)
$ hg log -G -r 'a': --hidden
o 5:69ad416a4a26 c