[PATCH] match: adding support for repository-root-based globs
Rodrigo Damazio Bovendorp
rdamazio at google.com
Mon Nov 14 23:59:09 EST 2016
# HG changeset patch
# User Rodrigo Damazio Bovendorp <rdamazio at google.com>
# Date 1475944120 25200
# Sat Oct 08 09:28:40 2016 -0700
# Node ID 93434cce258a797fcc3997c0af994a524695e273
# Parent b032a7b676c6637b2ac6f3ef29431013b15a08f9
match: adding support for repository-root-based globs
The broader plan is to add explicit base directories for all patterns:
============ ======== ======= ===========
pattern type root-ed cwd-ed any-of-path
============ ======== ======= ===========
wildcard rootglob cwdglob anyglob
regexp rootre cwdre anyre
raw string rootpath cwdpath anypath
============ ======== ======= ===========
(table by foozy)
I'm starting by adding rootglob.
One important characteristic and difference from the older glob types is
that rootglob does a *full* match, meaning that a * at the end will never
match recursively, even when the glob is used as an include pattern.
diff -r b032a7b676c6 -r 93434cce258a mercurial/help/patterns.txt
--- a/mercurial/help/patterns.txt Tue Nov 01 18:54:03 2016 -0700
+++ b/mercurial/help/patterns.txt Sat Oct 08 09:28:40 2016 -0700
@@ -40,6 +40,11 @@
``-I`` or ``-X`` options), can match also against directories: files
under matched directories are treated as matched.
+For ``-I`` and ``-X`` options, ``glob:`` will match directories recursively.
+``rootglob:``, on the other end, does a full match, meaning that all files, in
+directories or subdirectories, will only match if the entire expression matches.
+In that case, ``**`` can be used to obtain recursiveness.
+
Plain examples::
path:foo/bar a name bar in a directory named foo in the root
@@ -48,13 +53,18 @@
Glob examples::
- glob:*.c any name ending in ".c" in the current directory
- *.c any name ending in ".c" in the current directory
- **.c any name ending in ".c" in any subdirectory of the
- current directory including itself.
- foo/*.c any name ending in ".c" in the directory foo
- foo/**.c any name ending in ".c" in any subdirectory of foo
- including itself.
+ glob:*.c any name ending in ".c" in the current directory
+ *.c any name ending in ".c" in the current directory
+ **.c any name ending in ".c" in any subdirectory of the
+ current directory including itself.
+ foo/* any file in directory foo plus all its subdirectories,
+ recursively
+ foo/*.c any name ending in ".c" in the directory foo
+ foo/**.c any name ending in ".c" in any subdirectory of foo
+ including itself.
+ rootglob:*.c any name ending in ".c" in the repository root
+ rootglob:foo/* all files inside foo but not its subdirectories
+ rootglob:foo/** all files inside foo and its subdirectories
Regexp examples::
diff -r b032a7b676c6 -r 93434cce258a mercurial/match.py
--- a/mercurial/match.py Tue Nov 01 18:54:03 2016 -0700
+++ b/mercurial/match.py Sat Oct 08 09:28:40 2016 -0700
@@ -105,6 +105,8 @@
'glob:<glob>' - a glob relative to cwd
're:<regexp>' - a regular expression
'path:<path>' - a path relative to repository root
+ 'rootglob:<path>' - a glob relative to repository root. Unlike glob, *
+ will never match subdirectories.
'relglob:<glob>' - an unrooted glob (*.c matches C files in all dirs)
'relpath:<path>' - a path relative to cwd
'relre:<regexp>' - a regexp that needn't match the start of a name
@@ -286,7 +288,7 @@
for kind, pat in [_patsplit(p, default) for p in patterns]:
if kind in ('glob', 'relpath'):
pat = pathutil.canonpath(root, cwd, pat, auditor)
- elif kind in ('relglob', 'path'):
+ elif kind in ('relglob', 'path', 'rootglob'):
pat = util.normpath(pat)
elif kind in ('listfile', 'listfile0'):
try:
@@ -447,7 +449,8 @@
if ':' in pattern:
kind, pat = pattern.split(':', 1)
if kind in ('re', 'glob', 'path', 'relglob', 'relpath', 'relre',
- 'listfile', 'listfile0', 'set', 'include', 'subinclude'):
+ 'listfile', 'listfile0', 'set', 'include', 'subinclude',
+ 'rootglob'):
return kind, pat
return default, pattern
@@ -540,6 +543,8 @@
if pat == '.':
return ''
return '^' + util.re.escape(pat) + '(?:/|$)'
+ if kind == 'rootglob':
+ return '^' + _globre(pat) + '$'
if kind == 'relglob':
return '(?:|.*/)' + _globre(pat) + globsuffix
if kind == 'relpath':
@@ -614,6 +619,8 @@
>>> _roots([('glob', 'g/*', ''), ('glob', 'g', ''), ('glob', 'g*', '')])
['g', 'g', '.']
+ >>> _roots([('rootglob', 'g/*', ''), ('rootglob', 'g', '')])
+ ['g', 'g']
>>> _roots([('relpath', 'r', ''), ('path', 'p/p', ''), ('path', '', '')])
['r', 'p/p', '.']
>>> _roots([('relglob', 'rg*', ''), ('re', 're/', ''), ('relre', 'rr', '')])
@@ -621,7 +628,7 @@
'''
r = []
for kind, pat, source in kindpats:
- if kind == 'glob': # find the non-glob prefix
+ if kind == 'glob' or kind == 'rootglob': # find the non-glob prefix
root = []
for p in pat.split('/'):
if '[' in p or '{' in p or '*' in p or '?' in p:
@@ -636,7 +643,7 @@
def _anypats(kindpats):
for kind, pat, source in kindpats:
- if kind in ('glob', 're', 'relglob', 'relre', 'set'):
+ if kind in ('glob', 're', 'relglob', 'relre', 'set', 'rootglob'):
return True
_commentre = None
diff -r b032a7b676c6 -r 93434cce258a tests/test-walk.t
--- a/tests/test-walk.t Tue Nov 01 18:54:03 2016 -0700
+++ b/tests/test-walk.t Sat Oct 08 09:28:40 2016 -0700
@@ -112,6 +112,69 @@
f beans/navy ../beans/navy
f beans/pinto ../beans/pinto
f beans/turtle ../beans/turtle
+
+ $ hg debugwalk -I 'rootglob:*'
+ f fennel ../fennel
+ f fenugreek ../fenugreek
+ f fiddlehead ../fiddlehead
+ $ hg debugwalk -I 'rootglob:sk*nk'
+ $ hg debugwalk 'rootglob:sk*nk'
+ $ hg debugwalk -I 'rootglob:*k'
+ f fenugreek ../fenugreek
+ $ hg debugwalk -I 'rootglob:mammals/*'
+ f mammals/skunk skunk
+ $ hg debugwalk 'rootglob:mammals/*'
+ f mammals/skunk skunk
+ $ hg debugwalk -I 'rootglob:**/*u*'
+ f beans/turtle ../beans/turtle
+ f fenugreek ../fenugreek
+ f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
+ f mammals/skunk skunk
+ $ hg debugwalk -I 'rootglob:mammals/**'
+ f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
+ f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
+ f mammals/Procyonidae/raccoon Procyonidae/raccoon
+ f mammals/skunk skunk
+ $ hg debugwalk -I 'rootglob:*a*/*u*'
+ f beans/turtle ../beans/turtle
+ f mammals/skunk skunk
+ $ hg debugwalk 'rootglob:*a*/*u*'
+ f beans/turtle ../beans/turtle
+ f mammals/skunk skunk
+ $ hg debugwalk -X 'rootglob:mammals/*'
+ f beans/black ../beans/black
+ f beans/borlotti ../beans/borlotti
+ f beans/kidney ../beans/kidney
+ f beans/navy ../beans/navy
+ f beans/pinto ../beans/pinto
+ f beans/turtle ../beans/turtle
+ f fennel ../fennel
+ f fenugreek ../fenugreek
+ f fiddlehead ../fiddlehead
+ f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
+ f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
+ f mammals/Procyonidae/raccoon Procyonidae/raccoon
+ $ hg debugwalk -X 'rootglob:mammals/**'
+ f beans/black ../beans/black
+ f beans/borlotti ../beans/borlotti
+ f beans/kidney ../beans/kidney
+ f beans/navy ../beans/navy
+ f beans/pinto ../beans/pinto
+ f beans/turtle ../beans/turtle
+ f fennel ../fennel
+ f fenugreek ../fenugreek
+ f fiddlehead ../fiddlehead
+ $ hg debugwalk -X 'rootglob:**/*u*'
+ f beans/black ../beans/black
+ f beans/borlotti ../beans/borlotti
+ f beans/kidney ../beans/kidney
+ f beans/navy ../beans/navy
+ f beans/pinto ../beans/pinto
+ f fennel ../fennel
+ f fiddlehead ../fiddlehead
+ f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
+ f mammals/Procyonidae/raccoon Procyonidae/raccoon
+
$ hg debugwalk .
f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
More information about the Mercurial-devel
mailing list