revset: pass around ordering flags to operations
authorYuya Nishihara <yuya@tcha.org>
Sun, 07 Aug 2016 17:46:12 +0900
changeset 29932 09a84e747c88
parent 29931 d2d1be3009ca
child 29933 91a95ad985d8
revset: pass around ordering flags to operations Some operations and functions will need them to fix ordering bugs.
mercurial/revset.py
tests/test-revset.t
--- a/mercurial/revset.py	Sun Aug 07 17:48:52 2016 +0900
+++ b/mercurial/revset.py	Sun Aug 07 17:46:12 2016 +0900
@@ -360,7 +360,7 @@
         return baseset([x])
     return baseset()
 
-def rangeset(repo, subset, x, y):
+def rangeset(repo, subset, x, y, order):
     m = getset(repo, fullreposet(repo), x)
     n = getset(repo, fullreposet(repo), y)
 
@@ -385,16 +385,16 @@
     # would be more efficient.
     return r & subset
 
-def dagrange(repo, subset, x, y):
+def dagrange(repo, subset, x, y, order):
     r = fullreposet(repo)
     xs = reachableroots(repo, getset(repo, r, x), getset(repo, r, y),
                          includepath=True)
     return subset & xs
 
-def andset(repo, subset, x, y):
+def andset(repo, subset, x, y, order):
     return getset(repo, getset(repo, subset, x), y)
 
-def differenceset(repo, subset, x, y):
+def differenceset(repo, subset, x, y, order):
     return getset(repo, subset, x) - getset(repo, subset, y)
 
 def _orsetlist(repo, subset, xs):
@@ -406,10 +406,10 @@
     b = _orsetlist(repo, subset, xs[p:])
     return a + b
 
-def orset(repo, subset, x):
+def orset(repo, subset, x, order):
     return _orsetlist(repo, subset, getlist(x))
 
-def notset(repo, subset, x):
+def notset(repo, subset, x, order):
     return subset - getset(repo, subset, x)
 
 def listset(repo, subset, *xs):
@@ -419,7 +419,7 @@
 def keyvaluepair(repo, subset, k, v):
     raise error.ParseError(_("can't use a key-value pair in this context"))
 
-def func(repo, subset, a, b):
+def func(repo, subset, a, b, order):
     f = getsymbol(a)
     if f in symbols:
         return symbols[f](repo, subset, b)
@@ -516,7 +516,7 @@
     # Like ``ancestors(set)`` but follows only the first parents.
     return _ancestors(repo, subset, x, followfirst=True)
 
-def ancestorspec(repo, subset, x, n):
+def ancestorspec(repo, subset, x, n, order):
     """``set~n``
     Changesets that are the Nth ancestor (first parents only) of a changeset
     in set.
@@ -1528,7 +1528,7 @@
     # some optimisations from the fact this is a baseset.
     return subset & ps
 
-def parentpost(repo, subset, x):
+def parentpost(repo, subset, x, order):
     return p1(repo, subset, x)
 
 @predicate('parents([set])', safe=True)
@@ -1581,7 +1581,7 @@
     target = phases.secret
     return _phase(repo, subset, target)
 
-def parentspec(repo, subset, x, n):
+def parentspec(repo, subset, x, n, order):
     """``set^0``
     The set.
     ``set^1`` (or ``set^``), ``set^2``
@@ -2426,25 +2426,25 @@
     elif op == 'and':
         ta = _analyze(x[1], order)
         tb = _analyze(x[2], _tofolloworder[order])
-        return (op, ta, tb)
+        return (op, ta, tb, order)
     elif op == 'or':
-        return (op, _analyze(x[1], order))
+        return (op, _analyze(x[1], order), order)
     elif op == 'not':
-        return (op, _analyze(x[1], anyorder))
+        return (op, _analyze(x[1], anyorder), order)
     elif op == 'parentpost':
-        return (op, _analyze(x[1], defineorder))
+        return (op, _analyze(x[1], defineorder), order)
     elif op == 'group':
         return _analyze(x[1], order)
     elif op in ('dagrange', 'range', 'parent', 'ancestor'):
         ta = _analyze(x[1], defineorder)
         tb = _analyze(x[2], defineorder)
-        return (op, ta, tb)
+        return (op, ta, tb, order)
     elif op == 'list':
         return (op,) + tuple(_analyze(y, order) for y in x[1:])
     elif op == 'keyvalue':
         return (op, x[1], _analyze(x[2], order))
     elif op == 'func':
-        return (op, x[1], _analyze(x[2], defineorder))
+        return (op, x[1], _analyze(x[2], defineorder), order)
     raise ValueError('invalid operator %r' % op)
 
 def analyze(x, order=defineorder):
@@ -2473,22 +2473,24 @@
     elif op == 'and':
         wa, ta = _optimize(x[1], True)
         wb, tb = _optimize(x[2], True)
