[PATCH 2 of 7] obsolete: add the detection of bumped changeset

pierre-yves.david at logilab.fr pierre-yves.david at logilab.fr
Wed Oct 3 05:13:02 CDT 2012


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at logilab.fr>
# Date 1349257695 -7200
# Node ID 7866831b6cb69e817c1fe0fec81bb933fd46ae45
# Parent  af731e6a342308e9111c11287bd73a1a0fcbbd47
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
@@ -69,10 +69,13 @@ from i18n import _
 _fmfixed   = '>BIB20s'
 _fmnode = '20s'
 _fmfsize = struct.calcsize(_fmfixed)
 _fnodesize = struct.calcsize(_fmnode)
 
+# obsolescence marker flag
+bumpedfix = 1
+
 def _readmarkers(data):
     """Read and enumerate markers from raw data"""
     off = 0
     diskversion = _unpack('>B', data[off:off + 1])[0]
     off += 1
@@ -397,10 +400,52 @@ 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 changeset
+    candidates = _anysuccessors(repo, repo.revs('public()'))
+    # revision public or already obsolete don't account as bumped
+    query = '%ld - obsolete() - public()'
+    return set(repo.revs(query, candidates))
+
+def _anysuccessors(repo, revs):
+    """return revid of all successors of a set of revs
+    """
+    toproceed = [repo[r].node() for r in revs]
+    # prevent extra processing and cycle
+    seen = set(toproceed)
+    # records result
+    successors = set()
+    # mapping node -> marker that use node as precursors
+    markersfor = repo.obsstore.precursors
+    while toproceed:
+        nc = toproceed.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)
+                    toproceed.append(suc)
+    # only known nodes are returned
+    nm = repo.changelog.nodemap
+    cs = set()
+    for s in successors:
+        sr = nm.get(s)
+        if sr is not None:
+            cs.add(sr)
+    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