obsolete: detect divergent changesets
Divergent changeset are final successors (non obsolete) of a changeset who
compete with another set of final successors for this same changeset.
For example if you have two obsolescence markers A -> B and A -> C, B and C are
both "divergent" because they compete to be the one true successors of A.
Public revision can't be divergent.
This function is used and tested in the next changeset.
--- a/mercurial/obsolete.py Sat Nov 10 01:56:59 2012 +0100
+++ b/mercurial/obsolete.py Wed Dec 12 03:19:30 2012 +0100
@@ -684,6 +684,28 @@
query = '%ld - obsolete() - public()'
return set(repo.revs(query, _knownrevs(repo, successors)))
+@cachefor('divergent')
+def _computedivergentset(repo):
+ """the set of rev that compete to be the final successors of some revision.
+ """
+ divergent = set()
+ obsstore = repo.obsstore
+ newermap = {}
+ for ctx in repo.set('(not public()) - obsolete()'):
+ mark = obsstore.precursors.get(ctx.node(), ())
+ toprocess = set(mark)
+ while toprocess:
+ prec = toprocess.pop()[0]
+ if prec not in newermap:
+ successorssets(repo, prec, newermap)
+ newer = [n for n in newermap[prec] if n]
+ if len(newer) > 1:
+ divergent.add(ctx.rev())
+ break
+ toprocess.update(obsstore.precursors.get(prec, ()))
+ return divergent
+
+
def createmarkers(repo, relations, flag=0, metadata=None):
"""Add obsolete markers between changesets in a repo