[PATCH 2 of 4] revset: implemented set caching for revset evaluation

Lucas Moscovicz lmoscovicz at fb.com
Mon Feb 3 13:44:33 CST 2014


# HG changeset patch
# User Lucas Moscovicz <lmoscovicz at fb.com>
# Date 1390416362 28800
#      Wed Jan 22 10:46:02 2014 -0800
# Node ID 6787b6222593319d57225527030e68ab54bc3350
# Parent  f41001b383d8006c4e1949ffe2c377849767de47
revset: implemented set caching for revset evaluation

Added set caching to the baseset class. It lazily builds the set whenever it's
needed and keeps a reference which is returned when the set is requested
instead of being built again.

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -234,13 +234,13 @@
         r = range(m, n + 1)
     else:
         r = range(m, n - 1, -1)
-    s = set(subset)
+    s = subset.set()
     return baseset([x for x in r if x in s])
 
 def dagrange(repo, subset, x, y):
     r = baseset(repo)
     xs = _revsbetween(repo, getset(repo, r, x), getset(repo, r, y))
-    s = set(subset)
+    s = subset.set()
     return baseset([r for r in xs if r in s])
 
 def andset(repo, subset, x, y):
@@ -248,12 +248,12 @@
 
 def orset(repo, subset, x, y):
     xl = getset(repo, subset, x)
-    s = set(xl)
-    yl = getset(repo, [r for r in subset if r not in s], y)
+    s = xl.set()
+    yl = getset(repo, baseset([r for r in subset if r not in s]), y)
     return baseset(xl + yl)
 
 def notset(repo, subset, x):
-    s = set(getset(repo, subset, x))
+    s = getset(repo, subset, x).set()
     return baseset([r for r in subset if r not in s])
 
 def listset(repo, subset, a, b):
@@ -307,7 +307,8 @@
     if not args:
         return baseset([])
     s = set(_revancestors(repo, args, followfirst)) | set(args)
-    return baseset([r for r in subset if r in s])
+    ss = subset.set()
+    return baseset([r for r in ss if r in s])
 
 def ancestors(repo, subset, x):
     """``ancestors(set)``
@@ -335,7 +336,8 @@
         for i in range(n):
             r = cl.parentrevs(r)[0]
         ps.add(r)
-    return baseset([r for r in subset if r in ps])
+    s = subset.set()
+    return baseset([r for r in s if r in ps])
 
 def author(repo, subset, x):
     """``author(string)``
@@ -362,7 +364,8 @@
     # i18n: "bisect" is a keyword
     status = getstring(x, _("bisect requires a string")).lower()
     state = set(hbisect.get(repo, status))
-    return baseset([r for r in subset if r in state])
+    s = subset.set()
+    return baseset([r for r in s if r in state])
 
 # Backward-compatibility
 # - no help entry so that we do not advertise it any more
@@ -401,11 +404,13 @@
             bmrevs = set()
             for bmrev in matchrevs:
                 bmrevs.add(repo[bmrev].rev())
-            return baseset([r for r in subset if r in bmrevs])
+            s = subset.set()
+            return baseset([r for r in s if r in bmrevs])
 
     bms = set([repo[r].rev()
                for r in repo._bookmarks.values()])
-    return baseset([r for r in subset if r in bms])
+    s = subset.set()
+    return baseset([r for r in s if r in bms])
 
 def branch(repo, subset, x):
     """``branch(string or set)``
@@ -435,7 +440,7 @@
     b = set()
     for r in s:
         b.add(repo[r].branch())
-    s = set(s)
+    s = s.set()
     return baseset([r for r in subset if r in s or repo[r].branch() in b])
 
 def bumped(repo, subset, x):
@@ -510,7 +515,7 @@
     """``children(set)``
     Child changesets of changesets in set.
     """
-    s = set(getset(repo, baseset(repo), x))
+    s = getset(repo, baseset(repo), x).set()
     cs = _children(repo, subset, s)
     return baseset([r for r in subset if r in cs])
 
@@ -595,7 +600,8 @@
     if not args:
         return baseset([])
     s = set(_revdescendants(repo, args, followfirst)) | set(args)
-    return baseset([r for r in subset if r in s])
+    ss = subset.set()
+    return baseset([r for r in ss if r in s])
 
 def descendants(repo, subset, x):
     """``descendants(set)``
@@ -615,9 +621,9 @@
     is the same as passing all().
     """
     if x is not None:
-        args = set(getset(repo, baseset(repo), x))
+        args = getset(repo, baseset(repo), x).set()
     else:
-        args = set(getall(repo, baseset(repo), x))
+        args = getall(repo, baseset(repo), x).set()
 
     dests = set()
 
@@ -732,7 +738,8 @@
                 for fr in fl:
                     s.add(fl.linkrev(fr))
 
-    return baseset([r for r in subset if r in s])
+    ss = subset.set()
+    return baseset([r for r in ss if r in s])
 
 def first(repo, subset, x):
     """``first(set, [n])``
@@ -755,7 +762,8 @@
     else:
         s = set(_revancestors(repo, [c.rev()], followfirst)) | set([c.rev()])
 
-    return baseset([r for r in subset if r in s])
+    ss = subset.set()
+    return baseset([r for r in ss if r in s])
 
 def follow(repo, subset, x):
     """``follow([file])``
@@ -882,14 +890,15 @@
     hs = set()
     for b, ls in repo.branchmap().iteritems():
         hs.update(repo[h].rev() for h in ls)
-    return baseset([r for r in subset if r in hs])
+    s = subset.set()
+    return baseset([r for r in s if r in hs])
 
 def heads(repo, subset, x):
     """``heads(set)``
     Members of set with no children in set.
     """
-    s = getset(repo, subset, x)
-    ps = set(parents(repo, subset, x))
+    s = getset(repo, subset, x).set()
+    ps = parents(repo, subset, x).set()
     return baseset([r for r in s if r not in ps])
 
 def hidden(repo, subset, x):
@@ -930,7 +939,7 @@
     except (TypeError, ValueError):
         # i18n: "limit" is a keyword
         raise error.ParseError(_("limit expects a number"))
-    ss = set(subset)
+    ss = subset.set()
     os = getset(repo, baseset(repo), l[0])[:lim]
     return baseset([r for r in os if r in ss])
 
@@ -948,7 +957,7 @@
     except (TypeError, ValueError):
         # i18n: "last" is a keyword
         raise error.ParseError(_("last expects a number"))
-    ss = set(subset)
+    ss = subset.set()
     os = getset(repo, baseset(repo), l[0])[-lim:]
     return baseset([r for r in os if r in ss])
 
@@ -1043,9 +1052,9 @@
     for the first operation is selected.
     """
     if x is not None:
-        args = set(getset(repo, baseset(repo), x))
+        args = getset(repo, baseset(repo), x).set()
     else:
-        args = set(getall(repo, baseset(repo), x))
+        args = getall(repo, baseset(repo), x).set()
 
     def _firstsrc(rev):
         src = _getrevsource(repo, rev)
@@ -1060,7 +1069,8 @@
             src = prev
 
     o = set([_firstsrc(r) for r in args])
-    return baseset([r for r in subset if r in o])
+    s = subset.set()
+    return baseset([r for r in s if r in o])
 
 def outgoing(repo, subset, x):
     """``outgoing([path])``
@@ -1083,7 +1093,8 @@
     repo.ui.popbuffer()
     cl = repo.changelog
     o = set([cl.rev(r) for r in outgoing.missing])
-    return baseset([r for r in subset if r in o])
+    s = subset.set()
+    return baseset([r for r in s if r in o])
 
 def p1(repo, subset, x):
     """``p1([set])``
@@ -1097,7 +1108,8 @@
     cl = repo.changelog
     for r in getset(repo, baseset(repo), x):
         ps.add(cl.parentrevs(r)[0])
-    return baseset([r for r in subset if r in ps])
+    s = subset.set()
+    return baseset([r for r in s if r in ps])
 
 def p2(repo, subset, x):
     """``p2([set])``
@@ -1115,7 +1127,8 @@
     cl = repo.changelog
     for r in getset(repo, baseset(repo), x):
         ps.add(cl.parentrevs(r)[1])
-    return baseset([r for r in subset if r in ps])
+    s = subset.set()
+    return baseset([r for r in s if r in ps])
 
 def parents(repo, subset, x):
     """``parents([set])``
@@ -1129,7 +1142,8 @@
     cl = repo.changelog
     for r in getset(repo, baseset(repo), x):
         ps.update(cl.parentrevs(r))
-    return baseset([r for r in subset if r in ps])
+    s = subset.set()
+    return baseset([r for r in s if r in ps])
 
 def parentspec(repo, subset, x, n):
     """``set^0``
@@ -1154,7 +1168,8 @@
             parents = cl.parentrevs(r)
             if len(parents) > 1:
                 ps.add(parents[1])
-    return baseset([r for r in subset if r in ps])
+    s = subset.set()
+    return baseset([r for r in s if r in ps])
 
 def present(repo, subset, x):
     """``present(set)``
@@ -1352,8 +1367,6 @@
     Reverse order of set.
     """
     l = getset(repo, subset, x)
-    if not isinstance(l, list):
-        l = baseset(l)
     l.reverse()
     return l
 
@@ -1361,7 +1374,7 @@
     """``roots(set)``
     Changesets in set with no parent changeset in set.
     """
-    s = set(getset(repo, baseset(repo.changelog), x))
+    s = getset(repo, baseset(repo.changelog), x).set()
     subset = baseset([r for r in subset if r in s])
     cs = _children(repo, subset, s)
     return baseset([r for r in subset if r not in cs])
@@ -1527,10 +1540,9 @@
     s = getstring(x, "internal error")
     if not s:
         return baseset([])
-    if not isinstance(subset, set):
-        subset = set(subset)
     ls = [repo[r].rev() for r in s.split('\0')]
-    return baseset([r for r in ls if r in subset])
+    s = subset.set()
+    return baseset([r for r in ls if r in s])
 
 symbols = {
     "adds": adds,
@@ -2025,7 +2037,14 @@
         return funcs
 
 class baseset(list):
-    pass
+    def __init__(self, data):
+        super(baseset, self).__init__(data)
+        self._set = None
+
+    def set(self):
+        if not self._set:
+            self._set = set(self)
+        return self._set
 
 # tell hggettext to extract docstrings from these functions:
 i18nfunctions = symbols.values()


More information about the Mercurial-devel mailing list