##// END OF EJS Templates
fileset: add missing whitespace around operator
Thomas Arendsen Hein -
r14690:15faf0e6 stable
parent child Browse files
Show More
@@ -1,426 +1,426 b''
1 # fileset.py - file set queries for mercurial
1 # fileset.py - file set queries for mercurial
2 #
2 #
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
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.
6 # GNU General Public License version 2 or any later version.
7
7
8 import parser, error, util, merge, re
8 import parser, error, util, merge, re
9 from i18n import _
9 from i18n import _
10
10
11 elements = {
11 elements = {
12 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
12 "(": (20, ("group", 1, ")"), ("func", 1, ")")),
13 "-": (5, ("negate", 19), ("minus", 5)),
13 "-": (5, ("negate", 19), ("minus", 5)),
14 "not": (10, ("not", 10)),
14 "not": (10, ("not", 10)),
15 "!": (10, ("not", 10)),
15 "!": (10, ("not", 10)),
16 "and": (5, None, ("and", 5)),
16 "and": (5, None, ("and", 5)),
17 "&": (5, None, ("and", 5)),
17 "&": (5, None, ("and", 5)),
18 "or": (4, None, ("or", 4)),
18 "or": (4, None, ("or", 4)),
19 "|": (4, None, ("or", 4)),
19 "|": (4, None, ("or", 4)),
20 "+": (4, None, ("or", 4)),
20 "+": (4, None, ("or", 4)),
21 ",": (2, None, ("list", 2)),
21 ",": (2, None, ("list", 2)),
22 ")": (0, None, None),
22 ")": (0, None, None),
23 "symbol": (0, ("symbol",), None),
23 "symbol": (0, ("symbol",), None),
24 "string": (0, ("string",), None),
24 "string": (0, ("string",), None),
25 "end": (0, None, None),
25 "end": (0, None, None),
26 }
26 }
27
27
28 keywords = set(['and', 'or', 'not'])
28 keywords = set(['and', 'or', 'not'])
29
29
30 globchars = ".*{}[]?/\\"
30 globchars = ".*{}[]?/\\"
31
31
32 def tokenize(program):
32 def tokenize(program):
33 pos, l = 0, len(program)
33 pos, l = 0, len(program)
34 while pos < l:
34 while pos < l:
35 c = program[pos]
35 c = program[pos]
36 if c.isspace(): # skip inter-token whitespace
36 if c.isspace(): # skip inter-token whitespace
37 pass
37 pass
38 elif c in "(),-|&+!": # handle simple operators
38 elif c in "(),-|&+!": # handle simple operators
39 yield (c, None, pos)
39 yield (c, None, pos)
40 elif (c in '"\'' or c == 'r' and
40 elif (c in '"\'' or c == 'r' and
41 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
41 program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
42 if c == 'r':
42 if c == 'r':
43 pos += 1
43 pos += 1
44 c = program[pos]
44 c = program[pos]
45 decode = lambda x: x
45 decode = lambda x: x
46 else:
46 else:
47 decode = lambda x: x.decode('string-escape')
47 decode = lambda x: x.decode('string-escape')
48 pos += 1
48 pos += 1
49 s = pos
49 s = pos
50 while pos < l: # find closing quote
50 while pos < l: # find closing quote
51 d = program[pos]
51 d = program[pos]
52 if d == '\\': # skip over escaped characters
52 if d == '\\': # skip over escaped characters
53 pos += 2
53 pos += 2
54 continue
54 continue
55 if d == c:
55 if d == c:
56 yield ('string', decode(program[s:pos]), s)
56 yield ('string', decode(program[s:pos]), s)
57 break
57 break
58 pos += 1
58 pos += 1
59 else:
59 else:
60 raise error.ParseError(_("unterminated string"), s)
60 raise error.ParseError(_("unterminated string"), s)
61 elif c.isalnum() or c in globchars or ord(c) > 127:
61 elif c.isalnum() or c in globchars or ord(c) > 127:
62 # gather up a symbol/keyword
62 # gather up a symbol/keyword
63 s = pos
63 s = pos
64 pos += 1
64 pos += 1
65 while pos < l: # find end of symbol
65 while pos < l: # find end of symbol
66 d = program[pos]
66 d = program[pos]
67 if not (d.isalnum() or d in globchars or ord(d) > 127):
67 if not (d.isalnum() or d in globchars or ord(d) > 127):
68 break
68 break
69 pos += 1
69 pos += 1
70 sym = program[s:pos]
70 sym = program[s:pos]
71 if sym in keywords: # operator keywords
71 if sym in keywords: # operator keywords
72 yield (sym, None, s)
72 yield (sym, None, s)
73 else:
73 else:
74 yield ('symbol', sym, s)
74 yield ('symbol', sym, s)
75 pos -= 1
75 pos -= 1
76 else:
76 else:
77 raise error.ParseError(_("syntax error"), pos)
77 raise error.ParseError(_("syntax error"), pos)
78 pos += 1
78 pos += 1
79 yield ('end', None, pos)
79 yield ('end', None, pos)
80
80
81 parse = parser.parser(tokenize, elements).parse
81 parse = parser.parser(tokenize, elements).parse
82
82
83 def getstring(x, err):
83 def getstring(x, err):
84 if x and (x[0] == 'string' or x[0] == 'symbol'):
84 if x and (x[0] == 'string' or x[0] == 'symbol'):
85 return x[1]
85 return x[1]
86 raise error.ParseError(err)
86 raise error.ParseError(err)
87
87
88 def getset(mctx, x):
88 def getset(mctx, x):
89 if not x:
89 if not x:
90 raise error.ParseError(_("missing argument"))
90 raise error.ParseError(_("missing argument"))
91 return methods[x[0]](mctx, *x[1:])
91 return methods[x[0]](mctx, *x[1:])
92
92
93 def stringset(mctx, x):
93 def stringset(mctx, x):
94 m = mctx.matcher([x])
94 m = mctx.matcher([x])
95 return [f for f in mctx.subset if m(f)]
95 return [f for f in mctx.subset if m(f)]
96
96
97 def andset(mctx, x, y):
97 def andset(mctx, x, y):
98 return getset(mctx.narrow(getset(mctx, x)), y)
98 return getset(mctx.narrow(getset(mctx, x)), y)
99
99
100 def orset(mctx, x, y):
100 def orset(mctx, x, y):
101 # needs optimizing
101 # needs optimizing
102 xl = getset(mctx, x)
102 xl = getset(mctx, x)
103 yl = getset(mctx, y)
103 yl = getset(mctx, y)
104 return xl + [f for f in yl if f not in xl]
104 return xl + [f for f in yl if f not in xl]
105
105
106 def notset(mctx, x):
106 def notset(mctx, x):
107 s = set(getset(mctx, x))
107 s = set(getset(mctx, x))
108 return [r for r in mctx.subset if r not in s]
108 return [r for r in mctx.subset if r not in s]
109
109
110 def listset(mctx, a, b):
110 def listset(mctx, a, b):
111 raise error.ParseError(_("can't use a list in this context"))
111 raise error.ParseError(_("can't use a list in this context"))
112
112
113 def modified(mctx, x):
113 def modified(mctx, x):
114 """``modified()``
114 """``modified()``
115 File that is modified according to status.
115 File that is modified according to status.
116 """
116 """
117 getargs(x, 0, 0, _("modified takes no arguments"))
117 getargs(x, 0, 0, _("modified takes no arguments"))
118 s = mctx.status()[0]
118 s = mctx.status()[0]
119 return [f for f in mctx.subset if f in s]
119 return [f for f in mctx.subset if f in s]
120
120
121 def added(mctx, x):
121 def added(mctx, x):
122 """``added()``
122 """``added()``
123 File that is added according to status.
123 File that is added according to status.
124 """
124 """
125 getargs(x, 0, 0, _("added takes no arguments"))
125 getargs(x, 0, 0, _("added takes no arguments"))
126 s = mctx.status()[1]
126 s = mctx.status()[1]
127 return [f for f in mctx.subset if f in s]
127 return [f for f in mctx.subset if f in s]
128
128
129 def removed(mctx, x):
129 def removed(mctx, x):
130 """``removed()``
130 """``removed()``
131 File that is removed according to status.
131 File that is removed according to status.
132 """
132 """
133 getargs(x, 0, 0, _("removed takes no arguments"))
133 getargs(x, 0, 0, _("removed takes no arguments"))
134 s = mctx.status()[2]
134 s = mctx.status()[2]
135 return [f for f in mctx.subset if f in s]
135 return [f for f in mctx.subset if f in s]
136
136
137 def deleted(mctx, x):
137 def deleted(mctx, x):
138 """``deleted()``
138 """``deleted()``
139 File that is deleted according to status.
139 File that is deleted according to status.
140 """
140 """
141 getargs(x, 0, 0, _("deleted takes no arguments"))
141 getargs(x, 0, 0, _("deleted takes no arguments"))
142 s = mctx.status()[3]
142 s = mctx.status()[3]
143 return [f for f in mctx.subset if f in s]
143 return [f for f in mctx.subset if f in s]
144
144
145 def unknown(mctx, x):
145 def unknown(mctx, x):
146 """``unknown()``
146 """``unknown()``
147 File that is unknown according to status. These files will only be
147 File that is unknown according to status. These files will only be
148 considered if this predicate is used.
148 considered if this predicate is used.
149 """
149 """
150 getargs(x, 0, 0, _("unknown takes no arguments"))
150 getargs(x, 0, 0, _("unknown takes no arguments"))
151 s = mctx.status()[4]
151 s = mctx.status()[4]
152 return [f for f in mctx.subset if f in s]
152 return [f for f in mctx.subset if f in s]
153
153
154 def ignored(mctx, x):
154 def ignored(mctx, x):
155 """``ignored()``
155 """``ignored()``
156 File that is ignored according to status. These files will only be
156 File that is ignored according to status. These files will only be
157 considered if this predicate is used.
157 considered if this predicate is used.
158 """
158 """
159 getargs(x, 0, 0, _("ignored takes no arguments"))
159 getargs(x, 0, 0, _("ignored takes no arguments"))
160 s = mctx.status()[5]
160 s = mctx.status()[5]
161 return [f for f in mctx.subset if f in s]
161 return [f for f in mctx.subset if f in s]
162
162
163 def clean(mctx, x):
163 def clean(mctx, x):
164 """``clean()``
164 """``clean()``
165 File that is clean according to status.
165 File that is clean according to status.
166 """
166 """
167 getargs(x, 0, 0, _("clean takes no arguments"))
167 getargs(x, 0, 0, _("clean takes no arguments"))
168 s = mctx.status()[6]
168 s = mctx.status()[6]
169 return [f for f in mctx.subset if f in s]
169 return [f for f in mctx.subset if f in s]
170
170
171 def func(mctx, a, b):
171 def func(mctx, a, b):
172 if a[0] == 'symbol' and a[1] in symbols:
172 if a[0] == 'symbol' and a[1] in symbols:
173 return symbols[a[1]](mctx, b)
173 return symbols[a[1]](mctx, b)
174 raise error.ParseError(_("not a function: %s") % a[1])
174 raise error.ParseError(_("not a function: %s") % a[1])
175
175
176 def getlist(x):
176 def getlist(x):
177 if not x:
177 if not x:
178 return []
178 return []
179 if x[0] == 'list':
179 if x[0] == 'list':
180 return getlist(x[1]) + [x[2]]
180 return getlist(x[1]) + [x[2]]
181 return [x]
181 return [x]
182
182
183 def getargs(x, min, max, err):
183 def getargs(x, min, max, err):
184 l = getlist(x)
184 l = getlist(x)
185 if len(l) < min or len(l) > max:
185 if len(l) < min or len(l) > max:
186 raise error.ParseError(err)
186 raise error.ParseError(err)
187 return l
187 return l
188
188
189 def binary(mctx, x):
189 def binary(mctx, x):
190 """``binary()``
190 """``binary()``
191 File that appears to be binary (contails NUL bytes).
191 File that appears to be binary (contails NUL bytes).
192 """
192 """
193 getargs(x, 0, 0, _("binary takes no arguments"))
193 getargs(x, 0, 0, _("binary takes no arguments"))
194 return [f for f in mctx.subset if util.binary(mctx.ctx[f].data())]
194 return [f for f in mctx.subset if util.binary(mctx.ctx[f].data())]
195
195
196 def exec_(mctx, x):
196 def exec_(mctx, x):
197 """``exec()``
197 """``exec()``
198 File that is marked as executable.
198 File that is marked as executable.
199 """
199 """
200 getargs(x, 0, 0, _("exec takes no arguments"))
200 getargs(x, 0, 0, _("exec takes no arguments"))
201 return [f for f in mctx.subset if mctx.ctx.flags(f) == 'x']
201 return [f for f in mctx.subset if mctx.ctx.flags(f) == 'x']
202
202
203 def symlink(mctx, x):
203 def symlink(mctx, x):
204 """``symlink()``
204 """``symlink()``
205 File that is marked as a symlink.
205 File that is marked as a symlink.
206 """
206 """
207 getargs(x, 0, 0, _("symlink takes no arguments"))
207 getargs(x, 0, 0, _("symlink takes no arguments"))
208 return [f for f in mctx.subset if mctx.ctx.flags(f) == 'l']
208 return [f for f in mctx.subset if mctx.ctx.flags(f) == 'l']
209
209
210 def resolved(mctx, x):
210 def resolved(mctx, x):
211 """``resolved()``
211 """``resolved()``
212 File that is marked resolved according to the resolve state.
212 File that is marked resolved according to the resolve state.
213 """
213 """
214 getargs(x, 0, 0, _("resolved takes no arguments"))
214 getargs(x, 0, 0, _("resolved takes no arguments"))
215 if mctx.ctx.rev() is not None:
215 if mctx.ctx.rev() is not None:
216 return []
216 return []
217 ms = merge.mergestate(mctx.ctx._repo)
217 ms = merge.mergestate(mctx.ctx._repo)
218 return [f for f in mctx.subset if f in ms and ms[f] == 'r']
218 return [f for f in mctx.subset if f in ms and ms[f] == 'r']
219
219
220 def unresolved(mctx, x):
220 def unresolved(mctx, x):
221 """``unresolved()``
221 """``unresolved()``
222 File that is marked unresolved according to the resolve state.
222 File that is marked unresolved according to the resolve state.
223 """
223 """
224 getargs(x, 0, 0, _("unresolved takes no arguments"))
224 getargs(x, 0, 0, _("unresolved takes no arguments"))
225 if mctx.ctx.rev() is not None:
225 if mctx.ctx.rev() is not None:
226 return []
226 return []
227 ms = merge.mergestate(mctx.ctx._repo)
227 ms = merge.mergestate(mctx.ctx._repo)
228 return [f for f in mctx.subset if f in ms and ms[f] == 'u']
228 return [f for f in mctx.subset if f in ms and ms[f] == 'u']
229
229
230 def hgignore(mctx, x):
230 def hgignore(mctx, x):
231 """``resolved()``
231 """``resolved()``
232 File that matches the active .hgignore pattern.
232 File that matches the active .hgignore pattern.
233 """
233 """
234 getargs(x, 0, 0, _("hgignore takes no arguments"))
234 getargs(x, 0, 0, _("hgignore takes no arguments"))
235 ignore = mctx.ctx._repo.dirstate._ignore
235 ignore = mctx.ctx._repo.dirstate._ignore
236 return [f for f in mctx.subset if ignore(f)]
236 return [f for f in mctx.subset if ignore(f)]
237
237
238 def grep(mctx, x):
238 def grep(mctx, x):
239 """``grep(regex)``
239 """``grep(regex)``
240 File contains the given regular expression.
240 File contains the given regular expression.
241 """
241 """
242 pat = getstring(x, _("grep requires a pattern"))
242 pat = getstring(x, _("grep requires a pattern"))
243 r = re.compile(pat)
243 r = re.compile(pat)
244 return [f for f in mctx.subset if r.search(mctx.ctx[f].data())]
244 return [f for f in mctx.subset if r.search(mctx.ctx[f].data())]
245
245
246 _units = dict(k=2**10, K=2**10, kB=2**10, KB=2**10,
246 _units = dict(k=2**10, K=2**10, kB=2**10, KB=2**10,
247 M=2**20, MB=2**20, G=2**30, GB=2**30)
247 M=2**20, MB=2**20, G=2**30, GB=2**30)
248
248
249 def _sizetoint(s):
249 def _sizetoint(s):
250 try:
250 try:
251 s = s.strip()
251 s = s.strip()
252 for k, v in _units.items():
252 for k, v in _units.items():
253 if s.endswith(k):
253 if s.endswith(k):
254 return int(float(s[:-len(k)]) * v)
254 return int(float(s[:-len(k)]) * v)
255 return int(s)
255 return int(s)
256 except ValueError:
256 except ValueError:
257 raise
257 raise
258 raise error.ParseError(_("couldn't parse size"), s)
258 raise error.ParseError(_("couldn't parse size"), s)
259
259
260 def _sizetomax(s):
260 def _sizetomax(s):
261 try:
261 try:
262 s = s.strip()
262 s = s.strip()
263 for k, v in _units.items():
263 for k, v in _units.items():
264 if s.endswith(k):
264 if s.endswith(k):
265 # max(4k) = 5k - 1, max(4.5k) = 4.6k - 1
265 # max(4k) = 5k - 1, max(4.5k) = 4.6k - 1
266 n = s[:-len(k)]
266 n = s[:-len(k)]
267 inc = 1.0
267 inc = 1.0
268 if "." in n:
268 if "." in n:
269 inc /= 10 ** len(n.split(".")[1])
269 inc /= 10 ** len(n.split(".")[1])
270 return int((float(n) + inc) * v) - 1
270 return int((float(n) + inc) * v) - 1
271 # no extension, this is a precise value
271 # no extension, this is a precise value
272 return int(s)
272 return int(s)
273 except ValueError:
273 except ValueError:
274 raise
274 raise
275 raise error.ParseError(_("couldn't parse size"), s)
275 raise error.ParseError(_("couldn't parse size"), s)
276
276
277 def size(mctx, x):
277 def size(mctx, x):
278 """``size(expression)``
278 """``size(expression)``
279 File size matches the given expression. Examples:
279 File size matches the given expression. Examples:
280
280
281 - 1k (files from 1024 to 2047 bytes)
281 - 1k (files from 1024 to 2047 bytes)
282 - < 20k (files less than 20480 bytes)
282 - < 20k (files less than 20480 bytes)
283 - >= .5MB (files at least 524288 bytes)
283 - >= .5MB (files at least 524288 bytes)
284 - 4k - 1MB (files from 4096 bytes to 1048576 bytes)
284 - 4k - 1MB (files from 4096 bytes to 1048576 bytes)
285 """
285 """
286
286
287 expr = getstring(x, _("grep requires a pattern")).strip()
287 expr = getstring(x, _("grep requires a pattern")).strip()
288 if '-' in expr: # do we have a range?
288 if '-' in expr: # do we have a range?
289 a, b = expr.split('-', 1)
289 a, b = expr.split('-', 1)
290 a = _sizetoint(a)
290 a = _sizetoint(a)
291 b = _sizetoint(b)
291 b = _sizetoint(b)
292 m = lambda x: x >= a and x <= b
292 m = lambda x: x >= a and x <= b
293 elif expr.startswith("<="):
293 elif expr.startswith("<="):
294 a = _sizetoint(expr[2:])
294 a = _sizetoint(expr[2:])
295 m = lambda x: x <= a
295 m = lambda x: x <= a
296 elif expr.startswith("<"):
296 elif expr.startswith("<"):
297 a = _sizetoint(expr[1:])
297 a = _sizetoint(expr[1:])
298 m = lambda x: x < a
298 m = lambda x: x < a
299 elif expr.startswith(">="):
299 elif expr.startswith(">="):
300 a = _sizetoint(expr[2:])
300 a = _sizetoint(expr[2:])
301 m = lambda x: x >= a
301 m = lambda x: x >= a
302 elif expr.startswith(">"):
302 elif expr.startswith(">"):
303 a = _sizetoint(expr[1:])
303 a = _sizetoint(expr[1:])
304 m = lambda x: x > a
304 m = lambda x: x > a
305 elif expr[0].isdigit or expr[0] == '.':
305 elif expr[0].isdigit or expr[0] == '.':
306 a = _sizetoint(expr)
306 a = _sizetoint(expr)
307 b = _sizetomax(expr)
307 b = _sizetomax(expr)
308 m = lambda x: x >=a and x <= b
308 m = lambda x: x >= a and x <= b
309 else:
309 else:
310 raise error.ParseError(_("couldn't parse size"), expr)
310 raise error.ParseError(_("couldn't parse size"), expr)
311
311
312 return [f for f in mctx.subset if m(mctx.ctx[f].size())]
312 return [f for f in mctx.subset if m(mctx.ctx[f].size())]
313
313
314 def encoding(mctx, x):
314 def encoding(mctx, x):
315 """``encoding(name)``
315 """``encoding(name)``
316 File can be successfully decoded with the given character
316 File can be successfully decoded with the given character
317 encoding. May not be useful for encodings other than ASCII and
317 encoding. May not be useful for encodings other than ASCII and
318 UTF-8.
318 UTF-8.
319 """
319 """
320
320
321 enc = getstring(x, _("encoding requires an encoding name"))
321 enc = getstring(x, _("encoding requires an encoding name"))
322
322
323 s = []
323 s = []
324 for f in mctx.subset:
324 for f in mctx.subset:
325 d = mctx.ctx[f].data()
325 d = mctx.ctx[f].data()
326 try:
326 try:
327 d.decode(enc)
327 d.decode(enc)
328 except LookupError:
328 except LookupError:
329 raise util.Abort(_("unknown encoding '%s'") % enc)
329 raise util.Abort(_("unknown encoding '%s'") % enc)
330 except UnicodeDecodeError:
330 except UnicodeDecodeError:
331 continue
331 continue
332 s.append(f)
332 s.append(f)
333
333
334 return s
334 return s
335
335
336 def copied(mctx, x):
336 def copied(mctx, x):
337 """``copied()``
337 """``copied()``
338 File that is recorded as being copied.
338 File that is recorded as being copied.
339 """
339 """
340 s = []
340 s = []
341 for f in mctx.subset:
341 for f in mctx.subset:
342 p = mctx.ctx[f].parents()
342 p = mctx.ctx[f].parents()
343 if p and p[0].path() != f:
343 if p and p[0].path() != f:
344 s.append(f)
344 s.append(f)
345 return s
345 return s
346
346
347 symbols = {
347 symbols = {
348 'added': added,
348 'added': added,
349 'binary': binary,
349 'binary': binary,
350 'clean': clean,
350 'clean': clean,
351 'copied': copied,
351 'copied': copied,
352 'deleted': deleted,
352 'deleted': deleted,
353 'encoding': encoding,
353 'encoding': encoding,
354 'exec': exec_,
354 'exec': exec_,
355 'grep': grep,
355 'grep': grep,
356 'ignored': ignored,
356 'ignored': ignored,
357 'hgignore': hgignore,
357 'hgignore': hgignore,
358 'modified': modified,
358 'modified': modified,
359 'removed': removed,
359 'removed': removed,
360 'resolved': resolved,
360 'resolved': resolved,
361 'size': size,
361 'size': size,
362 'symlink': symlink,
362 'symlink': symlink,
363 'unknown': unknown,
363 'unknown': unknown,
364 'unresolved': unresolved,
364 'unresolved': unresolved,
365 }
365 }
366
366
367 methods = {
367 methods = {
368 'string': stringset,
368 'string': stringset,
369 'symbol': stringset,
369 'symbol': stringset,
370 'and': andset,
370 'and': andset,
371 'or': orset,
371 'or': orset,
372 'list': listset,
372 'list': listset,
373 'group': getset,
373 'group': getset,
374 'not': notset,
374 'not': notset,
375 'func': func,
375 'func': func,
376 }
376 }
377
377
378 class matchctx(object):
378 class matchctx(object):
379 def __init__(self, ctx, subset=None, status=None):
379 def __init__(self, ctx, subset=None, status=None):
380 self.ctx = ctx
380 self.ctx = ctx
381 self.subset = subset
381 self.subset = subset
382 self._status = status
382 self._status = status
383 def status(self):
383 def status(self):
384 return self._status
384 return self._status
385 def matcher(self, patterns):
385 def matcher(self, patterns):
386 return self.ctx.match(patterns)
386 return self.ctx.match(patterns)
387 def filter(self, files):
387 def filter(self, files):
388 return [f for f in files if f in self.subset]
388 return [f for f in files if f in self.subset]
389 def narrow(self, files):
389 def narrow(self, files):
390 return matchctx(self.ctx, self.filter(files), self._status)
390 return matchctx(self.ctx, self.filter(files), self._status)
391
391
392 def _intree(funcs, tree):
392 def _intree(funcs, tree):
393 if isinstance(tree, tuple):
393 if isinstance(tree, tuple):
394 if tree[0] == 'func' and tree[1][0] == 'symbol':
394 if tree[0] == 'func' and tree[1][0] == 'symbol':
395 if tree[1][1] in funcs:
395 if tree[1][1] in funcs:
396 return True
396 return True
397 for s in tree[1:]:
397 for s in tree[1:]:
398 if _intree(funcs, s):
398 if _intree(funcs, s):
399 return True
399 return True
400 return False
400 return False
401
401
402 def getfileset(ctx, expr):
402 def getfileset(ctx, expr):
403 tree, pos = parse(expr)
403 tree, pos = parse(expr)
404 if (pos != len(expr)):
404 if (pos != len(expr)):
405 raise error.ParseError("invalid token", pos)
405 raise error.ParseError("invalid token", pos)
406
406
407 # do we need status info?
407 # do we need status info?
408 if _intree(['modified', 'added', 'removed', 'deleted',
408 if _intree(['modified', 'added', 'removed', 'deleted',
409 'unknown', 'ignored', 'clean'], tree):
409 'unknown', 'ignored', 'clean'], tree):
410 unknown = _intree(['unknown'], tree)
410 unknown = _intree(['unknown'], tree)
411 ignored = _intree(['ignored'], tree)
411 ignored = _intree(['ignored'], tree)
412
412
413 r = ctx._repo
413 r = ctx._repo
414 status = r.status(ctx.p1(), ctx,
414 status = r.status(ctx.p1(), ctx,
415 unknown=unknown, ignored=ignored, clean=True)
415 unknown=unknown, ignored=ignored, clean=True)
416 subset = []
416 subset = []
417 for c in status:
417 for c in status:
418 subset.extend(c)
418 subset.extend(c)
419 else:
419 else:
420 status = None
420 status = None
421 subset = ctx.walk(ctx.match([]))
421 subset = ctx.walk(ctx.match([]))
422
422
423 return getset(matchctx(ctx, subset, status), tree)
423 return getset(matchctx(ctx, subset, status), tree)
424
424
425 # tell hggettext to extract docstrings from these functions:
425 # tell hggettext to extract docstrings from these functions:
426 i18nfunctions = symbols.values()
426 i18nfunctions = symbols.values()
General Comments 0
You need to be logged in to leave comments. Login now