Mercurial > hg-stable
changeset 29780:abe4eecc3253
revset: resolve ambiguity of x^:y before alias expansion
This is purely a parsing problem, which should be resolved before alias
expansion.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 06 Aug 2016 20:21:00 +0900 |
parents | 8e4841944e68 |
children | 9c51a5de76db |
files | mercurial/revset.py tests/test-revset.t |
diffstat | 2 files changed, 39 insertions(+), 88 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/revset.py Sat Aug 06 19:59:28 2016 +0900 +++ b/mercurial/revset.py Sat Aug 06 20:21:00 2016 +0900 @@ -2314,6 +2314,23 @@ and getsymbol(bases[1][1]) == 'ancestors'): return ('list', revs[2], bases[1][2]) +def _fixops(x): + """Rewrite raw parsed tree to resolve ambiguous syntax which cannot be + handled well by our simple top-down parser""" + if not isinstance(x, tuple): + return x + + op = x[0] + if op == 'parent': + # x^:y means (x^) : y, not x ^ (:y) + post = ('parentpost', x[1]) + if x[2][0] == 'dagrangepre': + return _fixops(('dagrange', post, x[2][1])) + elif x[2][0] == 'rangepre': + return _fixops(('range', post, x[2][1])) + + return (op,) + tuple(_fixops(y) for y in x[1:]) + def _optimize(x, small): if x is None: return 0, x @@ -2407,14 +2424,6 @@ elif op == 'group': return _optimize(x[1], small) elif op in 'dagrange range parent ancestorspec': - if op == 'parent': - # x^:y means (x^) : y, not x ^ (:y) - post = ('parentpost', x[1]) - if x[2][0] == 'dagrangepre': - return _optimize(('dagrange', post, x[2][1]), small) - elif x[2][0] == 'rangepre': - return _optimize(('range', post, x[2][1]), small) - wa, ta = _optimize(x[1], small) wb, tb = _optimize(x[2], small) return wa + wb, (op, ta, tb) @@ -2470,7 +2479,7 @@ syminitletters=syminitletters)) if pos != len(spec): raise error.ParseError(_('invalid token'), pos) - return parser.simplifyinfixops(tree, ('list', 'or')) + return _fixops(parser.simplifyinfixops(tree, ('list', 'or'))) class _aliasrules(parser.basealiasrules): """Parsing and expansion rule set of revset aliases"""
--- a/tests/test-revset.t Sat Aug 06 19:59:28 2016 +0900 +++ b/tests/test-revset.t Sat Aug 06 20:21:00 2016 +0900 @@ -482,12 +482,7 @@ x^:y means (x^):y - $ try --optimize '1^:2' - (parent - ('symbol', '1') - (rangepre - ('symbol', '2'))) - * optimized: + $ try '1^:2' (range (parentpost ('symbol', '1')) @@ -498,12 +493,7 @@ 1 2 - $ try --optimize '1^::2' - (parent - ('symbol', '1') - (dagrangepre - ('symbol', '2'))) - * optimized: + $ try '1^::2' (dagrange (parentpost ('symbol', '1')) @@ -516,31 +506,18 @@ x^:y should be resolved before omitting group operators - $ try --optimize '1^(:2)' + $ try '1^(:2)' (parent ('symbol', '1') (group (rangepre ('symbol', '2')))) - * optimized: - (parent - ('symbol', '1') - (range - ('string', '0') - ('symbol', '2'))) hg: parse error: ^ expects a number 0, 1, or 2 [255] x^:y should be resolved recursively - $ try --optimize 'sort(1^:2)' - (func - ('symbol', 'sort') - (parent - ('symbol', '1') - (rangepre - ('symbol', '2')))) - * optimized: + $ try 'sort(1^:2)' (func ('symbol', 'sort') (range @@ -553,22 +530,14 @@ 1 2 - $ try --optimize '(3^:4)^:2' - (parent - (group - (parent - ('symbol', '3') - (rangepre - ('symbol', '4')))) - (rangepre - ('symbol', '2'))) - * optimized: + $ try '(3^:4)^:2' (range (parentpost - (range - (parentpost - ('symbol', '3')) - ('symbol', '4'))) + (group + (range + (parentpost + ('symbol', '3')) + ('symbol', '4')))) ('symbol', '2')) * set: <spanset+ 0:2> @@ -576,22 +545,14 @@ 1 2 - $ try --optimize '(3^::4)^::2' - (parent - (group - (parent - ('symbol', '3') - (dagrangepre - ('symbol', '4')))) - (dagrangepre - ('symbol', '2'))) - * optimized: + $ try '(3^::4)^::2' (dagrange (parentpost - (dagrange - (parentpost - ('symbol', '3')) - ('symbol', '4'))) + (group + (dagrange + (parentpost + ('symbol', '3')) + ('symbol', '4')))) ('symbol', '2')) * set: <baseset+ [0, 1, 2]> @@ -601,14 +562,9 @@ x^ in alias should also be resolved - $ try --optimize 'A' --config 'revsetalias.A=1^:2' + $ try 'A' --config 'revsetalias.A=1^:2' ('symbol', 'A') * expanded: - (parent - ('symbol', '1') - (rangepre - ('symbol', '2'))) - * optimized: (range (parentpost ('symbol', '1')) @@ -619,7 +575,7 @@ 1 2 - $ try --optimize 'A:2' --config 'revsetalias.A=1^' + $ try 'A:2' --config 'revsetalias.A=1^' (range ('symbol', 'A') ('symbol', '2')) @@ -628,11 +584,6 @@ (parentpost ('symbol', '1')) ('symbol', '2')) - * optimized: - (range - (parentpost - ('symbol', '1')) - ('symbol', '2')) * set: <spanset+ 0:2> 0 @@ -642,7 +593,7 @@ but not beyond the boundary of alias expansion, because the resolution should be made at the parsing stage - $ try --optimize '1^A' --config 'revsetalias.A=:2' + $ try '1^A' --config 'revsetalias.A=:2' (parent ('symbol', '1') ('symbol', 'A')) @@ -651,17 +602,8 @@ ('symbol', '1') (rangepre ('symbol', '2'))) - * optimized: - (range - (parentpost - ('symbol', '1')) - ('symbol', '2')) - * set: - <spanset+ 0:2> - 0 - 1 - 2 -BROKEN: should be parsed as '1^(:2)' + hg: parse error: ^ expects a number 0, 1, or 2 + [255] ancestor can accept 0 or more arguments