# HG changeset patch # User Yuya Nishihara # Date 1470559572 -32400 # Node ID 09a84e747c88cf4bf6e3b65a662621283317202e # Parent d2d1be3009cac61e55c07320144a0e7e03171b36 revset: pass around ordering flags to operations Some operations and functions will need them to fix ordering bugs. diff -r d2d1be3009ca -r 09a84e747c88 mercurial/revset.py --- 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): diff -r d2d1be3009ca -r 09a84e747c88 tests/test-revset.t --- 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: 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: * optimized set: @@ -1027,8 +1038,11 @@ (difference (range ('symbol', '8') - ('symbol', '9')) - ('symbol', '8'))) + ('symbol', '9') + define) + ('symbol', '8') + define) + define) * set: 8 @@ -1044,7 +1058,8 @@ ('symbol', 'only') (list ('symbol', '9') - ('symbol', '5'))) + ('symbol', '5')) + define) * set: 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: 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: , @@ -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: , @@ -1370,10 +1398,13 @@ (and (range ('symbol', '2') - ('symbol', '0')) + ('symbol', '0') + define) (func ('symbol', '_hexlist') - ('string', '*'))) (glob) + ('string', '*') (glob) + follow) + define) * set: 0 @@ -1393,10 +1424,13 @@ (and (range ('symbol', '2') - ('symbol', '0')) + ('symbol', '0') + follow) (func ('symbol', '_hexlist') - ('string', '*'))) (glob) + ('string', '*') (glob) + define) + define) * set: 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: 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: , @@ -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: , @@ -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: , @@ -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: , @@ -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: , @@ -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: , @@ -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: 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: , @@ -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: 3 @@ -2306,7 +2383,8 @@ ('symbol', 'only') (list ('symbol', '1') - ('symbol', '3'))) + ('symbol', '3')) + define) * set: $ try --optimize 'not ::2 and ::6' @@ -2321,7 +2399,8 @@ ('symbol', 'only') (list ('symbol', '6') - ('symbol', '2'))) + ('symbol', '2')) + define) * set: 3 @@ -2342,7 +2421,8 @@ ('symbol', 'only') (list ('symbol', '6') - ('symbol', '4'))) + ('symbol', '4')) + define) * set: 3 @@ -2362,7 +2442,9 @@ None (func ('symbol', 'ancestors') - ('symbol', '1'))) + ('symbol', '1') + define) + define) hg: parse error: missing argument [255]