mercurial/revset.py
changeset 23725 6a81f88758aa
parent 23720 8ec03e0ef51a
child 23726 d944492445fa
equal deleted inserted replaced
23723:fd62b3e750af 23725:6a81f88758aa
  2035 
  2035 
  2036 class revsetalias(object):
  2036 class revsetalias(object):
  2037     funcre = re.compile('^([^(]+)\(([^)]+)\)$')
  2037     funcre = re.compile('^([^(]+)\(([^)]+)\)$')
  2038     args = None
  2038     args = None
  2039 
  2039 
       
  2040     # error message at parsing, or None
       
  2041     error = None
       
  2042     # whether own `error` information is already shown or not.
       
  2043     # this avoids showing same warning multiple times at each `findaliases`.
       
  2044     warned = False
       
  2045 
  2040     def __init__(self, name, value):
  2046     def __init__(self, name, value):
  2041         '''Aliases like:
  2047         '''Aliases like:
  2042 
  2048 
  2043         h = heads(default)
  2049         h = heads(default)
  2044         b($1) = ancestors($1) - ancestors(default)
  2050         b($1) = ancestors($1) - ancestors(default)
  2054                 value = value.replace(arg, '_aliasarg(%r)' % (arg,))
  2060                 value = value.replace(arg, '_aliasarg(%r)' % (arg,))
  2055         else:
  2061         else:
  2056             self.name = name
  2062             self.name = name
  2057             self.tree = ('symbol', name)
  2063             self.tree = ('symbol', name)
  2058 
  2064 
  2059         self.replacement, pos = parse(value)
  2065         try:
  2060         if pos != len(value):
  2066             self.replacement, pos = parse(value)
  2061             raise error.ParseError(_('invalid token'), pos)
  2067             if pos != len(value):
  2062         # Check for placeholder injection
  2068                 raise error.ParseError(_('invalid token'), pos)
  2063         _checkaliasarg(self.replacement, self.args)
  2069             # Check for placeholder injection
       
  2070             _checkaliasarg(self.replacement, self.args)
       
  2071         except error.ParseError, inst:
       
  2072             if len(inst.args) > 1:
       
  2073                 self.error = _('at %s: %s') % (inst.args[1], inst.args[0])
       
  2074             else:
       
  2075                 self.error = inst.args[0]
  2064 
  2076 
  2065 def _getalias(aliases, tree):
  2077 def _getalias(aliases, tree):
  2066     """If tree looks like an unexpanded alias, return it. Return None
  2078     """If tree looks like an unexpanded alias, return it. Return None
  2067     otherwise.
  2079     otherwise.
  2068     """
  2080     """
  2100     if not isinstance(tree, tuple):
  2112     if not isinstance(tree, tuple):
  2101         # Do not expand raw strings
  2113         # Do not expand raw strings
  2102         return tree
  2114         return tree
  2103     alias = _getalias(aliases, tree)
  2115     alias = _getalias(aliases, tree)
  2104     if alias is not None:
  2116     if alias is not None:
       
  2117         if alias.error:
       
  2118             raise util.Abort(_('failed to parse revset alias "%s": %s') %
       
  2119                              (alias.name, alias.error))
  2105         if alias in expanding:
  2120         if alias in expanding:
  2106             raise error.ParseError(_('infinite expansion of revset alias "%s" '
  2121             raise error.ParseError(_('infinite expansion of revset alias "%s" '
  2107                                      'detected') % alias.name)
  2122                                      'detected') % alias.name)
  2108         expanding.append(alias)
  2123         expanding.append(alias)
  2109         if alias.name not in cache:
  2124         if alias.name not in cache:
  2121     else:
  2136     else:
  2122         result = tuple(_expandaliases(aliases, t, expanding, cache)
  2137         result = tuple(_expandaliases(aliases, t, expanding, cache)
  2123                        for t in tree)
  2138                        for t in tree)
  2124     return result
  2139     return result
  2125 
  2140 
  2126 def findaliases(ui, tree):
  2141 def findaliases(ui, tree, showwarning=None):
  2127     _checkaliasarg(tree)
  2142     _checkaliasarg(tree)
  2128     aliases = {}
  2143     aliases = {}
  2129     for k, v in ui.configitems('revsetalias'):
  2144     for k, v in ui.configitems('revsetalias'):
  2130         alias = revsetalias(k, v)
  2145         alias = revsetalias(k, v)
  2131         aliases[alias.name] = alias
  2146         aliases[alias.name] = alias
  2132     return _expandaliases(aliases, tree, [], {})
  2147     tree = _expandaliases(aliases, tree, [], {})
       
  2148     if showwarning:
       
  2149         # warn about problematic (but not referred) aliases
       
  2150         for name, alias in sorted(aliases.iteritems()):
       
  2151             if alias.error and not alias.warned:
       
  2152                 msg = _('failed to parse revset alias "%s": %s'
       
  2153                         ) % (name, alias.error)
       
  2154                 showwarning(_('warning: %s\n') % (msg))
       
  2155                 alias.warned = True
       
  2156     return tree
  2133 
  2157 
  2134 def parse(spec, lookup=None):
  2158 def parse(spec, lookup=None):
  2135     p = parser.parser(tokenize, elements)
  2159     p = parser.parser(tokenize, elements)
  2136     return p.parse(spec, lookup=lookup)
  2160     return p.parse(spec, lookup=lookup)
  2137 
  2161 
  2143         lookup = repo.__contains__
  2167         lookup = repo.__contains__
  2144     tree, pos = parse(spec, lookup)
  2168     tree, pos = parse(spec, lookup)
  2145     if (pos != len(spec)):
  2169     if (pos != len(spec)):
  2146         raise error.ParseError(_("invalid token"), pos)
  2170         raise error.ParseError(_("invalid token"), pos)
  2147     if ui:
  2171     if ui:
  2148         tree = findaliases(ui, tree)
  2172         tree = findaliases(ui, tree, showwarning=ui.warn)
  2149     weight, tree = optimize(tree, True)
  2173     weight, tree = optimize(tree, True)
  2150     def mfunc(repo, subset):
  2174     def mfunc(repo, subset):
  2151         if util.safehasattr(subset, 'isascending'):
  2175         if util.safehasattr(subset, 'isascending'):
  2152             result = getset(repo, subset, tree)
  2176             result = getset(repo, subset, tree)
  2153         else:
  2177         else: