Show More
@@ -181,12 +181,7 b' def listmatch(mctx, x, y):' | |||||
181 | def func(mctx, a, b): |
|
181 | def func(mctx, a, b): | |
182 | funcname = getsymbol(a) |
|
182 | funcname = getsymbol(a) | |
183 | if funcname in symbols: |
|
183 | if funcname in symbols: | |
184 | enabled = mctx._existingenabled |
|
184 | return symbols[funcname](mctx, b) | |
185 | mctx._existingenabled = funcname in _existingcallers |
|
|||
186 | try: |
|
|||
187 | return symbols[funcname](mctx, b) |
|
|||
188 | finally: |
|
|||
189 | mctx._existingenabled = enabled |
|
|||
190 |
|
185 | |||
191 | keep = lambda fn: getattr(fn, '__doc__', None) is not None |
|
186 | keep = lambda fn: getattr(fn, '__doc__', None) is not None | |
192 |
|
187 | |||
@@ -203,9 +198,6 b' symbols = {}' | |||||
203 | # filesets using matchctx.status() |
|
198 | # filesets using matchctx.status() | |
204 | _statuscallers = set() |
|
199 | _statuscallers = set() | |
205 |
|
200 | |||
206 | # filesets using matchctx.existing() |
|
|||
207 | _existingcallers = set() |
|
|||
208 |
|
||||
209 | predicate = registrar.filesetpredicate() |
|
201 | predicate = registrar.filesetpredicate() | |
210 |
|
202 | |||
211 | @predicate('modified()', callstatus=True) |
|
203 | @predicate('modified()', callstatus=True) | |
@@ -285,7 +277,7 b' def tracked(mctx, x):' | |||||
285 | getargs(x, 0, 0, _("tracked takes no arguments")) |
|
277 | getargs(x, 0, 0, _("tracked takes no arguments")) | |
286 | return mctx.predicate(mctx.ctx.__contains__, predrepr='tracked') |
|
278 | return mctx.predicate(mctx.ctx.__contains__, predrepr='tracked') | |
287 |
|
279 | |||
288 |
@predicate('binary()' |
|
280 | @predicate('binary()') | |
289 | def binary(mctx, x): |
|
281 | def binary(mctx, x): | |
290 | """File that appears to be binary (contains NUL bytes). |
|
282 | """File that appears to be binary (contains NUL bytes). | |
291 | """ |
|
283 | """ | |
@@ -294,7 +286,7 b' def binary(mctx, x):' | |||||
294 | return mctx.fpredicate(lambda fctx: fctx.isbinary(), |
|
286 | return mctx.fpredicate(lambda fctx: fctx.isbinary(), | |
295 | predrepr='binary', cache=True) |
|
287 | predrepr='binary', cache=True) | |
296 |
|
288 | |||
297 |
@predicate('exec()' |
|
289 | @predicate('exec()') | |
298 | def exec_(mctx, x): |
|
290 | def exec_(mctx, x): | |
299 | """File that is marked as executable. |
|
291 | """File that is marked as executable. | |
300 | """ |
|
292 | """ | |
@@ -303,7 +295,7 b' def exec_(mctx, x):' | |||||
303 | ctx = mctx.ctx |
|
295 | ctx = mctx.ctx | |
304 | return mctx.predicate(lambda f: ctx.flags(f) == 'x', predrepr='exec') |
|
296 | return mctx.predicate(lambda f: ctx.flags(f) == 'x', predrepr='exec') | |
305 |
|
297 | |||
306 |
@predicate('symlink()' |
|
298 | @predicate('symlink()') | |
307 | def symlink(mctx, x): |
|
299 | def symlink(mctx, x): | |
308 | """File that is marked as a symlink. |
|
300 | """File that is marked as a symlink. | |
309 | """ |
|
301 | """ | |
@@ -354,7 +346,7 b' def portable(mctx, x):' | |||||
354 | return mctx.predicate(lambda f: util.checkwinfilename(f) is None, |
|
346 | return mctx.predicate(lambda f: util.checkwinfilename(f) is None, | |
355 | predrepr='portable') |
|
347 | predrepr='portable') | |
356 |
|
348 | |||
357 |
@predicate('grep(regex)' |
|
349 | @predicate('grep(regex)') | |
358 | def grep(mctx, x): |
|
350 | def grep(mctx, x): | |
359 | """File contains the given regular expression. |
|
351 | """File contains the given regular expression. | |
360 | """ |
|
352 | """ | |
@@ -408,7 +400,7 b' def sizematcher(expr):' | |||||
408 | b = _sizetomax(expr) |
|
400 | b = _sizetomax(expr) | |
409 | return lambda x: x >= a and x <= b |
|
401 | return lambda x: x >= a and x <= b | |
410 |
|
402 | |||
411 |
@predicate('size(expression)' |
|
403 | @predicate('size(expression)') | |
412 | def size(mctx, x): |
|
404 | def size(mctx, x): | |
413 | """File size matches the given expression. Examples: |
|
405 | """File size matches the given expression. Examples: | |
414 |
|
406 | |||
@@ -423,7 +415,7 b' def size(mctx, x):' | |||||
423 | return mctx.fpredicate(lambda fctx: m(fctx.size()), |
|
415 | return mctx.fpredicate(lambda fctx: m(fctx.size()), | |
424 | predrepr=('size(%r)', expr), cache=True) |
|
416 | predrepr=('size(%r)', expr), cache=True) | |
425 |
|
417 | |||
426 |
@predicate('encoding(name)' |
|
418 | @predicate('encoding(name)') | |
427 | def encoding(mctx, x): |
|
419 | def encoding(mctx, x): | |
428 | """File can be successfully decoded with the given character |
|
420 | """File can be successfully decoded with the given character | |
429 | encoding. May not be useful for encodings other than ASCII and |
|
421 | encoding. May not be useful for encodings other than ASCII and | |
@@ -445,7 +437,7 b' def encoding(mctx, x):' | |||||
445 |
|
437 | |||
446 | return mctx.fpredicate(encp, predrepr=('encoding(%r)', enc), cache=True) |
|
438 | return mctx.fpredicate(encp, predrepr=('encoding(%r)', enc), cache=True) | |
447 |
|
439 | |||
448 |
@predicate('eol(style)' |
|
440 | @predicate('eol(style)') | |
449 | def eol(mctx, x): |
|
441 | def eol(mctx, x): | |
450 | """File contains newlines of the given style (dos, unix, mac). Binary |
|
442 | """File contains newlines of the given style (dos, unix, mac). Binary | |
451 | files are excluded, files with mixed line endings match multiple |
|
443 | files are excluded, files with mixed line endings match multiple | |
@@ -566,7 +558,7 b' class matchctx(object):' | |||||
566 | self.subset = subset |
|
558 | self.subset = subset | |
567 | self._status = status |
|
559 | self._status = status | |
568 | self._badfn = badfn |
|
560 | self._badfn = badfn | |
569 | self._existingenabled = False |
|
561 | ||
570 | def status(self): |
|
562 | def status(self): | |
571 | return self._status |
|
563 | return self._status | |
572 |
|
564 | |||
@@ -621,17 +613,6 b' class matchctx(object):' | |||||
621 |
|
613 | |||
622 | def filter(self, files): |
|
614 | def filter(self, files): | |
623 | return [f for f in files if f in self.subset] |
|
615 | return [f for f in files if f in self.subset] | |
624 | def existing(self): |
|
|||
625 | if not self._existingenabled: |
|
|||
626 | raise error.ProgrammingError('unexpected existing() invocation') |
|
|||
627 | if self._status is not None: |
|
|||
628 | removed = set(self._status[3]) |
|
|||
629 | unknown = set(self._status[4] + self._status[5]) |
|
|||
630 | else: |
|
|||
631 | removed = set() |
|
|||
632 | unknown = set() |
|
|||
633 | return (f for f in self.subset |
|
|||
634 | if (f in self.ctx and f not in removed) or f in unknown) |
|
|||
635 |
|
616 | |||
636 | def switch(self, ctx, status=None): |
|
617 | def switch(self, ctx, status=None): | |
637 | subset = self.filter(_buildsubset(ctx, status)) |
|
618 | subset = self.filter(_buildsubset(ctx, status)) | |
@@ -683,13 +664,7 b' def match(ctx, expr, badfn=None):' | |||||
683 | def _buildstatus(ctx, tree, basectx=None): |
|
664 | def _buildstatus(ctx, tree, basectx=None): | |
684 | # do we need status info? |
|
665 | # do we need status info? | |
685 |
|
666 | |||
686 | # temporaty boolean to simplify the next conditional |
|
667 | if _intree(_statuscallers, tree): | |
687 | purewdir = ctx.rev() is None and basectx is None |
|
|||
688 |
|
||||
689 | if (_intree(_statuscallers, tree) or |
|
|||
690 | # Using matchctx.existing() on a workingctx requires us to check |
|
|||
691 | # for deleted files. |
|
|||
692 | (purewdir and _intree(_existingcallers, tree))): |
|
|||
693 | unknown = _intree(['unknown'], tree) |
|
668 | unknown = _intree(['unknown'], tree) | |
694 | ignored = _intree(['ignored'], tree) |
|
669 | ignored = _intree(['ignored'], tree) | |
695 |
|
670 | |||
@@ -711,10 +686,8 b' def loadpredicate(ui, extname, registrar' | |||||
711 | symbols[name] = func |
|
686 | symbols[name] = func | |
712 | if func._callstatus: |
|
687 | if func._callstatus: | |
713 | _statuscallers.add(name) |
|
688 | _statuscallers.add(name) | |
714 | if func._callexisting: |
|
|||
715 | _existingcallers.add(name) |
|
|||
716 |
|
689 | |||
717 |
# load built-in predicates explicitly to setup _statuscallers |
|
690 | # load built-in predicates explicitly to setup _statuscallers | |
718 | loadpredicate(None, None, predicate) |
|
691 | loadpredicate(None, None, predicate) | |
719 |
|
692 | |||
720 | # tell hggettext to extract docstrings from these functions: |
|
693 | # tell hggettext to extract docstrings from these functions: |
@@ -247,10 +247,6 b' class filesetpredicate(_funcregistrarbas' | |||||
247 | implies 'matchctx.status()' at runtime or not (False, by |
|
247 | implies 'matchctx.status()' at runtime or not (False, by | |
248 | default). |
|
248 | default). | |
249 |
|
249 | |||
250 | Optional argument 'callexisting' indicates whether a predicate |
|
|||
251 | implies 'matchctx.existing()' at runtime or not (False, by |
|
|||
252 | default). |
|
|||
253 |
|
||||
254 | 'filesetpredicate' instance in example above can be used to |
|
250 | 'filesetpredicate' instance in example above can be used to | |
255 | decorate multiple functions. |
|
251 | decorate multiple functions. | |
256 |
|
252 | |||
@@ -263,9 +259,8 b' class filesetpredicate(_funcregistrarbas' | |||||
263 | _getname = _funcregistrarbase._parsefuncdecl |
|
259 | _getname = _funcregistrarbase._parsefuncdecl | |
264 | _docformat = "``%s``\n %s" |
|
260 | _docformat = "``%s``\n %s" | |
265 |
|
261 | |||
266 |
def _extrasetup(self, name, func, callstatus=False |
|
262 | def _extrasetup(self, name, func, callstatus=False): | |
267 | func._callstatus = callstatus |
|
263 | func._callstatus = callstatus | |
268 | func._callexisting = callexisting |
|
|||
269 |
|
264 | |||
270 | class _templateregistrarbase(_funcregistrarbase): |
|
265 | class _templateregistrarbase(_funcregistrarbase): | |
271 | """Base of decorator to register functions as template specific one |
|
266 | """Base of decorator to register functions as template specific one |
@@ -448,27 +448,6 b" Test safety of 'encoding' on removed fil" | |||||
448 | mixed |
|
448 | mixed | |
449 | unknown |
|
449 | unknown | |
450 |
|
450 | |||
451 | Test detection of unintentional 'matchctx.existing()' invocation |
|
|||
452 |
|
||||
453 | $ cat > $TESTTMP/existingcaller.py <<EOF |
|
|||
454 | > from mercurial import registrar |
|
|||
455 | > |
|
|||
456 | > filesetpredicate = registrar.filesetpredicate() |
|
|||
457 | > @filesetpredicate(b'existingcaller()', callexisting=False) |
|
|||
458 | > def existingcaller(mctx, x): |
|
|||
459 | > # this 'mctx.existing()' invocation is unintentional |
|
|||
460 | > existing = set(mctx.existing()) |
|
|||
461 | > return mctx.predicate(existing.__contains__, cache=False) |
|
|||
462 | > EOF |
|
|||
463 |
|
||||
464 | $ cat >> .hg/hgrc <<EOF |
|
|||
465 | > [extensions] |
|
|||
466 | > existingcaller = $TESTTMP/existingcaller.py |
|
|||
467 | > EOF |
|
|||
468 |
|
||||
469 | $ fileset 'existingcaller()' 2>&1 | tail -1 |
|
|||
470 | *ProgrammingError: *unexpected existing() invocation* (glob) |
|
|||
471 |
|
||||
472 | Test 'revs(...)' |
|
451 | Test 'revs(...)' | |
473 | ================ |
|
452 | ================ | |
474 |
|
453 |
General Comments 0
You need to be logged in to leave comments.
Login now