diff mercurial/dagop.py @ 40000:8af835af0a85

dagop: extract DAG local heads functionality from revlog As part of implementing an alternate storage backend, I found myself having to reimplement this function. The DAG traversal logic is generic and can be factored out into a standalone function. We could probably combine this with headrevs(). But I'll leave that for another time. Differential Revision: https://phab.mercurial-scm.org/D4795
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 28 Sep 2018 10:20:37 -0700
parents 0b24fcd88066
children 61f9ef23a12f
line wrap: on
line diff
--- a/mercurial/dagop.py	Fri Sep 28 10:03:32 2018 -0700
+++ b/mercurial/dagop.py	Fri Sep 28 10:20:37 2018 -0700
@@ -773,6 +773,42 @@
 
     return headrevs
 
+def headrevssubset(revsfn, parentrevsfn, startrev=None, stoprevs=None):
+    """Returns the set of all revs that have no children with control.
+
+    ``revsfn`` is a callable that with no arguments returns an iterator over
+    all revision numbers in topological order. With a ``start`` argument, it
+    returns revision numbers starting at that number.
+
+    ``parentrevsfn`` is a callable receiving a revision number and returns an
+    iterable of parent revision numbers, where values can include nullrev.
+
+    ``startrev`` is a revision number at which to start the search.
+
+    ``stoprevs`` is an iterable of revision numbers that, when encountered,
+    will stop DAG traversal beyond them. Parents of revisions in this
+    collection will be heads.
+    """
+    if startrev is None:
+        startrev = nullrev
+
+    stoprevs = set(stoprevs or [])
+
+    reachable = {startrev}
+    heads = {startrev}
+
+    for rev in revsfn(start=startrev + 1):
+        for prev in parentrevsfn(rev):
+            if prev in reachable:
+                if rev not in stoprevs:
+                    reachable.add(rev)
+                heads.add(rev)
+
+            if prev in heads and prev not in stoprevs:
+                heads.remove(prev)
+
+    return heads
+
 def linearize(revs, parentsfn):
     """Linearize and topologically sort a list of revisions.