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