mercurial/fileset.py
changeset 38880 80fd7371f2d8
parent 38879 e79a69af1593
child 38881 dec16c0cce50
equal deleted inserted replaced
38879:e79a69af1593 38880: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()