+        order = x[3]
         w = min(wa, wb)
 
         # (::x and not ::y)/(not ::y and ::x) have a fast path
         tm = _matchonly(ta, tb) or _matchonly(tb, ta)
         if tm:
-            return w, ('func', ('symbol', 'only'), tm)
+            return w, ('func', ('symbol', 'only'), tm, order)
 
         if tb is not None and tb[0] == 'not':
-            return wa, ('difference', ta, tb[1])
+            return wa, ('difference', ta, tb[1], order)
 
         if wa > wb:
-            return w, (op, tb, ta)
-        return w, (op, ta, tb)
+            return w, (op, tb, ta, order)
+        return w, (op, ta, tb, order)
     elif op == 'or':
         # fast path for machine-generated expression, that is likely to have
         # lots of trivial revisions: 'a + b + c()' to '_list(a b) + c()'
+        order = x[2]
         ws, ts, ss = [], [], []
         def flushss():
             if not ss:
@@ -2497,7 +2499,7 @@
                 w, t = ss[0]
             else:
                 s = '\0'.join(t[1] for w, t in ss)
-                y = ('func', ('symbol', '_list'), ('string', s))
+                y = ('func', ('symbol', '_list'), ('string', s), order)
                 w, t = _optimize(y, False)
             ws.append(w)
             ts.append(t)
@@ -2516,23 +2518,27 @@
         # we can't reorder trees by weight because it would change the order.
         # ("sort(a + b)" == "sort(b + a)", but "a + b" != "b + a")
         #   ts = tuple(t for w, t in sorted(zip(ws, ts), key=lambda wt: wt[0]))
-        return max(ws), (op, ('list',) + tuple(ts))
+        return max(ws), (op, ('list',) + tuple(ts), order)
     elif op == 'not':
         # Optimize not public() to _notpublic() because we have a fast version
-        if x[1] == ('func', ('symbol', 'public'), None):
-            newsym = ('func', ('symbol', '_notpublic'), None)
+        if x[1][:3] == ('func', ('symbol', 'public'), None):
+            order = x[1][3]
+            newsym = ('func', ('symbol', '_notpublic'), None, order)
             o = _optimize(newsym, not small)
             return o[0], o[1]
         else:
             o = _optimize(x[1], not small)
-            return o[0], (op, o[1])
+            order = x[2]
+            return o[0], (op, o[1], order)
     elif op == 'parentpost':
         o = _optimize(x[1], small)
-        return o[0], (op, o[1])
+        order = x[2]
+        return o[0], (op, o[1], order)
     elif op in ('dagrange', 'range', 'parent', 'ancestor'):
         wa, ta = _optimize(x[1], small)
         wb, tb = _optimize(x[2], small)
-        return wa + wb, (op, ta, tb)
+        order = x[3]
+        return wa + wb, (op, ta, tb, order)
     elif op == 'list':
         ws, ts = zip(*(_optimize(y, small) for y in x[1:]))
         return sum(ws), (op,) + ts
@@ -2557,7 +2563,8 @@
             w = 10 # assume most sorts look at changelog
         else:
             w = 1
-        return w + wa, (op, x[1], ta)
+        order = x[3]
+        return w + wa, (op, x[1], ta, order)
     raise ValueError('invalid operator %r' % op)
 
 def optimize(tree):
--- a/tests/test-revset.t	Sun Aug 07 17:48:52 2016 +0900
+++ b/tests/test-revset.t	Sun Aug 07 17:46:12 2016 +0900
@@ -163,7 +163,8 @@
   * optimized:
   (range
     ('string', '0')
-    ('string', 'tip'))
+    ('string', 'tip')
+    define)
   * set:
   <spanset+ 0:9>
   0
@@ -491,7 +492,8 @@
     ('symbol', 'foo')
     (func
       ('symbol', '_notpublic')
-      None))
+      None
+      any))
   hg: parse error: can't use a key-value pair in this context
   [255]
 
@@ -543,15 +545,20 @@
     (or
       (list
         ('symbol', '0')
-        ('symbol', '1')))
+        ('symbol', '1'))
+      define)
     (not
-      ('symbol', '1')))
+      ('symbol', '1')
+      follow)
+    define)
   * optimized:
   (difference
     (func
       ('symbol', '_list')
-      ('string', '0\x001'))
-    ('symbol', '1'))
+      ('string', '0\x001')
+      define)
+    ('symbol', '1')
+    define)
   0
 
   $ hg debugrevspec -p unknown '0'
@@ -571,14 +578,18 @@
   (and
     (func
       ('symbol', 'r3232')
-      None)
-    ('symbol', '2'))
+      None
+      define)
+    ('symbol', '2')
+    define)
   * optimized:
   (and
     ('symbol', '2')
     (func
       ('symbol', 'r3232')
-      None))
+      None
+      define)
+    define)
   * analyzed set:
   <baseset [2]>
   * optimized set:
