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()