Mercurial > hg
annotate mercurial/fileset.py @ 14605:9f1139cf5c76
hg: rearrange peer scheme lookup
There is now only peer scheme lookup. Repository lookup goes through
peer scheme lookup. When peer and repo types are finally separated,
repo lookup will use peer.local() to get a repository object.
The underbar is dropped so that extensions can patch the table.
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 13 Jun 2011 14:53:23 -0500 |
parents | 68db17047637 |
children | b0566467c492 |
rev | line source |
---|---|
14511
30506b894359
filesets: introduce basic fileset expression parser
Matt Mackall <mpm@selenic.com>
parents:
14509
diff
changeset
|
1 # fileset.py - file set queries for mercurial |
11275 | 2 # |
3 # Copyright 2010 Matt Mackall <mpm@selenic.com> | |
4 # | |
5 # This software may be used and distributed according to the terms of the | |
6 # GNU General Public License version 2 or any later version. | |
7 | |
14554 | 8 import parser, error |
13593
cc4721ed7a2a
help: extract items doc generation function
Patrick Mezard <pmezard@gmail.com>
parents:
13506
diff
changeset
|
9 from i18n import _ |
11275 | 10 |
11 elements = { | |
12 "(": (20, ("group", 1, ")"), ("func", 1, ")")), | |
12616
e797fdf91df4
revset: lower precedence of minus infix (issue2361)
Matt Mackall <mpm@selenic.com>
parents:
12615
diff
changeset
|
13 "-": (5, ("negate", 19), ("minus", 5)), |
11275 | 14 "not": (10, ("not", 10)), |
15 "!": (10, ("not", 10)), | |
16 "and": (5, None, ("and", 5)), | |
17 "&": (5, None, ("and", 5)), | |
18 "or": (4, None, ("or", 4)), | |
19 "|": (4, None, ("or", 4)), | |
20 "+": (4, None, ("or", 4)), | |
21 ",": (2, None, ("list", 2)), | |
22 ")": (0, None, None), | |
23 "symbol": (0, ("symbol",), None), | |
24 "string": (0, ("string",), None), | |
25 "end": (0, None, None), | |
26 } | |
27 | |
28 keywords = set(['and', 'or', 'not']) | |
29 | |
14551
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
30 globchars = ".*{}[]?/\\" |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
31 |
11275 | 32 def tokenize(program): |
33 pos, l = 0, len(program) | |
34 while pos < l: | |
35 c = program[pos] | |
36 if c.isspace(): # skip inter-token whitespace | |
37 pass | |
14511
30506b894359
filesets: introduce basic fileset expression parser
Matt Mackall <mpm@selenic.com>
parents:
14509
diff
changeset
|
38 elif c in "(),-|&+!": # handle simple operators |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
39 yield (c, None, pos) |
12408
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
40 elif (c in '"\'' or c == 'r' and |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
41 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
42 if c == 'r': |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
43 pos += 1 |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
44 c = program[pos] |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
45 decode = lambda x: x |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
46 else: |
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
47 decode = lambda x: x.decode('string-escape') |
11275 | 48 pos += 1 |
49 s = pos | |
50 while pos < l: # find closing quote | |
51 d = program[pos] | |
52 if d == '\\': # skip over escaped characters | |
53 pos += 2 | |
54 continue | |
55 if d == c: | |
12408
78a97859b90d
revset: support raw string literals
Brodie Rao <brodie@bitheap.org>
parents:
12401
diff
changeset
|
56 yield ('string', decode(program[s:pos]), s) |
11275 | 57 break |
58 pos += 1 | |
59 else: | |
11383
de544774ebea
revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents:
11349
diff
changeset
|
60 raise error.ParseError(_("unterminated string"), s) |
14551
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
61 elif c.isalnum() or c in globchars or ord(c) > 127: |
14513 | 62 # gather up a symbol/keyword |
11275 | 63 s = pos |
64 pos += 1 | |
65 while pos < l: # find end of symbol | |
66 d = program[pos] | |
14551
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
67 if not (d.isalnum() or d in globchars or ord(d) > 127): |
11275 | 68 break |
69 pos += 1 | |
70 sym = program[s:pos] | |
71 if sym in keywords: # operator keywords | |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
72 yield (sym, None, s) |
11275 | 73 else: |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
74 yield ('symbol', sym, s) |
11275 | 75 pos -= 1 |
76 else: | |
11383
de544774ebea
revset: all your error messages are belong to _
Martin Geisler <mg@lazybytes.net>
parents:
11349
diff
changeset
|
77 raise error.ParseError(_("syntax error"), pos) |
11275 | 78 pos += 1 |
11289
4215ce511134
revset: raise ParseError exceptions
Matt Mackall <mpm@selenic.com>
parents:
11284
diff
changeset
|
79 yield ('end', None, pos) |
11275 | 80 |
81 parse = parser.parser(tokenize, elements).parse | |
82 | |
14551
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
83 def getstring(x, err): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
84 if x and (x[0] == 'string' or x[0] == 'symbol'): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
85 return x[1] |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
86 raise error.ParseError(err) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
87 |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
88 def getset(mctx, x): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
89 if not x: |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
90 raise error.ParseError(_("missing argument")) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
91 return methods[x[0]](mctx, *x[1:]) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
92 |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
93 def stringset(mctx, x): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
94 m = mctx.matcher([x]) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
95 return [f for f in mctx.subset if m(f)] |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
96 |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
97 def andset(mctx, x, y): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
98 return getset(mctx.narrow(getset(mctx, x)), y) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
99 |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
100 def orset(mctx, x, y): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
101 # needs optimizing |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
102 xl = getset(mctx, x) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
103 yl = getset(mctx, y) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
104 return xl + [f for f in yl if f not in xl] |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
105 |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
106 def notset(mctx, x): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
107 s = set(getset(mctx, x)) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
108 return [r for r in mctx.subset if r not in s] |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
109 |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
110 def listset(mctx, a, b): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
111 raise error.ParseError(_("can't use a list in this context")) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
112 |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
113 methods = { |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
114 'string': stringset, |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
115 'symbol': stringset, |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
116 'and': andset, |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
117 'or': orset, |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
118 'list': listset, |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
119 'group': getset, |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
120 'not': notset |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
121 } |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
122 |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
123 class matchctx(object): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
124 def __init__(self, ctx, matchfn, subset=None): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
125 self.ctx = ctx |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
126 self.matchfn = matchfn |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
127 self.subset = subset |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
128 if subset is None: |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
129 self.subset = ctx.walk(matchfn([])) # optimize this later |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
130 def matcher(self, pattern): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
131 return self.matchfn(pattern) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
132 def filter(self, files): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
133 return [f for f in files if f in self.subset] |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
134 def narrow(self, files): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
135 return matchctx(self.ctx, self.matchfn, |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
136 self.filter(files)) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
137 |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
138 def getfileset(ctx, matchfn, expr): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
139 tree, pos = parse(expr) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
140 if (pos != len(expr)): |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
141 raise error.ParseError("invalid token", pos) |
68d814a3cefd
fileset: basic pattern and boolean support
Matt Mackall <mpm@selenic.com>
parents:
14513
diff
changeset
|
142 return getset(matchctx(ctx, matchfn), tree) |