Mercurial > public > mercurial-scm > hg-stable
diff mercurial/match.py @ 41282:4fab8a7d2d72
match: support rooted globs in hgignore
In a .hgignore, "glob:foo" always means "**/foo". This cannot be
avoided because there is no syntax like "^" in regexes to say you
don't want the implied "**/" (of course one can use regexes, but glob
syntax is nice).
When you have a long list of fairly specific globs like
path/to/some/thing, this has two consequences:
1. unintended files may be ignored (not too common though)
2. matching performance can suffer significantly
Here is vanilla hg status timing on a private repository:
Using syntax:glob everywhere
real 0m2.199s
user 0m1.545s
sys 0m0.619s
When rooting the appropriate globs
real 0m1.434s
user 0m0.847s
sys 0m0.565s
(tangentially, none of this shows up in --profile's output. It
seems that C code doesn't play well with profiling)
The code already supports this but there is no syntax to make use of
it, so it seems reasonable to create such syntax. I create a new
hgignore syntax "rootglob".
Differential Revision: https://phab.mercurial-scm.org/D5493
author | Valentin Gatien-Baron <vgatien-baron@janestreet.com> |
---|---|
date | Thu, 03 Jan 2019 19:02:46 -0500 |
parents | 074c72a38423 |
children | b7a0efb3c370 |
line wrap: on
line diff
--- a/mercurial/match.py Wed Nov 07 15:45:09 2018 -0800 +++ b/mercurial/match.py Thu Jan 03 19:02:46 2019 -0500 @@ -25,6 +25,7 @@ ) allpatternkinds = ('re', 'glob', 'path', 'relglob', 'relpath', 'relre', + 'rootglob', 'listfile', 'listfile0', 'set', 'include', 'subinclude', 'rootfilesin') cwdrelativepatternkinds = ('relpath', 'glob') @@ -221,7 +222,7 @@ for kind, pat in [_patsplit(p, default) for p in patterns]: if kind in cwdrelativepatternkinds: pat = pathutil.canonpath(root, cwd, pat, auditor) - elif kind in ('relglob', 'path', 'rootfilesin'): + elif kind in ('relglob', 'path', 'rootfilesin', 'rootglob'): pat = util.normpath(pat) elif kind in ('listfile', 'listfile0'): try: @@ -1137,7 +1138,7 @@ if pat.startswith('^'): return pat return '.*' + pat - if kind == 'glob': + if kind in ('glob', 'rootglob'): return _globre(pat) + globsuffix raise error.ProgrammingError('not a regex pattern: %s:%s' % (kind, pat)) @@ -1252,7 +1253,7 @@ r = [] d = [] for kind, pat, source in kindpats: - if kind == 'glob': # find the non-glob prefix + if kind in ('glob', 'rootglob'): # find the non-glob prefix root = [] for p in pat.split('/'): if '[' in p or '{' in p or '*' in p or '?' in p: @@ -1351,6 +1352,7 @@ syntax: glob # defaults following lines to non-rooted globs re:pattern # non-rooted regular expression glob:pattern # non-rooted glob + rootglob:pat # rooted glob (same root as ^ in regexps) pattern # pattern of the current default type if sourceinfo is set, returns a list of tuples: @@ -1361,6 +1363,7 @@ 're': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:', + 'rootglob': 'rootglob:', 'include': 'include', 'subinclude': 'subinclude', }