[PATCH 4 of 9 V2] obsolete: add the detection of bumped changeset

pierre-yves.david at logilab.fr pierre-yves.david at logilab.fr
Mon Oct 15 07:46:18 CDT 2012


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at logilab.fr>
# Date 1350295946 -7200
# Node ID b992c8e9e2a74630a9f932e98f46a34a6252725b
# Parent  79cf3c2a7ec3728e57f3c771187dd8cb9a92bfa1
obsolete: add the detection of bumped changeset.

Bumped changeset are non-public changeset that tries to succeed to a public()
changeset.

diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -422,10 +422,55 @@ def _computesuspendedset(repo):
 @cachefor('extinct')
 def _computeextinctset(repo):
     """the set of obsolete parents without non obsolete descendants"""
     return set(repo.revs('obsolete() - obsolete()::unstable()'))
 
+ at cachefor('bumped')
+def _computebumpedset(repo):
+    """the set of rev trying to obsolete public revision"""
+    # get all possible bumped changesets
+    candidates = _allflatsuccessors(repo, repo.revs('public()'))
+    # revision public or already obsolete don't count as bumped
+    query = '%ld - obsolete() - public()'
+    return set(repo.revs(query, candidates))
+
+def _allflatsuccessors(repo, revs):
+    """return revid of all successors of a set of revs
+
+    Only know node are returned (unknown node does not have revid).  This
+    function loose the split vs divergence information, revision are not
+    grouped by successors set.
+    """
+    cl = repo.changelog
+    pending = [cl.node(r) for r in revs]
+    # prevent extra processing and cycle
+    seen = set(pending)
+    # records result
+    successors = set()
+    # mapping {node -> marker that use node as precursors}
+    markersfor = repo.obsstore.precursors
+    while pending:
+        nc = pending.pop()
+        # for all markers that make this node obsolete
+        for mark in markersfor.get(nc, ()):
+            # for all successors
+            for suc in mark[1]:
+                # record this as a successors
+                successors.add(suc)
+                # add it to the list of node to proceed
+                # we want the successors of this successors too.
+                if suc not in seen:
+                    seen.add(suc)
+                    pending.append(suc)
+    # only known nodes are returned
+    tonode = repo.changelog.nodemap.get
+    cs = set(tonode(s) for s in successors)
+    # drop None added by unknown nodes
+    cs.difference_update(set([None]))
+    return cs
+
+
 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