changeset 35296:2cb05e6043be

dagop: add smartset interface to filectxancestors() The original filectx API is kept public since we'll need it to walk ancestor (rev, match) pairs efficiently. The current implementation scans ancestors twice for 'hg log -fp FILE'.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 22 Oct 2017 18:57:42 +0900
parents bea46aed1e1b
children c9144396099b
files mercurial/dagop.py mercurial/revset.py
diffstat 2 files changed, 20 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/dagop.py	Thu Dec 07 13:20:47 2017 -0800
+++ b/mercurial/dagop.py	Sun Oct 22 18:57:42 2017 +0900
@@ -77,7 +77,10 @@
 
 def filectxancestors(fctxs, followfirst=False):
     """Like filectx.ancestors(), but can walk from multiple files/revisions,
-    and includes the given fctxs themselves"""
+    and includes the given fctxs themselves
+
+    Yields (rev, {fctx, ...}) pairs in descending order.
+    """
     visit = {}
     def addvisit(fctx):
         rev = fctx.rev()
@@ -93,13 +96,21 @@
     for c in fctxs:
         addvisit(c)
     while visit:
-        rev = max(visit)
-        c = visit[rev].pop()
-        if not visit[rev]:
-            del visit[rev]
-        yield c
-        for parent in c.parents()[:cut]:
-            addvisit(parent)
+        currev = max(visit)
+        curfctxs = visit.pop(currev)
+        yield currev, curfctxs
+        for c in curfctxs:
+            for parent in c.parents()[:cut]:
+                addvisit(parent)
+
+def filerevancestors(fctxs, followfirst=False):
+    """Like filectx.ancestors(), but can walk from multiple files/revisions,
+    and includes the given fctxs themselves
+
+    Returns a smartset.
+    """
+    gen = (rev for rev, _cs in filectxancestors(fctxs, followfirst))
+    return generatorset(gen, iterasc=False)
 
 def _genrevancestors(repo, revs, followfirst, startdepth, stopdepth, cutfunc):
     if followfirst:
--- a/mercurial/revset.py	Thu Dec 07 13:20:47 2017 -0800
+++ b/mercurial/revset.py	Sun Oct 22 18:57:42 2017 +0900
@@ -928,8 +928,7 @@
         files = c.manifest().walk(matcher)
 
         fctxs = [c[f].introfilectx() for f in files]
-        a = dagop.filectxancestors(fctxs, followfirst)
-        s = set(c.rev() for c in a)
+        s = dagop.filerevancestors(fctxs, followfirst)
     else:
         s = dagop.revancestors(repo, baseset([c.rev()]), followfirst)