42 if not x: |
42 if not x: |
43 raise error.ParseError(_("missing argument")) |
43 raise error.ParseError(_("missing argument")) |
44 return methods[x[0]](mctx, *x[1:]) |
44 return methods[x[0]](mctx, *x[1:]) |
45 |
45 |
46 def getmatchwithstatus(mctx, x, hint): |
46 def getmatchwithstatus(mctx, x, hint): |
47 return getmatch(mctx, x) |
47 keys = set(getstring(hint, 'status hint must be a string').split()) |
|
48 return getmatch(mctx.withstatus(keys), x) |
48 |
49 |
49 def stringmatch(mctx, x): |
50 def stringmatch(mctx, x): |
50 return mctx.matcher([x]) |
51 return mctx.matcher([x]) |
51 |
52 |
52 def kindpatmatch(mctx, x, y): |
53 def kindpatmatch(mctx, x, y): |
95 # fun(mctx, x) |
96 # fun(mctx, x) |
96 # with: |
97 # with: |
97 # mctx - current matchctx instance |
98 # mctx - current matchctx instance |
98 # x - argument in tree form |
99 # x - argument in tree form |
99 symbols = filesetlang.symbols |
100 symbols = filesetlang.symbols |
100 |
|
101 # filesets using matchctx.status() |
|
102 _statuscallers = set() |
|
103 |
101 |
104 predicate = registrar.filesetpredicate() |
102 predicate = registrar.filesetpredicate() |
105 |
103 |
106 @predicate('modified()', callstatus=True, weight=_WEIGHT_STATUS) |
104 @predicate('modified()', callstatus=True, weight=_WEIGHT_STATUS) |
107 def modified(mctx, x): |
105 def modified(mctx, x): |
417 revspec = getstring(r, reverr) |
414 revspec = getstring(r, reverr) |
418 if not revspec: |
415 if not revspec: |
419 raise error.ParseError(reverr) |
416 raise error.ParseError(reverr) |
420 basectx, ctx = scmutil.revpair(repo, [baserevspec, revspec]) |
417 basectx, ctx = scmutil.revpair(repo, [baserevspec, revspec]) |
421 mc = mctx.switch(basectx, ctx) |
418 mc = mctx.switch(basectx, ctx) |
422 mc.buildstatus(x) |
|
423 return getmatch(mc, x) |
419 return getmatch(mc, x) |
424 |
420 |
425 @predicate('subrepo([pattern])') |
421 @predicate('subrepo([pattern])') |
426 def subrepo(mctx, x): |
422 def subrepo(mctx, x): |
427 """Subrepositories whose paths match the given pattern. |
423 """Subrepositories whose paths match the given pattern. |
464 self._basectx = basectx |
460 self._basectx = basectx |
465 self.ctx = ctx |
461 self.ctx = ctx |
466 self._badfn = badfn |
462 self._badfn = badfn |
467 self._status = None |
463 self._status = None |
468 |
464 |
469 def buildstatus(self, tree): |
465 def withstatus(self, keys): |
470 if not _intree(_statuscallers, tree): |
466 """Create matchctx which has precomputed status specified by the keys""" |
471 return |
467 mctx = matchctx(self._basectx, self.ctx, self._badfn) |
472 unknown = _intree(['unknown'], tree) |
468 mctx._buildstatus(keys) |
473 ignored = _intree(['ignored'], tree) |
469 return mctx |
|
470 |
|
471 def _buildstatus(self, keys): |
474 self._status = self._basectx.status(self.ctx, |
472 self._status = self._basectx.status(self.ctx, |
475 listignored=ignored, |
473 listignored='ignored' in keys, |
476 listclean=True, |
474 listclean=True, |
477 listunknown=unknown) |
475 listunknown='unknown' in keys) |
478 |
476 |
479 def status(self): |
477 def status(self): |
480 return self._status |
478 return self._status |
481 |
479 |
482 def matcher(self, patterns): |
480 def matcher(self, patterns): |
531 badfn=self._badfn) |
529 badfn=self._badfn) |
532 |
530 |
533 def switch(self, basectx, ctx): |
531 def switch(self, basectx, ctx): |
534 return matchctx(basectx, ctx, self._badfn) |
532 return matchctx(basectx, ctx, self._badfn) |
535 |
533 |
536 # filesets using matchctx.switch() |
|
537 _switchcallers = [ |
|
538 'revs', |
|
539 'status', |
|
540 ] |
|
541 |
|
542 def _intree(funcs, tree): |
|
543 if isinstance(tree, tuple): |
|
544 if tree[0] == 'func' and tree[1][0] == 'symbol': |
|
545 if tree[1][1] in funcs: |
|
546 return True |
|
547 if tree[1][1] in _switchcallers: |
|
548 # arguments won't be evaluated in the current context |
|
549 return False |
|
550 for s in tree[1:]: |
|
551 if _intree(funcs, s): |
|
552 return True |
|
553 return False |
|
554 |
|
555 def match(ctx, expr, badfn=None): |
534 def match(ctx, expr, badfn=None): |
556 """Create a matcher for a single fileset expression""" |
535 """Create a matcher for a single fileset expression""" |
557 tree = filesetlang.parse(expr) |
536 tree = filesetlang.parse(expr) |
558 tree = filesetlang.analyze(tree) |
537 tree = filesetlang.analyze(tree) |
559 tree = filesetlang.optimize(tree) |
538 tree = filesetlang.optimize(tree) |
560 mctx = matchctx(ctx.p1(), ctx, badfn=badfn) |
539 mctx = matchctx(ctx.p1(), ctx, badfn=badfn) |
561 mctx.buildstatus(tree) |
|
562 return getmatch(mctx, tree) |
540 return getmatch(mctx, tree) |
563 |
541 |
564 |
542 |
565 def loadpredicate(ui, extname, registrarobj): |
543 def loadpredicate(ui, extname, registrarobj): |
566 """Load fileset predicates from specified registrarobj |
544 """Load fileset predicates from specified registrarobj |
567 """ |
545 """ |
568 for name, func in registrarobj._table.iteritems(): |
546 for name, func in registrarobj._table.iteritems(): |
569 symbols[name] = func |
547 symbols[name] = func |
570 if func._callstatus: |
548 |
571 _statuscallers.add(name) |
549 # load built-in predicates explicitly |
572 |
|
573 # load built-in predicates explicitly to setup _statuscallers |
|
574 loadpredicate(None, None, predicate) |
550 loadpredicate(None, None, predicate) |
575 |
551 |
576 # tell hggettext to extract docstrings from these functions: |
552 # tell hggettext to extract docstrings from these functions: |
577 i18nfunctions = symbols.values() |
553 i18nfunctions = symbols.values() |