diff mercurial/revset.py @ 29932:09a84e747c88

revset: pass around ordering flags to operations Some operations and functions will need them to fix ordering bugs.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 07 Aug 2016 17:46:12 +0900
parents d2d1be3009ca
children 91a95ad985d8
line wrap: on
line diff
--- 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):