A fileset predicate can invoke 'matchctx.existing()' successfully,
even if it isn't marked as "existing caller". It is aborted only in
some corner cases: e.g. there were one deleted file in the working
directory (see 2c5c0790cbcc for detail).
This patch makes 'matchctx.existing()' invocation abort if not
'_existingenabled', which is true only while "existing caller"
running.
After this changes, non-"existing caller" predicate function is
aborted immediately, whenever it invokes 'matchctx.existing()'. This
prevent developer from forgetting to mark a predicate as "existing
caller".
BTW, unintentional 'matchctx.status()' invocation can be detected
easily without any additional trick like this patch, because it
returns 'None' if a predicate isn't marked as "status caller", and
referring field (e.g. '.modified') of it is always aborted.
This reduces cost of examining whether given predicate calls
'matchctx.status()' or 'matchctx.existing()' in 'getfileset()' at
runtime.
This kind of examination is used also in subsequent patch, which
detects unintentional 'matchctx.existing()' invocation per each
predicate evaluation.
Before this patch, predicates calling 'matchctx.status()' are listed
up by immediate list value in 'getfileset()'.
This prevents 3rd party extensions from adding specific predicate
calling 'matchctx.status()'.
This uses decorator to mark a predicate as "status caller".
This can also localize changes for adding (or removing) a "status
caller" predicate function in source code.
Using decorator can localize changes for adding (or removing) a
fileset predicate function in source code.
It is also useful to pick predicates up for specific purpose. For
example, subsequent patches marks predicates as "call status" or "use
existing" via decorator.
To avoid (1) redundancy between "predicate name" and (the beginning
of) help document, and (2) accidental typo of help document, this
patch also makes decorator put predicate declration into the beginning
of help.
Before this patch, predicate function 'encoding' and 'eol' aren't
listed up in '_existingcallers', even though they invoke 'existing()'.
This causes unexpected failure of these predicate, if there is a
(manually) deleted file in the working directory.
2c5c0790cbcc and 12b403664548 seem to overlook putting already
existing 'encoding' or newly introduced 'eol' into '_existingcallers'.
This patch also changes order of fileset "eol(unix)" output in test,
because "existing caller" predicates show "A(dded)" files before
"C(lean)" ones.
Help of status cmd defines status file of 'missing', what is
called in fileset 'deleted'. To stay consistent this patch
introduces missing() predicate which in fact is alias to
'deleted'.
The home of 'Abort' is 'error' not 'util' however, a lot of code seems to be
confused about that and gives all the credit to 'util' instead of the
hardworking 'error'. In a spirit of equity, we break the cycle of injustice and
give back to 'error' the respect it deserves. And screw that 'util' poser.
For great justice.
When specifying one plain value in size(), e.g. size(1k), fileset tries to
guess the upper bound automatically (see the comment in _sizetomax()). It
didn't ignore the specified unit's case, and so size("1 GB"), for example,
produced this error:
hg: parse error: couldn't parse size: 1 GB
Let's do the same thing that util.sizetoint() does: .lower().
The two test lines without output just check that there are no parse errors.
This will allow us to define both a primary expression, ":", and a prefix
operator, ":y". The ambiguity will be resolved by the next patch.
Prefix actions in elements table are adjusted as follows:
original prefix primary prefix
----------------- -------- -----------------
("group", 1, ")") -> n/a ("group", 1, ")")
("negate", 19) -> n/a ("negate", 19)
("symbol",) -> "symbol" n/a
Python 2.6 introduced the "except type as instance" syntax, replacing
the "except type, instance" syntax that came before. Python 3 dropped
support for the latter syntax. Since we no longer support Python 2.4 or
2.5, we have no need to continue supporting the "except type, instance".
This patch mass rewrites the exception syntax to be Python 2.6+ and
Python 3 compatible.
This patch was produced by running `2to3 -f except -w -n .`.
This can simplify the interface of parse() function. Our tokenizer tends to
have optional arguments other than the message to be parsed.
Before this patch, the "lookup" argument existed only for the revset, and the
templater had to pack [program, start, end] to be passed to its tokenizer.
Unlike revsets, it looks like all of the filesets are documented, so there's
really nothing to test. This is aimed more at parity with revsets and
future-proofing.
This has mostly the same semantics as the files that the 'ui.portablefilenames'
config option would warn or abort about. The only difference is filenames that
case-fold to the same string -- given a set of filenames we've already
checked we can check whether a new one collides with them, but we don't have a
way to tell which filename it collided with.
parse() cannot be called at the same time because a parser object keeps its
states. This is no problem for command-line hg client, but it would cause
strange errors in multi-threaded hgweb.
Creating parser object is not too expensive.
original:
% python -m timeit -s 'from mercurial import revset' 'revset.parse("0::tip")'
100000 loops, best of 3: 11.3 usec per loop
thread-safe:
% python -m timeit -s 'from mercurial import revset' 'revset.parse("0::tip")'
100000 loops, best of 3: 13.1 usec per loop
Add sorted() in places found by testing with PYTHONHASHSEED=random and code
inspection.
An alternative to sprinkling sorted() all over would be to change substate to a
custom dict with sorted iterators...
When running:
$ hg debugfileset 'binary() and ignored()'
getfileset() was correctly retrieving ignored files but
matchctx.existing() was not taking them in account. Just add them along
with unknown files.
By default, unknown files are ignored. If the 'unknown()' predicate
appears in the syntax tree, then they are taken in account.
Unfortunately, matchctx.existing() was filtering against non-deleted
context files, which does not include unknown files. So:
$ hg debugfileset 'binary() and unknown()'
would not return existing binary unknown files.
Running:
$ hg debugfileset 'binary()'
would traceback if there were one deleted file in the working directory.
It happened because matchctx.existing() was filtering files against the
ctx.__contains__() but deleted files are still considered part of
workingctx.
This new fileset symbol returns a list of subrepos whose paths match a given
pattern. If the argument has no pattern type set, an exact
match is performed.
If no argument is passed, return a list of all subrepos.