@@ -1027,8 +1038,11 @@
     (difference
       (range
         ('symbol', '8')
-        ('symbol', '9'))
-      ('symbol', '8')))
+        ('symbol', '9')
+        define)
+      ('symbol', '8')
+      define)
+    define)
   * set:
   <baseset+ [8, 9]>
   8
@@ -1044,7 +1058,8 @@
     ('symbol', 'only')
     (list
       ('symbol', '9')
-      ('symbol', '5')))
+      ('symbol', '5'))
+    define)
   * set:
   <baseset+ [2, 4, 8, 9]>
   2
@@ -1258,10 +1273,13 @@
   (and
     (range
       ('symbol', '2')
-      ('symbol', '0'))
+      ('symbol', '0')
+      define)
     (func
       ('symbol', '_list')
-      ('string', '0\x001\x002')))
+      ('string', '0\x001\x002')
+      follow)
+    define)
   * set:
   <baseset [0, 1, 2]>
   0
@@ -1287,13 +1305,17 @@
   (and
     (range
       ('symbol', '2')
-      ('symbol', '0'))
+      ('symbol', '0')
+      define)
     (or
       (list
         (range
           ('symbol', '0')
-          ('symbol', '1'))
-        ('symbol', '2'))))
+          ('symbol', '1')
+          follow)
+        ('symbol', '2'))
+      follow)
+    define)
   * set:
   <addset
     <filteredset
@@ -1319,10 +1341,13 @@
   (and
     (func
       ('symbol', '_intlist')
-      ('string', '0\x001\x002'))
+      ('string', '0\x001\x002')
+      follow)
     (range
       ('symbol', '2')
-      ('symbol', '0')))
+      ('symbol', '0')
+      define)
+    define)
   * set:
   <filteredset
     <spanset- 0:2>,
@@ -1343,10 +1368,13 @@
   (and
     (func
       ('symbol', '_intlist')
-      ('string', '0\x002\x001'))
+      ('string', '0\x002\x001')
+      define)
     (range
       ('symbol', '2')
-      ('symbol', '0')))
+      ('symbol', '0')
+      follow)
+    define)
   * set:
   <filteredset
     <spanset- 0:2>,
@@ -1370,10 +1398,13 @@
   (and
     (range
       ('symbol', '2')
-      ('symbol', '0'))
+      ('symbol', '0')
+      define)
     (func
       ('symbol', '_hexlist')
-      ('string', '*'))) (glob)
+      ('string', '*') (glob)
+      follow)
+    define)
   * set:
   <baseset [0, 1, 2]>
   0
@@ -1393,10 +1424,13 @@
   (and
     (range
       ('symbol', '2')
-      ('symbol', '0'))
+      ('symbol', '0')
+      follow)
     (func
       ('symbol', '_hexlist')
-      ('string', '*'))) (glob)
+      ('string', '*') (glob)
+      define)
+    define)
   * set:
   <baseset [0, 2, 1]>
   0
@@ -1421,12 +1455,16 @@
   (and
     (range
       ('symbol', '2')
-      ('symbol', '0'))
+      ('symbol', '0')
+      define)
     (func
       ('symbol', 'present')
       (func
         ('symbol', '_list')
-        ('string', '0\x001\x002'))))
+        ('string', '0\x001\x002')
+        define)
+      follow)
+    define)
   * set:
   <baseset [0, 1, 2]>
   0
@@ -1450,12 +1488,16 @@
   (and
     (range
       ('symbol', '0')
-      ('symbol', '2'))
+      ('symbol', '2')
+      define)
     (func
       ('symbol', 'reverse')
       (func
         ('symbol', 'all')
-        None)))
+        None
+        define)
+      follow)
+    define)
   * set:
   <filteredset
     <spanset- 0:2>,
@@ -1484,14 +1526,18 @@
   (and
     (range
       ('symbol', '0')
-      ('symbol', '2'))
+      ('symbol', '2')
+      define)
     (func
       ('symbol', 'sort')
       (list
         (func
           ('symbol', 'all')
-          None)
-        ('string', '-rev'))))
+          None
+          define)
+        ('string', '-rev'))
+      follow)
+    define)
   * set:
   <filteredset
     <spanset- 0:2>,
@@ -1519,12 +1565,16 @@
   (and
     (range
       ('symbol', '2')
-      ('symbol', '0'))
+      ('symbol', '0')
+      define)
     (func
       ('symbol', 'first')
       (func
         ('symbol', '_list')
-        ('string', '1\x000\x002'))))
+        ('string', '1\x000\x002')
+        define)
+      follow)
+    define)
   * set:
   <baseset
     <limit n=1, offset=0,
