Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/fileset.py @ 38919:80fd7371f2d8
fileset: build status according to 'withstatus' hint
_switchcallers is no longer needed since 'withstatus' node is reinserted for
arguments of functions like revs().
New matchctx instance is created per 'withstatus' to make sure that status
tuple is available only for children of the 'withstatus' node.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 22 Jul 2018 11:20:48 +0900 |
parents | e79a69af1593 |
children | dec16c0cce50 |
comparison
equal
deleted
inserted
replaced
38918:e79a69af1593 | 38919:80fd7371f2d8 |
---|---|
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): |
388 | 386 |
389 matchers = [] | 387 matchers = [] |
390 for r in revs: | 388 for r in revs: |
391 ctx = repo[r] | 389 ctx = repo[r] |
392 mc = mctx.switch(ctx.p1(), ctx) | 390 mc = mctx.switch(ctx.p1(), ctx) |
393 mc.buildstatus(x) | |
394 matchers.append(getmatch(mc, x)) | 391 matchers.append(getmatch(mc, x)) |
395 if not matchers: | 392 if not matchers: |
396 return mctx.never() | 393 return mctx.never() |
397 if len(matchers) == 1: | 394 if len(matchers) == 1: |
398 return matchers[0] | 395 return matchers[0] |
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() |