Patchwork [1,of,6] dagop: add smartset interface to filectxancestors()

login
register
mail settings
Submitter Yuya Nishihara
Date Dec. 7, 2017, 3:09 p.m.
Message ID <33687d121e08c716d8e4.1512659359@mimosa>
Download mbox | patch
Permalink /patch/25996/
State Accepted
Headers show

Comments

Yuya Nishihara - Dec. 7, 2017, 3:09 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1508666262 -32400
#      Sun Oct 22 18:57:42 2017 +0900
# Node ID 33687d121e08c716d8e41e0135b14c75c78c3fda
# Parent  8e72f9152c4dbd3820a750539dc5eef53d040bfa
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'.

Patch

diff --git a/mercurial/dagop.py b/mercurial/dagop.py
--- a/mercurial/dagop.py
+++ b/mercurial/dagop.py
@@ -77,7 +77,10 @@  def _walkrevtree(pfunc, revs, startdepth
 
 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 @@  def filectxancestors(fctxs, followfirst=
     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:
diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -928,8 +928,7 @@  def _follow(repo, subset, x, name, follo
         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)