@@ -1549,12 +1599,16 @@
   (difference
     (range
       ('symbol', '2')
-      ('symbol', '0'))
+      ('symbol', '0')
+      define)
     (func
       ('symbol', 'last')
       (func
         ('symbol', '_list')
-        ('string', '0\x002\x001'))))
+        ('string', '0\x002\x001')
+        define)
+      any)
+    define)
   * set:
   <filteredset
     <spanset- 0:2>,
@@ -1590,14 +1644,19 @@
   (and
     (range
       ('symbol', '2')
-      ('symbol', '0'))
+      ('symbol', '0')
+      define)
     (range
       (func
         ('symbol', '_list')
-        ('string', '1\x000\x002'))
+        ('string', '1\x000\x002')
+        define)
       (func
         ('symbol', '_list')
-        ('string', '0\x002\x001'))))
+        ('string', '0\x002\x001')
+        define)
+      follow)
+    define)
   * set:
   <filteredset
     <baseset [1]>,
@@ -1623,10 +1682,13 @@
   (and
     (func
       ('symbol', '_list')
-      ('string', '2\x000\x001'))
+      ('string', '2\x000\x001')
+      follow)
     (func
       ('symbol', 'contains')
-      ('string', 'glob:*')))
+      ('string', 'glob:*')
+      define)
+    define)
   * set:
   <filteredset
     <baseset [2, 0, 1]>,
@@ -1653,12 +1715,16 @@
   (and
     (func
       ('symbol', '_list')
-      ('string', '0\x002\x001'))
+      ('string', '0\x002\x001')
+      follow)
     (func
       ('symbol', 'reverse')
       (func
         ('symbol', 'contains')
-        ('string', 'glob:*'))))
+        ('string', 'glob:*')
+        define)
+      define)
+    define)
   * set:
   <filteredset
     <baseset [1, 2, 0]>,
@@ -2052,7 +2118,8 @@
   * optimized:
   (func
     ('symbol', '_list')
-    ('string', '0\x001\x002\x00-2\x00tip\x00null'))
+    ('string', '0\x001\x002\x00-2\x00tip\x00null')
+    define)
   * set:
   <baseset [0, 1, 2, 8, 9, -1]>
   0
@@ -2075,10 +2142,13 @@
     (list
       (func
         ('symbol', '_list')
-        ('string', '0\x001'))
+        ('string', '0\x001')
+        define)
       (range
         ('symbol', '2')
-        ('symbol', '3'))))
+        ('symbol', '3')
+        define))
+    define)
   * set:
   <addset
     <baseset [0, 1]>,
@@ -2105,14 +2175,18 @@
     (list
       (range
         ('symbol', '0')
-        ('symbol', '1'))
+        ('symbol', '1')
+        define)
       ('symbol', '2')
       (range
         ('symbol', '3')
-        ('symbol', '4'))
+        ('symbol', '4')
+        define)
       (func
         ('symbol', '_list')
-        ('string', '5\x006'))))
+        ('string', '5\x006')
+        define))
+    define)
   * set:
   <addset
     <addset
@@ -2139,7 +2213,8 @@
       ('symbol', '1')
       ('symbol', '2')
       ('symbol', '3')
-      ('symbol', '4')))
+      ('symbol', '4'))
+    define)
   * set:
   <addset
     <addset
@@ -2259,7 +2334,8 @@
   (or
     (list
       ('symbol', '0')
-      None))
+      None)
+    define)
   hg: parse error: missing argument
   [255]
 
@@ -2289,7 +2365,8 @@
     ('symbol', 'only')
     (list
       ('symbol', '3')
-      ('symbol', '1')))
+      ('symbol', '1'))
+    define)
   * set:
   <baseset+ [3]>
   3
@@ -2306,7 +2383,8 @@
     ('symbol', 'only')
     (list
       ('symbol', '1')
-      ('symbol', '3')))
+      ('symbol', '3'))
+    define)
   * set:
   <baseset+ []>
   $ try --optimize 'not ::2 and ::6'
@@ -2321,7 +2399,8 @@
     ('symbol', 'only')
     (list
       ('symbol', '6')
-      ('symbol', '2')))
+      ('symbol', '2'))
+    define)
   * set:
   <baseset+ [3, 4, 5, 6]>
   3
@@ -2342,7 +2421,8 @@
     ('symbol', 'only')
     (list
       ('symbol', '6')
-      ('symbol', '4')))
+      ('symbol', '4'))
+    define)
   * set:
   <baseset+ [3, 5, 6]>
   3
@@ -2362,7 +2442,9 @@
     None
     (func
       ('symbol', 'ancestors')
-      ('symbol', '1')))
+      ('symbol', '1')
+      define)
+    define)
   hg: parse error: missing argument
   [255]