diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -954,70 +954,46 @@ def optimize(x, small): class revsetalias(object): funcre = re.compile('^([^(]+)\(([^)]+)\)$') - args = () + args = None - def __init__(self, token, value): + def __init__(self, name, value): '''Aliases like: h = heads(default) b($1) = ancestors($1) - ancestors(default) ''' - if isinstance(token, tuple): - self.type, self.name = token - else: - m = self.funcre.search(token) + if isinstance(name, tuple): # parameter substitution + self.tree = name + self.replacement = value + else: # alias definition + m = self.funcre.search(name) if m: - self.type = 'func' - self.name = m.group(1) + self.tree = ('func', ('symbol', m.group(1))) self.args = [x.strip() for x in m.group(2).split(',')] + for arg in self.args: + value = value.replace(arg, repr(arg)) else: - self.type = 'symbol' - self.name = token + self.tree = ('symbol', name) - if isinstance(value, str): - for arg in self.args: - value = value.replace(arg, repr(arg)) self.replacement, pos = parse(value) if pos != len(value): raise error.ParseError(_('invalid token'), pos) - else: - self.replacement = value - - def match(self, tree): - if not tree: - return False - if tree == (self.type, self.name): - return True - if tree[0] != self.type: - return False - if len(tree) > 1 and tree[1] != ('symbol', self.name): - return False - # 'func' + funcname + args - if ((self.args and len(tree) != 3) or - (len(self.args) == 1 and tree[2][0] == 'list') or - (len(self.args) > 1 and (tree[2][0] != 'list' or - len(tree[2]) - 1 != len(self.args)))): - raise error.ParseError(_('invalid amount of arguments'), - len(tree) - 2) - return True - - def replace(self, tree): - if tree == (self.type, self.name): - return self.replacement - result = self.replacement - def getsubtree(i): - if tree[2][0] == 'list': - return tree[2][i + 1] - return tree[i + 2] - for i, v in enumerate(self.args): - valalias = revsetalias(('string', v), getsubtree(i)) - result = valalias.process(result) - return result def process(self, tree): - if self.match(tree): - return self.replace(tree) if isinstance(tree, tuple): + if self.args is None: + if tree == self.tree: + return self.replacement + elif tree[:2] == self.tree: + l = getlist(tree[2]) + if len(l) != len(self.args): + raise error.ParseError( + _('invalid number of arguments: %s') % len(l)) + result = self.replacement + for a, v in zip(self.args, l): + valalias = revsetalias(('string', a), v) + result = valalias.process(result) + return result return tuple(map(self.process, tree)) return tree diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -420,6 +420,7 @@ aliases: $ echo 'm = merge()' >> .hg/hgrc $ echo 'd($1) = reverse(sort($1, date))' >> .hg/hgrc $ echo 'rs(ARG1, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc + $ echo 'rs4(ARG1, ARGA, ARGB, ARG2) = reverse(sort(ARG1, ARG2))' >> .hg/hgrc $ try m ('symbol', 'm') @@ -437,6 +438,23 @@ aliases: ('func', ('symbol', 'reverse'), ('func', ('symbol', 'sort'), ('list', ('or', ('symbol', '2'), ('symbol', '3')), ('symbol', 'date')))) 3 2 + $ try 'rs()' + ('func', ('symbol', 'rs'), None) + hg: parse error: invalid number of arguments: 0 + [255] + $ try 'rs(2)' + ('func', ('symbol', 'rs'), ('symbol', '2')) + hg: parse error: invalid number of arguments: 1 + [255] + $ try 'rs(2, data, 7)' + ('func', ('symbol', 'rs'), ('list', ('list', ('symbol', '2'), ('symbol', 'data')), ('symbol', '7'))) + hg: parse error: invalid number of arguments: 3 + [255] + $ try 'rs4(2 or 3, x, x, date)' + ('func', ('symbol', 'rs4'), ('list', ('list', ('list', ('or', ('symbol', '2'), ('symbol', '3')), ('symbol', 'x')), ('symbol', 'x')), ('symbol', 'date'))) + ('func', ('symbol', 'reverse'), ('func', ('symbol', 'sort'), ('list', ('or', ('symbol', '2'), ('symbol', '3')), ('symbol', 'date')))) + 3 + 2 issue2549 - correct optimizations