diff -r 79681d8ee587 -r f23cbca9b277 mercurial/revsetlang.py --- a/mercurial/revsetlang.py Wed Feb 17 21:31:09 2016 +0900 +++ b/mercurial/revsetlang.py Wed Feb 17 21:40:59 2016 +0900 @@ -258,6 +258,18 @@ template = _cachedtree(tmplspec) return parser.buildtree(template, ('symbol', '_'), *repls) +def _match(patspec, tree): + """Test if a tree matches the given pattern statement; return the matches + + >>> _match('f(_)', parse('f()')) + >>> _match('f(_)', parse('f(1)')) + [('func', ('symbol', 'f'), ('symbol', '1')), ('symbol', '1')] + >>> _match('f(_)', parse('f(1, 2)')) + """ + pattern = _cachedtree(patspec) + return parser.matchtree(pattern, tree, ('symbol', '_'), + {'keyvalue', 'list'}) + def _isnamedfunc(x, funcname): """Check if given tree matches named function""" return x and x[0] == 'func' and getsymbol(x[1]) == funcname @@ -278,15 +290,7 @@ return x[2] def _matchonly(revs, bases): - """ - >>> f = lambda *args: _matchonly(*map(parse, args)) - >>> f('ancestors(A)', 'not ancestors(B)') - ('list', ('symbol', 'A'), ('symbol', 'B')) - """ - ta = _matchnamedfunc(revs, 'ancestors') - tb = bases and bases[0] == 'not' and _matchnamedfunc(bases[1], 'ancestors') - if _isposargs(ta, 1) and _isposargs(tb, 1): - return ('list', ta, tb) + return _match('ancestors(_) and not ancestors(_)', ('and', revs, bases)) def _fixops(x): """Rewrite raw parsed tree to resolve ambiguous syntax which cannot be @@ -389,8 +393,9 @@ if m: return w, _build('only(_, _)', *m[1:]) - if tb is not None and tb[0] == 'not': - return wa, ('difference', ta, tb[1]) + m = _match('not _', tb) + if m: + return wa, ('difference', ta, m[1]) if wa > wb: op = 'andsmally' return w, (op, ta, tb) @@ -424,7 +429,7 @@ return max(ws), (op, ('list',) + tuple(ts)) elif op == 'not': # Optimize not public() to _notpublic() because we have a fast version - if x[1][:3] == ('func', ('symbol', 'public'), None): + if _match('public()', x[1]): o = _optimize(_build('_notpublic()'), not small) return o[0], o[1] else: