Show More
@@ -43,6 +43,9 b' def getmatch(mctx, x):' | |||
|
43 | 43 | raise error.ParseError(_("missing argument")) |
|
44 | 44 | return methods[x[0]](mctx, *x[1:]) |
|
45 | 45 | |
|
46 | def getmatchwithstatus(mctx, x, hint): | |
|
47 | return getmatch(mctx, x) | |
|
48 | ||
|
46 | 49 | def stringmatch(mctx, x): |
|
47 | 50 | return mctx.matcher([x]) |
|
48 | 51 | |
@@ -443,6 +446,7 b' def subrepo(mctx, x):' | |||
|
443 | 446 | return mctx.predicate(sstate.__contains__, predrepr='subrepo') |
|
444 | 447 | |
|
445 | 448 | methods = { |
|
449 | 'withstatus': getmatchwithstatus, | |
|
446 | 450 | 'string': stringmatch, |
|
447 | 451 | 'symbol': stringmatch, |
|
448 | 452 | 'kindpat': kindpatmatch, |
@@ -171,6 +171,82 b' def _analyze(x):' | |||
|
171 | 171 | return (op, x[1], ta) |
|
172 | 172 | raise error.ProgrammingError('invalid operator %r' % op) |
|
173 | 173 | |
|
174 | def _insertstatushints(x): | |
|
175 | """Insert hint nodes where status should be calculated (first path) | |
|
176 | ||
|
177 | This works in bottom-up way, summing up status names and inserting hint | |
|
178 | nodes at 'and' and 'or' as needed. Thus redundant hint nodes may be left. | |
|
179 | ||
|
180 | Returns (status-names, new-tree) at the given subtree, where status-names | |
|
181 | is a sum of status names referenced in the given subtree. | |
|
182 | """ | |
|
183 | if x is None: | |
|
184 | return (), x | |
|
185 | ||
|
186 | op = x[0] | |
|
187 | if op in {'string', 'symbol', 'kindpat'}: | |
|
188 | return (), x | |
|
189 | if op == 'not': | |
|
190 | h, t = _insertstatushints(x[1]) | |
|
191 | return h, (op, t) | |
|
192 | if op == 'and': | |
|
193 | ha, ta = _insertstatushints(x[1]) | |
|
194 | hb, tb = _insertstatushints(x[2]) | |
|
195 | hr = ha + hb | |
|
196 | if ha and hb: | |
|
197 | return hr, ('withstatus', (op, ta, tb), ('string', ' '.join(hr))) | |
|
198 | return hr, (op, ta, tb) | |
|
199 | if op == 'or': | |
|
200 | hs, ts = zip(*(_insertstatushints(y) for y in x[1:])) | |
|
201 | hr = sum(hs, ()) | |
|
202 | if sum(bool(h) for h in hs) > 1: | |
|
203 | return hr, ('withstatus', (op,) + ts, ('string', ' '.join(hr))) | |
|
204 | return hr, (op,) + ts | |
|
205 | if op == 'list': | |
|
206 | hs, ts = zip(*(_insertstatushints(y) for y in x[1:])) | |
|
207 | return sum(hs, ()), (op,) + ts | |
|
208 | if op == 'func': | |
|
209 | f = getsymbol(x[1]) | |
|
210 | # don't propagate 'ha' crossing a function boundary | |
|
211 | ha, ta = _insertstatushints(x[2]) | |
|
212 | if getattr(symbols.get(f), '_callstatus', False): | |
|
213 | return (f,), ('withstatus', (op, x[1], ta), ('string', f)) | |
|
214 | return (), (op, x[1], ta) | |
|
215 | raise error.ProgrammingError('invalid operator %r' % op) | |
|
216 | ||
|
217 | def _mergestatushints(x, instatus): | |
|
218 | """Remove redundant status hint nodes (second path) | |
|
219 | ||
|
220 | This is the top-down path to eliminate inner hint nodes. | |
|
221 | """ | |
|
222 | if x is None: | |
|
223 | return x | |
|
224 | ||
|
225 | op = x[0] | |
|
226 | if op == 'withstatus': | |
|
227 | if instatus: | |
|
228 | # drop redundant hint node | |
|
229 | return _mergestatushints(x[1], instatus) | |
|
230 | t = _mergestatushints(x[1], instatus=True) | |
|
231 | return (op, t, x[2]) | |
|
232 | if op in {'string', 'symbol', 'kindpat'}: | |
|
233 | return x | |
|
234 | if op == 'not': | |
|
235 | t = _mergestatushints(x[1], instatus) | |
|
236 | return (op, t) | |
|
237 | if op == 'and': | |
|
238 | ta = _mergestatushints(x[1], instatus) | |
|
239 | tb = _mergestatushints(x[2], instatus) | |
|
240 | return (op, ta, tb) | |
|
241 | if op in {'list', 'or'}: | |
|
242 | ts = tuple(_mergestatushints(y, instatus) for y in x[1:]) | |
|
243 | return (op,) + ts | |
|
244 | if op == 'func': | |
|
245 | # don't propagate 'instatus' crossing a function boundary | |
|
246 | ta = _mergestatushints(x[2], instatus=False) | |
|
247 | return (op, x[1], ta) | |
|
248 | raise error.ProgrammingError('invalid operator %r' % op) | |
|
249 | ||
|
174 | 250 | def analyze(x): |
|
175 | 251 | """Transform raw parsed tree to evaluatable tree which can be fed to |
|
176 | 252 | optimize() or getmatch() |
@@ -178,7 +254,9 b' def analyze(x):' | |||
|
178 | 254 | All pseudo operations should be mapped to real operations or functions |
|
179 | 255 | defined in methods or symbols table respectively. |
|
180 | 256 | """ |
|
181 |
|
|
|
257 | t = _analyze(x) | |
|
258 | _h, t = _insertstatushints(t) | |
|
259 | return _mergestatushints(t, instatus=False) | |
|
182 | 260 | |
|
183 | 261 | def _optimizeandops(op, ta, tb): |
|
184 | 262 | if tb is not None and tb[0] == 'not': |
@@ -205,6 +283,9 b' def _optimize(x):' | |||
|
205 | 283 | return 0, x |
|
206 | 284 | |
|
207 | 285 | op = x[0] |
|
286 | if op == 'withstatus': | |
|
287 | w, t = _optimize(x[1]) | |
|
288 | return w, (op, t, x[2]) | |
|
208 | 289 | if op in {'string', 'symbol'}: |
|
209 | 290 | return WEIGHT_CHECK_FILENAME, x |
|
210 | 291 | if op == 'kindpat': |
@@ -24,7 +24,9 b' def _compile(tree):' | |||
|
24 | 24 | if not tree: |
|
25 | 25 | raise error.ParseError(_("missing argument")) |
|
26 | 26 | op = tree[0] |
|
27 | if op in {'symbol', 'string', 'kindpat'}: | |
|
27 | if op == 'withstatus': | |
|
28 | return _compile(tree[1]) | |
|
29 | elif op in {'symbol', 'string', 'kindpat'}: | |
|
28 | 30 | name = filesetlang.getpattern(tree, {'path'}, _('invalid file pattern')) |
|
29 | 31 | if name.startswith('**'): # file extension test, ex. "**.tar.gz" |
|
30 | 32 | ext = name[2:] |
@@ -175,18 +175,22 b' Show parsed tree at stages:' | |||
|
175 | 175 | (func |
|
176 | 176 | (symbol 'grep') |
|
177 | 177 | (string 'b')) |
|
178 | (func | |
|
179 | (symbol 'clean') | |
|
180 | None))) | |
|
178 | (withstatus | |
|
179 | (func | |
|
180 | (symbol 'clean') | |
|
181 | None) | |
|
182 | (string 'clean')))) | |
|
181 | 183 | * optimized: |
|
182 | 184 | (or |
|
183 | 185 | (patterns |
|
184 | 186 | (symbol 'a1') |
|
185 | 187 | (symbol 'a2')) |
|
186 | 188 | (and |
|
187 | (func | |
|
188 | (symbol 'clean') | |
|
189 | None) | |
|
189 | (withstatus | |
|
190 | (func | |
|
191 | (symbol 'clean') | |
|
192 | None) | |
|
193 | (string 'clean')) | |
|
190 | 194 | (func |
|
191 | 195 | (symbol 'grep') |
|
192 | 196 | (string 'b')))) |
@@ -374,6 +378,156 b' Test files status in different revisions' | |||
|
374 | 378 | b2 |
|
375 | 379 | c1 |
|
376 | 380 | |
|
381 | Test insertion of status hints | |
|
382 | ||
|
383 | $ fileset -p optimized 'added()' | |
|
384 | * optimized: | |
|
385 | (withstatus | |
|
386 | (func | |
|
387 | (symbol 'added') | |
|
388 | None) | |
|
389 | (string 'added')) | |
|
390 | c1 | |
|
391 | ||
|
392 | $ fileset -p optimized 'a* & removed()' | |
|
393 | * optimized: | |
|
394 | (and | |
|
395 | (symbol 'a*') | |
|
396 | (withstatus | |
|
397 | (func | |
|
398 | (symbol 'removed') | |
|
399 | None) | |
|
400 | (string 'removed'))) | |
|
401 | a2 | |
|
402 | ||
|
403 | $ fileset -p optimized 'a* - removed()' | |
|
404 | * optimized: | |
|
405 | (minus | |
|
406 | (symbol 'a*') | |
|
407 | (withstatus | |
|
408 | (func | |
|
409 | (symbol 'removed') | |
|
410 | None) | |
|
411 | (string 'removed'))) | |
|
412 | a1 | |
|
413 | ||
|
414 | $ fileset -p analyzed -p optimized '(added() + removed()) - a*' | |
|
415 | * analyzed: | |
|
416 | (and | |
|
417 | (withstatus | |
|
418 | (or | |
|
419 | (func | |
|
420 | (symbol 'added') | |
|
421 | None) | |
|
422 | (func | |
|
423 | (symbol 'removed') | |
|
424 | None)) | |
|
425 | (string 'added removed')) | |
|
426 | (not | |
|
427 | (symbol 'a*'))) | |
|
428 | * optimized: | |
|
429 | (and | |
|
430 | (not | |
|
431 | (symbol 'a*')) | |
|
432 | (withstatus | |
|
433 | (or | |
|
434 | (func | |
|
435 | (symbol 'added') | |
|
436 | None) | |
|
437 | (func | |
|
438 | (symbol 'removed') | |
|
439 | None)) | |
|
440 | (string 'added removed'))) | |
|
441 | c1 | |
|
442 | ||
|
443 | $ fileset -p optimized 'a* + b* + added() + unknown()' | |
|
444 | * optimized: | |
|
445 | (withstatus | |
|
446 | (or | |
|
447 | (patterns | |
|
448 | (symbol 'a*') | |
|
449 | (symbol 'b*')) | |
|
450 | (func | |
|
451 | (symbol 'added') | |
|
452 | None) | |
|
453 | (func | |
|
454 | (symbol 'unknown') | |
|
455 | None)) | |
|
456 | (string 'added unknown')) | |
|
457 | a1 | |
|
458 | a2 | |
|
459 | b1 | |
|
460 | b2 | |
|
461 | c1 | |
|
462 | c3 | |
|
463 | ||
|
464 | $ fileset -p analyzed -p optimized 'removed() & missing() & a*' | |
|
465 | * analyzed: | |
|
466 | (and | |
|
467 | (withstatus | |
|
468 | (and | |
|
469 | (func | |
|
470 | (symbol 'removed') | |
|
471 | None) | |
|
472 | (func | |
|
473 | (symbol 'missing') | |
|
474 | None)) | |
|
475 | (string 'removed missing')) | |
|
476 | (symbol 'a*')) | |
|
477 | * optimized: | |
|
478 | (and | |
|
479 | (symbol 'a*') | |
|
480 | (withstatus | |
|
481 | (and | |
|
482 | (func | |
|
483 | (symbol 'removed') | |
|
484 | None) | |
|
485 | (func | |
|
486 | (symbol 'missing') | |
|
487 | None)) | |
|
488 | (string 'removed missing'))) | |
|
489 | ||
|
490 | $ fileset -p optimized 'clean() & revs(0, added())' | |
|
491 | * optimized: | |
|
492 | (and | |
|
493 | (withstatus | |
|
494 | (func | |
|
495 | (symbol 'clean') | |
|
496 | None) | |
|
497 | (string 'clean')) | |
|
498 | (func | |
|
499 | (symbol 'revs') | |
|
500 | (list | |
|
501 | (symbol '0') | |
|
502 | (withstatus | |
|
503 | (func | |
|
504 | (symbol 'added') | |
|
505 | None) | |
|
506 | (string 'added'))))) | |
|
507 | b1 | |
|
508 | ||
|
509 | $ fileset -p optimized 'clean() & status(null, 0, b* & added())' | |
|
510 | * optimized: | |
|
511 | (and | |
|
512 | (withstatus | |
|
513 | (func | |
|
514 | (symbol 'clean') | |
|
515 | None) | |
|
516 | (string 'clean')) | |
|
517 | (func | |
|
518 | (symbol 'status') | |
|
519 | (list | |
|
520 | (symbol 'null') | |
|
521 | (symbol '0') | |
|
522 | (and | |
|
523 | (symbol 'b*') | |
|
524 | (withstatus | |
|
525 | (func | |
|
526 | (symbol 'added') | |
|
527 | None) | |
|
528 | (string 'added')))))) | |
|
529 | b1 | |
|
530 | ||
|
377 | 531 | Test files properties |
|
378 | 532 | |
|
379 | 533 | >>> open('bin', 'wb').write(b'\0a') and None |
General Comments 0
You need to be logged in to leave comments.
Login now