comparison mercurial/revset.py @ 16838:d37d221334be

revset: cache alias expansions Caching has no performance effect on the revset aliases which triggered the recent recursive evaluation bug. I wrote it not to feel bad about expanding several times the same complicated expression.
author Patrick Mezard <patrick@mezard.eu>
date Thu, 24 May 2012 13:05:06 +0200
parents cafd8a8fb713
children eeb464ed7275
comparison
equal deleted inserted replaced
16837:1b9d54c00d50 16838:d37d221334be
1479 arg = _getaliasarg(tree) 1479 arg = _getaliasarg(tree)
1480 if arg is not None: 1480 if arg is not None:
1481 return args[arg] 1481 return args[arg]
1482 return tuple(_expandargs(t, args) for t in tree) 1482 return tuple(_expandargs(t, args) for t in tree)
1483 1483
1484 def _expandaliases(aliases, tree, expanding): 1484 def _expandaliases(aliases, tree, expanding, cache):
1485 """Expand aliases in tree, recursively. 1485 """Expand aliases in tree, recursively.
1486 1486
1487 'aliases' is a dictionary mapping user defined aliases to 1487 'aliases' is a dictionary mapping user defined aliases to
1488 revsetalias objects. 1488 revsetalias objects.
1489 """ 1489 """
1494 if alias is not None: 1494 if alias is not None:
1495 if alias in expanding: 1495 if alias in expanding:
1496 raise error.ParseError(_('infinite expansion of revset alias "%s" ' 1496 raise error.ParseError(_('infinite expansion of revset alias "%s" '
1497 'detected') % alias.name) 1497 'detected') % alias.name)
1498 expanding.append(alias) 1498 expanding.append(alias)
1499 result = _expandaliases(aliases, alias.replacement, expanding) 1499 if alias.name not in cache:
1500 cache[alias.name] = _expandaliases(aliases, alias.replacement,
1501 expanding, cache)
1502 result = cache[alias.name]
1500 expanding.pop() 1503 expanding.pop()
1501 if alias.args is not None: 1504 if alias.args is not None:
1502 l = getlist(tree[2]) 1505 l = getlist(tree[2])
1503 if len(l) != len(alias.args): 1506 if len(l) != len(alias.args):
1504 raise error.ParseError( 1507 raise error.ParseError(
1505 _('invalid number of arguments: %s') % len(l)) 1508 _('invalid number of arguments: %s') % len(l))
1506 l = [_expandaliases(aliases, a, []) for a in l] 1509 l = [_expandaliases(aliases, a, [], cache) for a in l]
1507 result = _expandargs(result, dict(zip(alias.args, l))) 1510 result = _expandargs(result, dict(zip(alias.args, l)))
1508 else: 1511 else:
1509 result = tuple(_expandaliases(aliases, t, expanding) 1512 result = tuple(_expandaliases(aliases, t, expanding, cache)
1510 for t in tree) 1513 for t in tree)
1511 return result 1514 return result
1512 1515
1513 def findaliases(ui, tree): 1516 def findaliases(ui, tree):
1514 _checkaliasarg(tree) 1517 _checkaliasarg(tree)
1515 aliases = {} 1518 aliases = {}
1516 for k, v in ui.configitems('revsetalias'): 1519 for k, v in ui.configitems('revsetalias'):
1517 alias = revsetalias(k, v) 1520 alias = revsetalias(k, v)
1518 aliases[alias.name] = alias 1521 aliases[alias.name] = alias
1519 return _expandaliases(aliases, tree, []) 1522 return _expandaliases(aliases, tree, [], {})
1520 1523
1521 parse = parser.parser(tokenize, elements).parse 1524 parse = parser.parser(tokenize, elements).parse
1522 1525
1523 def match(ui, spec): 1526 def match(ui, spec):
1524 if not spec: 1527 if not spec: