Mercurial > public > mercurial-scm > hg
diff mercurial/revset.py @ 27987:b19d8d5d6b51 stable
revset: flatten chained 'list' operations (aka function args) (issue5072)
Internal _matchfiles() function can take bunch of arguments, which would
lead to a maximum recursion depth error. This patch avoids the excessive
stack use by flattening 'list' nodes beforehand.
Since getlist() no longer takes a nested 'list' nodes, _parsealiasdecl()
also needs to flatten argument list, "aliasname($1, $2, ...)".
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Tue, 02 Feb 2016 23:49:49 +0900 |
parents | 4186d359046a |
children | a036e1ae1fbe |
line wrap: on
line diff
--- a/mercurial/revset.py Fri Feb 05 19:40:57 2016 +0100 +++ b/mercurial/revset.py Tue Feb 02 23:49:49 2016 +0900 @@ -319,7 +319,7 @@ if not x: return [] if x[0] == 'list': - return getlist(x[1]) + [x[2]] + return list(x[1:]) return [x] def getargs(x, min, max, err): @@ -448,7 +448,7 @@ def notset(repo, subset, x): return subset - getset(repo, subset, x) -def listset(repo, subset, a, b): +def listset(repo, subset, *xs): raise error.ParseError(_("can't use a list in this context"), hint=_('see hg help "revsets.x or y"')) @@ -2252,7 +2252,7 @@ return o[0], (op, o[1]) elif op == 'group': return optimize(x[1], small) - elif op in 'dagrange range list parent ancestorspec': + elif op in 'dagrange range parent ancestorspec': if op == 'parent': # x^:y means (x^) : y, not x ^ (:y) post = ('parentpost', x[1]) @@ -2264,6 +2264,9 @@ wa, ta = optimize(x[1], small) wb, tb = optimize(x[2], small) return wa + wb, (op, ta, tb) + elif op == 'list': + ws, ts = zip(*(optimize(y, small) for y in x[1:])) + return sum(ws), (op,) + ts elif op == 'func': f = getstring(x[1], _("not a symbol")) wa, ta = optimize(x[2], small) @@ -2365,6 +2368,7 @@ tree, pos = p.parse(_tokenizealias(decl)) if (pos != len(decl)): raise error.ParseError(_('invalid token'), pos) + tree = parser.simplifyinfixops(tree, ('list',)) if isvalidsymbol(tree): # "name = ...." style @@ -2455,7 +2459,7 @@ tree, pos = p.parse(tokenizedefn(defn)) if pos != len(defn): raise error.ParseError(_('invalid token'), pos) - return parser.simplifyinfixops(tree, ('or',)) + return parser.simplifyinfixops(tree, ('list', 'or')) class revsetalias(object): # whether own `error` information is already shown or not. @@ -2586,7 +2590,7 @@ tree, pos = p.parse(tokenize(spec, lookup=lookup)) if pos != len(spec): raise error.ParseError(_("invalid token"), pos) - return parser.simplifyinfixops(tree, ('or',)) + return parser.simplifyinfixops(tree, ('list', 'or')) def posttreebuilthook(tree, repo): # hook for extensions to execute code on the optimized tree