# HG changeset patch # User Yuya Nishihara # Date 1470557045 -32400 # Node ID b3845cab4ddc9fcab4902e66683605f55438c1a3 # Parent e5a97ec6ebb8c6d2a9dcfbc5cb8e0dd5aec03ec5 revset: wrap arguments of 'or' by 'list' node This makes the number of 'or' arguments deterministic so we can attach additional ordering flag to all operator nodes. See the next patch. We rewrite the tree immediately after chained 'or' operations are flattened by simplifyinfixops(), so we don't need to care if arguments are stored in x[1] or x[1:]. diff -r e5a97ec6ebb8 -r b3845cab4ddc mercurial/revset.py --- a/mercurial/revset.py Tue Sep 13 20:30:19 2016 +0200 +++ b/mercurial/revset.py Sun Aug 07 17:04:05 2016 +0900 @@ -397,15 +397,18 @@ def differenceset(repo, subset, x, y): return getset(repo, subset, x) - getset(repo, subset, y) -def orset(repo, subset, *xs): +def _orsetlist(repo, subset, xs): assert xs if len(xs) == 1: return getset(repo, subset, xs[0]) p = len(xs) // 2 - a = orset(repo, subset, *xs[:p]) - b = orset(repo, subset, *xs[p:]) + a = _orsetlist(repo, subset, xs[:p]) + b = _orsetlist(repo, subset, xs[p:]) return a + b +def orset(repo, subset, x): + return _orsetlist(repo, subset, getlist(x)) + def notset(repo, subset, x): return subset - getset(repo, subset, x) @@ -2339,6 +2342,10 @@ return _fixops(('range', post, x[2][1])) elif x[2][0] == 'rangeall': return _fixops(('rangepost', post)) + elif op == 'or': + # make number of arguments deterministic: + # x + y + z -> (or x y z) -> (or (list x y z)) + return (op, _fixops(('list',) + x[1:])) return (op,) + tuple(_fixops(y) for y in x[1:]) @@ -2374,7 +2381,7 @@ tb = _analyze(x[2]) return (op, ta, tb) elif op == 'or': - return (op,) + tuple(_analyze(y) for y in x[1:]) + return (op, _analyze(x[1])) elif op == 'not': return (op, _analyze(x[1])) elif op == 'parentpost': @@ -2445,7 +2452,7 @@ ws.append(w) ts.append(t) del ss[:] - for y in x[1:]: + for y in getlist(x[1]): w, t = _optimize(y, False) if t is not None and (t[0] == 'string' or t[0] == 'symbol'): ss.append((w, t)) @@ -2459,7 +2466,7 @@ # 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,) + tuple(ts) + return max(ws), (op, ('list',) + tuple(ts)) elif op == 'not': # Optimize not public() to _notpublic() because we have a fast version if x[1] == ('func', ('symbol', 'public'), None): @@ -2613,7 +2620,7 @@ if len(specs) == 1: tree = parse(specs[0], lookup) else: - tree = ('or',) + tuple(parse(s, lookup) for s in specs) + tree = ('or', ('list',) + tuple(parse(s, lookup) for s in specs)) if ui: tree = expandaliases(ui, tree) diff -r e5a97ec6ebb8 -r b3845cab4ddc tests/test-glog.t --- a/tests/test-glog.t Tue Sep 13 20:30:19 2016 +0200 +++ b/tests/test-glog.t Sun Aug 07 17:04:05 2016 +0900 @@ -1455,12 +1455,13 @@ (group (group (or - (func - ('symbol', 'user') - ('string', 'test')) - (func - ('symbol', 'user') - ('string', 'not-a-user'))))) + (list + (func + ('symbol', 'user') + ('string', 'test')) + (func + ('symbol', 'user') + ('string', 'not-a-user')))))) $ testlog -b not-a-branch abort: unknown revision 'not-a-branch'! abort: unknown revision 'not-a-branch'! @@ -1470,26 +1471,28 @@ (group (group (or - (func - ('symbol', 'branch') - ('string', 'default')) - (func - ('symbol', 'branch') - ('string', 'branch')) - (func - ('symbol', 'branch') - ('string', 'branch'))))) + (list + (func + ('symbol', 'branch') + ('string', 'default')) + (func + ('symbol', 'branch') + ('string', 'branch')) + (func + ('symbol', 'branch') + ('string', 'branch')))))) $ testlog -k expand -k merge [] (group (group (or - (func - ('symbol', 'keyword') - ('string', 'expand')) - (func - ('symbol', 'keyword') - ('string', 'merge'))))) + (list + (func + ('symbol', 'keyword') + ('string', 'expand')) + (func + ('symbol', 'keyword') + ('string', 'merge')))))) $ testlog --only-merges [] (group @@ -1520,17 +1523,19 @@ (not (group (or - ('string', '31') - (func - ('symbol', 'ancestors') - ('string', '31'))))) + (list + ('string', '31') + (func + ('symbol', 'ancestors') + ('string', '31')))))) (not (group (or - ('string', '32') - (func - ('symbol', 'ancestors') - ('string', '32')))))))) + (list + ('string', '32') + (func + ('symbol', 'ancestors') + ('string', '32'))))))))) Dedicated repo for --follow and paths filtering. The g is crafted to have 2 filelog topological heads in a linear changeset graph. @@ -1587,12 +1592,13 @@ (group (group (or - (func - ('symbol', 'filelog') - ('string', 'a')) - (func - ('symbol', 'filelog') - ('string', 'b'))))) + (list + (func + ('symbol', 'filelog') + ('string', 'a')) + (func + ('symbol', 'filelog') + ('string', 'b')))))) Test falling back to slow path for non-existing files @@ -1744,12 +1750,13 @@ (group (group (or - (func - ('symbol', 'follow') - ('string', 'g')) - (func - ('symbol', 'follow') - ('string', 'e'))))) + (list + (func + ('symbol', 'follow') + ('string', 'g')) + (func + ('symbol', 'follow') + ('string', 'e')))))) $ cat log.nodes nodetag 4 nodetag 3 diff -r e5a97ec6ebb8 -r b3845cab4ddc tests/test-revset.t --- a/tests/test-revset.t Tue Sep 13 20:30:19 2016 +0200 +++ b/tests/test-revset.t Sun Aug 07 17:04:05 2016 +0900 @@ -187,9 +187,10 @@ 6 $ try '0|1|2' (or - ('symbol', '0') - ('symbol', '1') - ('symbol', '2')) + (list + ('symbol', '0') + ('symbol', '1') + ('symbol', '2'))) * set: 0 @@ -339,10 +340,11 @@ $ log '1&2' $ try '1&2|3' # precedence - and is higher (or - (and - ('symbol', '1') - ('symbol', '2')) - ('symbol', '3')) + (list + (and + ('symbol', '1') + ('symbol', '2')) + ('symbol', '3'))) * set: , @@ -350,10 +352,11 @@ 3 $ try '1|2&3' (or - ('symbol', '1') - (and - ('symbol', '2') - ('symbol', '3'))) + (list + ('symbol', '1') + (and + ('symbol', '2') + ('symbol', '3')))) * set: , @@ -369,11 +372,13 @@ $ try '1|(2|3)' (or - ('symbol', '1') - (group - (or - ('symbol', '2') - ('symbol', '3')))) + (list + ('symbol', '1') + (group + (or + (list + ('symbol', '2') + ('symbol', '3')))))) * set: , @@ -465,8 +470,9 @@ (keyvalue ('symbol', 'foo') (or - ('symbol', 'bar') - ('symbol', 'baz'))) + (list + ('symbol', 'bar') + ('symbol', 'baz')))) hg: parse error: can't use a key-value pair in this context [255] @@ -528,14 +534,16 @@ (minus (group (or - ('symbol', '0') - ('symbol', '1'))) + (list + ('symbol', '0') + ('symbol', '1')))) ('symbol', '1')) * analyzed: (and (or - ('symbol', '0') - ('symbol', '1')) + (list + ('symbol', '0') + ('symbol', '1'))) (not ('symbol', '1'))) * optimized: @@ -1242,9 +1250,10 @@ ('symbol', '0')) (group (or - ('symbol', '0') - ('symbol', '1') - ('symbol', '2')))) + (list + ('symbol', '0') + ('symbol', '1') + ('symbol', '2'))))) * optimized: (and (range @@ -1269,20 +1278,22 @@ ('symbol', '0')) (group (or - (range - ('symbol', '0') - ('symbol', '1')) - ('symbol', '2')))) + (list + (range + ('symbol', '0') + ('symbol', '1')) + ('symbol', '2'))))) * optimized: (and (range ('symbol', '2') ('symbol', '0')) (or - (range - ('symbol', '0') - ('symbol', '1')) - ('symbol', '2'))) + (list + (range + ('symbol', '0') + ('symbol', '1')) + ('symbol', '2')))) * set: , @@ -1997,14 +2016,15 @@ (func ('symbol', 'sort') (or - (func - ('symbol', 'ancestors') - ('symbol', '4')) - (func - ('symbol', 'reverse') - (dagrange - ('symbol', '1') - ('symbol', '5'))))) + (list + (func + ('symbol', 'ancestors') + ('symbol', '4')) + (func + ('symbol', 'reverse') + (dagrange + ('symbol', '1') + ('symbol', '5')))))) * set: , @@ -2020,14 +2040,15 @@ $ try --optimize '0|(1)|"2"|-2|tip|null' (or - ('symbol', '0') - (group - ('symbol', '1')) - ('string', '2') - (negate - ('symbol', '2')) - ('symbol', 'tip') - ('symbol', 'null')) + (list + ('symbol', '0') + (group + ('symbol', '1')) + ('string', '2') + (negate + ('symbol', '2')) + ('symbol', 'tip') + ('symbol', 'null'))) * optimized: (func ('symbol', '_list') @@ -2043,19 +2064,21 @@ $ try --optimize '0|1|2:3' (or - ('symbol', '0') - ('symbol', '1') - (range - ('symbol', '2') - ('symbol', '3'))) + (list + ('symbol', '0') + ('symbol', '1') + (range + ('symbol', '2') + ('symbol', '3')))) * optimized: (or - (func - ('symbol', '_list') - ('string', '0\x001')) - (range - ('symbol', '2') - ('symbol', '3'))) + (list + (func + ('symbol', '_list') + ('string', '0\x001')) + (range + ('symbol', '2') + ('symbol', '3')))) * set: , @@ -2067,27 +2090,29 @@ $ try --optimize '0:1|2|3:4|5|6' (or - (range - ('symbol', '0') - ('symbol', '1')) - ('symbol', '2') - (range - ('symbol', '3') - ('symbol', '4')) - ('symbol', '5') - ('symbol', '6')) + (list + (range + ('symbol', '0') + ('symbol', '1')) + ('symbol', '2') + (range + ('symbol', '3') + ('symbol', '4')) + ('symbol', '5') + ('symbol', '6'))) * optimized: (or - (range - ('symbol', '0') - ('symbol', '1')) - ('symbol', '2') - (range - ('symbol', '3') - ('symbol', '4')) - (func - ('symbol', '_list') - ('string', '5\x006'))) + (list + (range + ('symbol', '0') + ('symbol', '1')) + ('symbol', '2') + (range + ('symbol', '3') + ('symbol', '4')) + (func + ('symbol', '_list') + ('string', '5\x006')))) * set: , @@ -2769,15 +2800,16 @@ ('symbol', '3')))) * expanded: (or - (range - ('symbol', '0') - ('symbol', '1')) - (range - ('symbol', '1') - ('symbol', '2')) - (range - ('symbol', '2') - ('symbol', '3'))) + (list + (range + ('symbol', '0') + ('symbol', '1')) + (range + ('symbol', '1') + ('symbol', '2')) + (range + ('symbol', '2') + ('symbol', '3')))) * set: , @@ -2868,10 +2900,11 @@ ('symbol', 'tip'))) * expanded: (or - ('symbol', 'tip') - (func - ('symbol', 'desc') - ('string', '$1'))) + (list + ('symbol', 'tip') + (func + ('symbol', 'desc') + ('string', '$1')))) * set: , @@ -2907,8 +2940,9 @@ ('symbol', 'rs') (list (or - ('symbol', '2') - ('symbol', '3')) + (list + ('symbol', '2') + ('symbol', '3'))) ('symbol', 'date'))) * expanded: (func @@ -2917,8 +2951,9 @@ ('symbol', 'sort') (list (or - ('symbol', '2') - ('symbol', '3')) + (list + ('symbol', '2') + ('symbol', '3'))) ('symbol', 'date')))) * set: @@ -2950,8 +2985,9 @@ ('symbol', 'rs4') (list (or - ('symbol', '2') - ('symbol', '3')) + (list + ('symbol', '2') + ('symbol', '3'))) ('symbol', 'x') ('symbol', 'x') ('symbol', 'date'))) @@ -2962,8 +2998,9 @@ ('symbol', 'sort') (list (or - ('symbol', '2') - ('symbol', '3')) + (list + ('symbol', '2') + ('symbol', '3'))) ('symbol', 'date')))) * set: @@ -3034,9 +3071,10 @@ ('symbol', 'limit') (list (or - ('symbol', '1') - ('symbol', '2') - ('symbol', '3')) + (list + ('symbol', '1') + ('symbol', '2') + ('symbol', '3'))) ('symbol', '2'))) (not ('symbol', '2'))) @@ -3054,8 +3092,9 @@ (func ('symbol', 'max') (or - ('symbol', '1') - ('symbol', '2'))) + (list + ('symbol', '1') + ('symbol', '2')))) (not ('symbol', '2'))) * set: @@ -3071,8 +3110,9 @@ (func ('symbol', 'min') (or - ('symbol', '1') - ('symbol', '2'))) + (list + ('symbol', '1') + ('symbol', '2')))) (not ('symbol', '1'))) * set: @@ -3089,8 +3129,9 @@ ('symbol', 'last') (list (or - ('symbol', '1') - ('symbol', '2')) + (list + ('symbol', '1') + ('symbol', '2'))) ('symbol', '1'))) (not ('symbol', '2')))