[PATCH 3 of 6 V2] obsolete: detect divergent changesets

pierre-yves.david at logilab.fr pierre-yves.david at logilab.fr
Thu Dec 13 08:51:50 CST 2012


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at logilab.fr>
# Date 1355278770 -3600
# Node ID cfc7306dbdc75659ca4c85a14720f8de87cd797e
# Parent  a63af12dc0cdf8e7c828f2278427b3beea1220c2
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.

diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -684,10 +684,32 @@ def _computebumpedset(repo):
                                ignoreflags=bumpedfix)
     # revision public or already obsolete don't count as bumped
     query = '%ld - obsolete() - public()'
     return set(repo.revs(query, _knownrevs(repo, successors)))
 
+ at 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
 
     <relations> must be an iterable of (<old>, (<new>, ...)) tuple.
     `old` and `news` are changectx.


More information about the Mercurial-devel mailing list