revset: pass around ordering flags to operations
Some operations and functions will need them to fix ordering bugs.
--- 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]