changeset 18070:af632936d3d9

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.
author Pierre-Yves David <pierre-yves.david@logilab.fr>
date Wed, 12 Dec 2012 03:19:30 +0100
parents f84e731cbd20
children bea754715961
files mercurial/obsolete.py
diffstat 1 files changed, 22 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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