##// END OF EJS Templates
dirstate: ignore symlinks when fs cannot handle them (issue1888)...
dirstate: ignore symlinks when fs cannot handle them (issue1888) When the filesystem cannot handle the executable bit, we currently ignore it completely when looking for modified files. Similarly, it is impossible to set or clear the bit when the filesystem ignores it. This patch makes Mercurial treat symbolic links the same way. Symlinks are a little different since they manifest themselves as small files containing a filename (the symlink target). On Windows, these files show up as regular files, and on Linux and Mac they show up as real symlinks. Issue1888 presents a case where the symlink files are better ignored from the Windows side. A Linux client creates symlinks in a working copy which is shared over a network between Linux and Windows clients. The Samba server is helpful and defererences the symlink when the Windows client looks at it. This means that Mercurial on the Windows side sees file content instead of a file name in the symlink, and hence flags the link as modified. Ignoring the change would be much more helpful, similarly to how Mercurial does not report any changes when executable bits are ignored in a checkout on Windows. An initial checkout of a symbolic link on a file system that cannot handle symbolic links will still result in a regular file containing the target file name as its content. Sharing such a checkout with a Linux client will not turn the file into a symlink automatically, but 'hg revert' can fix that. After the revert, the Windows client will see the correct file content (provided by the Samba server when it follows the link on the Linux side) and otherwise ignore the change. Running 'hg perfstatus' 10 times gives these results: Before: After: min: 0.544703 min: 0.546549 med: 0.547592 med: 0.548881 avg: 0.549146 avg: 0.548549 max: 0.564112 max: 0.551504 The median time is increased about 0.24%.

File last commit:

r11708:ba65d61f default
r11769:ca6cebd8 stable
Show More
revset.py
572 lines | 16.3 KiB | text/x-python | PythonLexer
Matt Mackall
revset: introduce revset core
r11275 # revset.py - revision set queries for mercurial
#
# Copyright 2010 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
import re
Dirkjan Ochtman
move discovery methods from localrepo into new discovery module
r11301 import parser, util, error, discovery
Matt Mackall
revset: introduce revset core
r11275 import match as _match
Martin Geisler
revset: all your error messages are belong to _
r11383 from i18n import _
Matt Mackall
revset: introduce revset core
r11275
elements = {
"(": (20, ("group", 1, ")"), ("func", 1, ")")),
"-": (19, ("negate", 19), ("minus", 19)),
Matt Mackall
revset: add support for prefix and suffix versions of : and ::
r11278 "::": (17, ("dagrangepre", 17), ("dagrange", 17),
("dagrangepost", 17)),
"..": (17, ("dagrangepre", 17), ("dagrange", 17),
("dagrangepost", 17)),
":": (15, ("rangepre", 15), ("range", 15), ("rangepost", 15)),
Matt Mackall
revset: introduce revset core
r11275 "not": (10, ("not", 10)),
"!": (10, ("not", 10)),
"and": (5, None, ("and", 5)),
"&": (5, None, ("and", 5)),
"or": (4, None, ("or", 4)),
"|": (4, None, ("or", 4)),
"+": (4, None, ("or", 4)),
",": (2, None, ("list", 2)),
")": (0, None, None),
"symbol": (0, ("symbol",), None),
"string": (0, ("string",), None),
"end": (0, None, None),
}
keywords = set(['and', 'or', 'not'])
def tokenize(program):
pos, l = 0, len(program)
while pos < l:
c = program[pos]
if c.isspace(): # skip inter-token whitespace
pass
Matt Mackall
revset: add support for prefix and suffix versions of : and ::
r11278 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
Matt Mackall
revset: raise ParseError exceptions
r11289 yield ('::', None, pos)
Matt Mackall
revset: add support for prefix and suffix versions of : and ::
r11278 pos += 1 # skip ahead
Matt Mackall
revset: introduce revset core
r11275 elif c == '.' and program[pos:pos + 2] == '..': # look ahead carefully
Matt Mackall
revset: raise ParseError exceptions
r11289 yield ('..', None, pos)
Matt Mackall
revset: introduce revset core
r11275 pos += 1 # skip ahead
Matt Mackall
revset: add support for prefix and suffix versions of : and ::
r11278 elif c in "():,-|&+!": # handle simple operators
Matt Mackall
revset: raise ParseError exceptions
r11289 yield (c, None, pos)
Matt Mackall
revset: introduce revset core
r11275 elif c in '"\'': # handle quoted strings
pos += 1
s = pos
while pos < l: # find closing quote
d = program[pos]
if d == '\\': # skip over escaped characters
pos += 2
continue
if d == c:
Matt Mackall
revset: raise ParseError exceptions
r11289 yield ('string', program[s:pos].decode('string-escape'), s)
Matt Mackall
revset: introduce revset core
r11275 break
pos += 1
else:
Martin Geisler
revset: all your error messages are belong to _
r11383 raise error.ParseError(_("unterminated string"), s)
Matt Mackall
revset: allow extended characters in symbols
r11404 elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
Matt Mackall
revset: introduce revset core
r11275 s = pos
pos += 1
while pos < l: # find end of symbol
d = program[pos]
Matt Mackall
revset: allow extended characters in symbols
r11404 if not (d.isalnum() or d in "._" or ord(d) > 127):
Matt Mackall
revset: introduce revset core
r11275 break
if d == '.' and program[pos - 1] == '.': # special case for ..
pos -= 1
break
pos += 1
sym = program[s:pos]
if sym in keywords: # operator keywords
Matt Mackall
revset: raise ParseError exceptions
r11289 yield (sym, None, s)
Matt Mackall
revset: introduce revset core
r11275 else:
Matt Mackall
revset: raise ParseError exceptions
r11289 yield ('symbol', sym, s)
Matt Mackall
revset: introduce revset core
r11275 pos -= 1
else:
Martin Geisler
revset: all your error messages are belong to _
r11383 raise error.ParseError(_("syntax error"), pos)
Matt Mackall
revset: introduce revset core
r11275 pos += 1
Matt Mackall
revset: raise ParseError exceptions
r11289 yield ('end', None, pos)
Matt Mackall
revset: introduce revset core
r11275
# helpers
def getstring(x, err):
Matt Mackall
revset: fix up contains/getstring when no args passed
r11406 if x and (x[0] == 'string' or x[0] == 'symbol'):
Matt Mackall
revset: introduce revset core
r11275 return x[1]
Matt Mackall
revset: raise ParseError exceptions
r11289 raise error.ParseError(err)
Matt Mackall
revset: introduce revset core
r11275
def getlist(x):
if not x:
return []
if x[0] == 'list':
return getlist(x[1]) + [x[2]]
return [x]
Matt Mackall
revset: improve filter argument handling
r11339 def getargs(x, min, max, err):
Matt Mackall
revset: introduce revset core
r11275 l = getlist(x)
Matt Mackall
revset: improve filter argument handling
r11339 if len(l) < min or len(l) > max:
Matt Mackall
revset: raise ParseError exceptions
r11289 raise error.ParseError(err)
Matt Mackall
revset: introduce revset core
r11275 return l
def getset(repo, subset, x):
if not x:
Martin Geisler
revset: all your error messages are belong to _
r11383 raise error.ParseError(_("missing argument"))
Matt Mackall
revset: introduce revset core
r11275 return methods[x[0]](repo, subset, *x[1:])
# operator methods
def stringset(repo, subset, x):
x = repo[x].rev()
Matt Mackall
revset: fix up tests
r11282 if x == -1 and len(subset) == len(repo):
return [-1]
Matt Mackall
revset: introduce revset core
r11275 if x in subset:
return [x]
return []
def symbolset(repo, subset, x):
if x in symbols:
Martin Geisler
revset: all your error messages are belong to _
r11383 raise error.ParseError(_("can't use %s here") % x)
Matt Mackall
revset: introduce revset core
r11275 return stringset(repo, subset, x)
def rangeset(repo, subset, x, y):
Matt Mackall
revset: deal with empty sets in range endpoints...
r11456 m = getset(repo, subset, x)
if not m:
m = getset(repo, range(len(repo)), x)
n = getset(repo, subset, y)
if not n:
n = getset(repo, range(len(repo)), y)
if not m or not n:
return []
m, n = m[0], n[-1]
Matt Mackall
revset: introduce revset core
r11275 if m < n:
Matt Mackall
revset: deal with empty sets in range endpoints...
r11456 r = range(m, n + 1)
else:
r = range(m, n - 1, -1)
s = set(subset)
return [x for x in r if x in s]
Matt Mackall
revset: introduce revset core
r11275
def andset(repo, subset, x, y):
return getset(repo, getset(repo, subset, x), y)
def orset(repo, subset, x, y):
s = set(getset(repo, subset, x))
s |= set(getset(repo, [r for r in subset if r not in s], y))
return [r for r in subset if r in s]
def notset(repo, subset, x):
s = set(getset(repo, subset, x))
return [r for r in subset if r not in s]
def listset(repo, subset, a, b):
Martin Geisler
revset: all your error messages are belong to _
r11383 raise error.ParseError(_("can't use a list in this context"))
Matt Mackall
revset: introduce revset core
r11275
def func(repo, subset, a, b):
if a[0] == 'symbol' and a[1] in symbols:
return symbols[a[1]](repo, subset, b)
Martin Geisler
revset: all your error messages are belong to _
r11383 raise error.ParseError(_("not a function: %s") % a[1])
Matt Mackall
revset: introduce revset core
r11275
# functions
def p1(repo, subset, x):
ps = set()
cl = repo.changelog
for r in getset(repo, subset, x):
ps.add(cl.parentrevs(r)[0])
return [r for r in subset if r in ps]
def p2(repo, subset, x):
ps = set()
cl = repo.changelog
for r in getset(repo, subset, x):
ps.add(cl.parentrevs(r)[1])
return [r for r in subset if r in ps]
def parents(repo, subset, x):
ps = set()
cl = repo.changelog
for r in getset(repo, subset, x):
ps.update(cl.parentrevs(r))
return [r for r in subset if r in ps]
def maxrev(repo, subset, x):
s = getset(repo, subset, x)
if s:
m = max(s)
if m in subset:
return [m]
return []
def limit(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 l = getargs(x, 2, 2, _("limit wants two arguments"))
Matt Mackall
revset: introduce revset core
r11275 try:
Martin Geisler
revset: all your error messages are belong to _
r11383 lim = int(getstring(l[1], _("limit wants a number")))
Matt Mackall
revset: introduce revset core
r11275 except ValueError:
Martin Geisler
revset: all your error messages are belong to _
r11383 raise error.ParseError(_("limit expects a number"))
Matt Mackall
revset: introduce revset core
r11275 return getset(repo, subset, l[0])[:lim]
def children(repo, subset, x):
cs = set()
cl = repo.changelog
s = set(getset(repo, subset, x))
for r in xrange(0, len(repo)):
for p in cl.parentrevs(r):
if p in s:
cs.add(r)
return [r for r in subset if r in cs]
def branch(repo, subset, x):
s = getset(repo, range(len(repo)), x)
b = set()
for r in s:
b.add(repo[r].branch())
s = set(s)
return [r for r in subset if r in s or repo[r].branch() in b]
def ancestor(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 l = getargs(x, 2, 2, _("ancestor wants two arguments"))
Matt Mackall
revset: fix ancestor subset handling (issue2298)
r11650 r = range(len(repo))
a = getset(repo, r, l[0])
b = getset(repo, r, l[1])
if len(a) != 1 or len(b) != 1:
Martin Geisler
revset: all your error messages are belong to _
r11383 raise error.ParseError(_("ancestor arguments must be single revisions"))
Matt Mackall
revset: fix ancestor subset handling (issue2298)
r11650 an = [repo[a[0]].ancestor(repo[b[0]]).rev()]
return [r for r in an if r in subset]
Matt Mackall
revset: introduce revset core
r11275
def ancestors(repo, subset, x):
args = getset(repo, range(len(repo)), x)
Matt Mackall
revset: deal with empty sets in range endpoints...
r11456 if not args:
return []
Matt Mackall
revset: introduce revset core
r11275 s = set(repo.changelog.ancestors(*args)) | set(args)
return [r for r in subset if r in s]
def descendants(repo, subset, x):
args = getset(repo, range(len(repo)), x)
Matt Mackall
revset: deal with empty sets in range endpoints...
r11456 if not args:
return []
Matt Mackall
revset: introduce revset core
r11275 s = set(repo.changelog.descendants(*args)) | set(args)
return [r for r in subset if r in s]
def follow(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 getargs(x, 0, 0, _("follow takes no arguments"))
Matt Mackall
revset: introduce revset core
r11275 p = repo['.'].rev()
s = set(repo.changelog.ancestors(p)) | set([p])
return [r for r in subset if r in s]
def date(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 ds = getstring(x, _("date wants a string"))
Matt Mackall
revset: introduce revset core
r11275 dm = util.matchdate(ds)
return [r for r in subset if dm(repo[r].date()[0])]
def keyword(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 kw = getstring(x, _("keyword wants a string")).lower()
Matt Mackall
revset: introduce revset core
r11275 l = []
for r in subset:
c = repo[r]
t = " ".join(c.files() + [c.user(), c.description()])
if kw in t.lower():
l.append(r)
return l
def grep(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 gr = re.compile(getstring(x, _("grep wants a string")))
Matt Mackall
revset: introduce revset core
r11275 l = []
for r in subset:
c = repo[r]
for e in c.files() + [c.user(), c.description()]:
if gr.search(e):
l.append(r)
continue
return l
def author(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 n = getstring(x, _("author wants a string")).lower()
Matt Mackall
revset: introduce revset core
r11275 return [r for r in subset if n in repo[r].user().lower()]
def hasfile(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 pat = getstring(x, _("file wants a pattern"))
Matt Mackall
revset: introduce revset core
r11275 m = _match.match(repo.root, repo.getcwd(), [pat])
s = []
for r in subset:
for f in repo[r].files():
if m(f):
s.append(r)
continue
return s
def contains(repo, subset, x):
Matt Mackall
revset: fix up contains/getstring when no args passed
r11406 pat = getstring(x, _("contains wants a pattern"))
Matt Mackall
revset: introduce revset core
r11275 m = _match.match(repo.root, repo.getcwd(), [pat])
s = []
if m.files() == [pat]:
for r in subset:
if pat in repo[r]:
s.append(r)
continue
else:
for r in subset:
for f in repo[r].manifest():
if m(f):
s.append(r)
continue
return s
def checkstatus(repo, subset, pat, field):
m = _match.match(repo.root, repo.getcwd(), [pat])
s = []
fast = (m.files() == [pat])
for r in subset:
c = repo[r]
if fast:
if pat not in c.files():
continue
else:
for f in c.files():
if m(f):
break
else:
continue
files = repo.status(c.p1().node(), c.node())[field]
if fast:
if pat in files:
s.append(r)
continue
else:
for f in files:
if m(f):
s.append(r)
continue
return s
def modifies(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 pat = getstring(x, _("modifies wants a pattern"))
Matt Mackall
revset: introduce revset core
r11275 return checkstatus(repo, subset, pat, 0)
def adds(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 pat = getstring(x, _("adds wants a pattern"))
Matt Mackall
revset: introduce revset core
r11275 return checkstatus(repo, subset, pat, 1)
def removes(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 pat = getstring(x, _("removes wants a pattern"))
Matt Mackall
revset: introduce revset core
r11275 return checkstatus(repo, subset, pat, 2)
def merge(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 getargs(x, 0, 0, _("merge takes no arguments"))
Matt Mackall
revset: introduce revset core
r11275 cl = repo.changelog
return [r for r in subset if cl.parentrevs(r)[1] != -1]
def closed(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 getargs(x, 0, 0, _("closed takes no arguments"))
Georg Brandl
revset: fix call to ctx.extra() in closed()
r11349 return [r for r in subset if repo[r].extra().get('close')]
Matt Mackall
revset: introduce revset core
r11275
def head(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 getargs(x, 0, 0, _("head takes no arguments"))
Matt Mackall
revset: introduce revset core
r11275 hs = set()
for b, ls in repo.branchmap().iteritems():
hs.update(repo[h].rev() for h in ls)
return [r for r in subset if r in hs]
def reverse(repo, subset, x):
l = getset(repo, subset, x)
l.reverse()
return l
def sort(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 l = getargs(x, 1, 2, _("sort wants one or two arguments"))
Matt Mackall
revset: introduce revset core
r11275 keys = "rev"
if len(l) == 2:
Martin Geisler
revset: all your error messages are belong to _
r11383 keys = getstring(l[1], _("sort spec must be a string"))
Matt Mackall
revset: introduce revset core
r11275
s = l[0]
keys = keys.split()
l = []
def invert(s):
return "".join(chr(255 - ord(c)) for c in s)
for r in getset(repo, subset, s):
c = repo[r]
e = []
for k in keys:
if k == 'rev':
e.append(r)
elif k == '-rev':
e.append(-r)
elif k == 'branch':
e.append(c.branch())
elif k == '-branch':
e.append(invert(c.branch()))
elif k == 'desc':
e.append(c.description())
elif k == '-desc':
e.append(invert(c.description()))
elif k in 'user author':
e.append(c.user())
elif k in '-user -author':
e.append(invert(c.user()))
elif k == 'date':
e.append(c.date()[0])
elif k == '-date':
e.append(-c.date()[0])
else:
Martin Geisler
revset: all your error messages are belong to _
r11383 raise error.ParseError(_("unknown sort key %r") % k)
Matt Mackall
revset: introduce revset core
r11275 e.append(r)
l.append(e)
l.sort()
return [e[-1] for e in l]
def getall(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 getargs(x, 0, 0, _("all takes no arguments"))
Matt Mackall
revset: introduce revset core
r11275 return subset
def heads(repo, subset, x):
s = getset(repo, subset, x)
ps = set(parents(repo, subset, x))
return [r for r in s if r not in ps]
def roots(repo, subset, x):
s = getset(repo, subset, x)
cs = set(children(repo, subset, x))
return [r for r in s if r not in cs]
def outgoing(repo, subset, x):
Matt Mackall
revset: delay import of hg to avoid start-up import loops
r11293 import hg # avoid start-up nasties
Martin Geisler
revset: all your error messages are belong to _
r11383 l = getargs(x, 0, 1, _("outgoing wants a repository path"))
Matt Mackall
revset: improve filter argument handling
r11339 dest = l[1:] or ''
Matt Mackall
revset: introduce revset core
r11275 dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
dest, branches = hg.parseurl(dest)
other = hg.repository(hg.remoteui(repo, {}), dest)
repo.ui.pushbuffer()
Dirkjan Ochtman
move discovery methods from localrepo into new discovery module
r11301 o = discovery.findoutgoing(repo, other)
Matt Mackall
revset: introduce revset core
r11275 repo.ui.popbuffer()
cl = repo.changelog
o = set([cl.rev(r) for r in repo.changelog.nodesbetween(o, None)[0]])
return [r for r in subset if r in o]
Matt Mackall
revset: add tagged predicate
r11280 def tagged(repo, subset, x):
Martin Geisler
revset: all your error messages are belong to _
r11383 getargs(x, 0, 0, _("tagged takes no arguments"))
Matt Mackall
revset: add tagged predicate
r11280 cl = repo.changelog
s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
return [r for r in subset if r in s]
Matt Mackall
revset: introduce revset core
r11275 symbols = {
Matt Mackall
revset: sort the predicate list
r11284 "adds": adds,
"all": getall,
Matt Mackall
revset: introduce revset core
r11275 "ancestor": ancestor,
"ancestors": ancestors,
Matt Mackall
revset: sort the predicate list
r11284 "author": author,
Matt Mackall
revset: introduce revset core
r11275 "branch": branch,
Matt Mackall
revset: sort the predicate list
r11284 "children": children,
"closed": closed,
"contains": contains,
"date": date,
"descendants": descendants,
"file": hasfile,
"follow": follow,
"grep": grep,
"head": head,
"heads": heads,
Matt Mackall
revset: introduce revset core
r11275 "keyword": keyword,
Matt Mackall
revset: sort the predicate list
r11284 "limit": limit,
"max": maxrev,
"merge": merge,
"modifies": modifies,
"outgoing": outgoing,
Matt Mackall
revset: introduce revset core
r11275 "p1": p1,
"p2": p2,
"parents": parents,
Matt Mackall
revset: sort the predicate list
r11284 "removes": removes,
"reverse": reverse,
Matt Mackall
revset: introduce revset core
r11275 "roots": roots,
Matt Mackall
revset: sort the predicate list
r11284 "sort": sort,
Matt Mackall
revset: add tagged predicate
r11280 "tagged": tagged,
Matt Mackall
revset: sort the predicate list
r11284 "user": author,
Matt Mackall
revset: introduce revset core
r11275 }
methods = {
"range": rangeset,
"string": stringset,
"symbol": symbolset,
"and": andset,
"or": orset,
"not": notset,
"list": listset,
"func": func,
}
Matt Mackall
revset: optimize the parse tree directly...
r11279 def optimize(x, small):
if x == None:
return 0, x
Matt Mackall
revset: introduce revset core
r11275 smallbonus = 1
if small:
smallbonus = .5
op = x[0]
Matt Mackall
revset: fix - handling in the optimizer
r11283 if op == 'minus':
Matt Mackall
revset: optimize the parse tree directly...
r11279 return optimize(('and', x[1], ('not', x[2])), small)
elif op == 'dagrange':
return optimize(('and', ('func', ('symbol', 'descendants'), x[1]),
('func', ('symbol', 'ancestors'), x[2])), small)
elif op == 'dagrangepre':
return optimize(('func', ('symbol', 'ancestors'), x[1]), small)
elif op == 'dagrangepost':
return optimize(('func', ('symbol', 'descendants'), x[1]), small)
elif op == 'rangepre':
return optimize(('range', ('string', '0'), x[1]), small)
elif op == 'rangepost':
return optimize(('range', x[1], ('string', 'tip')), small)
Matt Mackall
revset: make negate work for sort specs
r11467 elif op == 'negate':
return optimize(('string',
'-' + getstring(x[1], _("can't negate that"))), small)
Matt Mackall
revset: optimize the parse tree directly...
r11279 elif op in 'string symbol negate':
return smallbonus, x # single revisions are small
Matt Mackall
revset: introduce revset core
r11275 elif op == 'and' or op == 'dagrange':
Matt Mackall
revset: optimize the parse tree directly...
r11279 wa, ta = optimize(x[1], True)
wb, tb = optimize(x[2], True)
w = min(wa, wb)
if wa > wb:
return w, (op, tb, ta)
return w, (op, ta, tb)
elif op == 'or':
wa, ta = optimize(x[1], False)
wb, tb = optimize(x[2], False)
if wb < wa:
wb, wa = wa, wb
return max(wa, wb), (op, ta, tb)
Matt Mackall
revset: introduce revset core
r11275 elif op == 'not':
Matt Mackall
revset: optimize the parse tree directly...
r11279 o = optimize(x[1], not small)
return o[0], (op, o[1])
Matt Mackall
revset: introduce revset core
r11275 elif op == 'group':
Matt Mackall
revset: optimize the parse tree directly...
r11279 return optimize(x[1], small)
elif op in 'range list':
wa, ta = optimize(x[1], small)
wb, tb = optimize(x[2], small)
return wa + wb, (op, ta, tb)
Matt Mackall
revset: introduce revset core
r11275 elif op == 'func':
Martin Geisler
revset: all your error messages are belong to _
r11383 f = getstring(x[1], _("not a symbol"))
Matt Mackall
revset: optimize the parse tree directly...
r11279 wa, ta = optimize(x[2], small)
Matt Mackall
revset: introduce revset core
r11275 if f in "grep date user author keyword branch file":
Matt Mackall
revset: optimize the parse tree directly...
r11279 w = 10 # slow
elif f in "modifies adds removes outgoing":
w = 30 # slower
Matt Mackall
revset: introduce revset core
r11275 elif f == "contains":
Matt Mackall
revset: optimize the parse tree directly...
r11279 w = 100 # very slow
Matt Mackall
revset: introduce revset core
r11275 elif f == "ancestor":
Matt Mackall
revset: optimize the parse tree directly...
r11279 w = 1 * smallbonus
Matt Mackall
revset: introduce revset core
r11275 elif f == "reverse limit":
Matt Mackall
revset: optimize the parse tree directly...
r11279 w = 0
Matt Mackall
revset: introduce revset core
r11275 elif f in "sort":
Matt Mackall
revset: optimize the parse tree directly...
r11279 w = 10 # assume most sorts look at changelog
Matt Mackall
revset: introduce revset core
r11275 else:
Matt Mackall
revset: optimize the parse tree directly...
r11279 w = 1
return w + wa, (op, x[1], ta)
return 1, x
Matt Mackall
revset: introduce revset core
r11275
parse = parser.parser(tokenize, elements).parse
def match(spec):
Matt Mackall
revset: nicer exception for empty queries
r11385 if not spec:
raise error.ParseError(_("empty query"))
Matt Mackall
revset: introduce revset core
r11275 tree = parse(spec)
Matt Mackall
revset: optimize the parse tree directly...
r11279 weight, tree = optimize(tree, True)
Matt Mackall
revset: introduce revset core
r11275 def mfunc(repo, subset):
return getset(repo, subset, tree)
return mfunc