[PATCH 1 of 2] match: adding support for matching files inside a directory
Rodrigo Damazio Bovendorp
rdamazio at google.com
Fri Feb 10 23:52:49 UTC 2017
# HG changeset patch
# User Rodrigo Damazio Bovendorp <rdamazio at google.com>
# Date 1486768320 28800
# Fri Feb 10 15:12:00 2017 -0800
# Node ID 2d9523f80c5b5fbace1b0566fb47bed7468369b0
# Parent a95fc01aaffe805bcc4c02a822b82a1162fa35b9
match: adding support for matching files inside a directory
This adds a new "rootfilesin" matcher type which matches files inside a
directory, but not any subdirectories (so it matches non-recursively).
This has the "root" prefix per foozy's plan for other matchers (rootglob,
rootpath, cwdre, etc.).
diff -r a95fc01aaffe -r 2d9523f80c5b mercurial/help/patterns.txt
--- a/mercurial/help/patterns.txt Wed Feb 08 14:37:38 2017 -0800
+++ b/mercurial/help/patterns.txt Fri Feb 10 15:12:00 2017 -0800
@@ -13,7 +13,10 @@
To use a plain path name without any pattern matching, start it with
``path:``. These path names must completely match starting at the
-current repository root.
+current repository root, and when the path points to a directory, it is matched
+recursively. To match all files in a directory non-recursively (not including
+any files in subdirectories), ``rootfilesin:`` can be used, specifying an
+absolute path (relative to the repository root).
To use an extended glob, start a name with ``glob:``. Globs are rooted
at the current directory; a glob such as ``*.c`` will only match files
@@ -39,12 +42,15 @@
All patterns, except for ``glob:`` specified in command line (not for
``-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.
Plain examples::
- path:foo/bar a name bar in a directory named foo in the root
- of the repository
- path:path:name a file or directory named "path:name"
+ path:foo/bar a name bar in a directory named foo in the root
+ of the repository
+ path:path:name a file or directory named "path:name"
+ rootfilesin:foo/bar the files in a directory called foo/bar, but not any files
+ in its subdirectories and not a file bar in directory foo
Glob examples::
@@ -52,6 +58,8 @@
*.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.
diff -r a95fc01aaffe -r 2d9523f80c5b mercurial/match.py
--- a/mercurial/match.py Wed Feb 08 14:37:38 2017 -0800
+++ b/mercurial/match.py Fri Feb 10 15:12:00 2017 -0800
@@ -104,7 +104,10 @@
a pattern is one of:
'glob:<glob>' - a glob relative to cwd
're:<regexp>' - a regular expression
- 'path:<path>' - a path relative to repository root
+ 'path:<path>' - a path relative to repository root, which is matched
+ recursively
+ 'rootfilesin:<path>' - a path relative to repository root, which is
+ matched non-recursively (will not 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
@@ -153,7 +156,7 @@
elif patterns:
kindpats = self._normalize(patterns, default, root, cwd, auditor)
if not _kindpatsalwaysmatch(kindpats):
- self._files = _roots(kindpats)
+ self._files = _explicitfiles(kindpats)
self._anypats = self._anypats or _anypats(kindpats)
self.patternspat, pm = _buildmatch(ctx, kindpats, '$',
listsubrepos, root)
@@ -286,7 +289,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', 'rootfilesin'):
pat = util.normpath(pat)
elif kind in ('listfile', 'listfile0'):
try:
@@ -447,7 +450,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',
+ 'rootfilesin'):
return kind, pat
return default, pattern
@@ -540,6 +544,14 @@
if pat == '.':
return ''
return '^' + util.re.escape(pat) + '(?:/|$)'
+ if kind == 'rootfilesin':
+ if pat == '.':
+ escaped = ''
+ else:
+ # Pattern is a directory name.
+ escaped = util.re.escape(pat) + '/'
+ # Anything after the pattern must be a non-directory.
+ return '^' + escaped + '[^/]*$'
if kind == 'relglob':
return '(?:|.*/)' + _globre(pat) + globsuffix
if kind == 'relpath':
@@ -614,6 +626,8 @@
>>> _roots([('glob', 'g/*', ''), ('glob', 'g', ''), ('glob', 'g*', '')])
['g', 'g', '.']
+ >>> _roots([('rootfilesin', 'g', ''), ('rootfilesin', '', '')])
+ ['g', '.']
>>> _roots([('relpath', 'r', ''), ('path', 'p/p', ''), ('path', '', '')])
['r', 'p/p', '.']
>>> _roots([('relglob', 'rg*', ''), ('re', 're/', ''), ('relre', 'rr', '')])
@@ -628,15 +642,28 @@
break
root.append(p)
r.append('/'.join(root) or '.')
- elif kind in ('relpath', 'path'):
+ elif kind in ('relpath', 'path', 'rootfilesin'):
r.append(pat or '.')
else: # relglob, re, relre
r.append('.')
return r
+def _explicitfiles(kindpats):
+ '''Returns the potential explicit filenames from the patterns.
+
+ >>> _explicitfiles([('path', 'foo/bar', '')])
+ ['foo/bar']
+ >>> _explicitfiles([('rootfilesin', 'foo/bar', '')])
+ []
+ '''
+ # Keep only the pattern kinds where one can specify filenames (vs only
+ # directory names).
+ filable = [kp for kp in kindpats if kp[0] not in ('rootfilesin')]
+ return _roots(filable)
+
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', 'rootfilesin'):
return True
_commentre = None
diff -r a95fc01aaffe -r 2d9523f80c5b tests/test-walk.t
--- a/tests/test-walk.t Wed Feb 08 14:37:38 2017 -0800
+++ b/tests/test-walk.t Fri Feb 10 15:12:00 2017 -0800
@@ -112,6 +112,74 @@
f beans/navy ../beans/navy
f beans/pinto ../beans/pinto
f beans/turtle ../beans/turtle
+
+ $ hg debugwalk 'rootfilesin:'
+ f fennel ../fennel
+ f fenugreek ../fenugreek
+ f fiddlehead ../fiddlehead
+ $ hg debugwalk -I 'rootfilesin:'
+ f fennel ../fennel
+ f fenugreek ../fenugreek
+ f fiddlehead ../fiddlehead
+ $ hg debugwalk 'rootfilesin:.'
+ f fennel ../fennel
+ f fenugreek ../fenugreek
+ f fiddlehead ../fiddlehead
+ $ hg debugwalk -I 'rootfilesin:.'
+ f fennel ../fennel
+ f fenugreek ../fenugreek
+ f fiddlehead ../fiddlehead
+ $ hg debugwalk -X 'rootfilesin:'
+ 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 mammals/Procyonidae/cacomistle Procyonidae/cacomistle
+ f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
+ f mammals/Procyonidae/raccoon Procyonidae/raccoon
+ f mammals/skunk skunk
+ $ hg debugwalk 'rootfilesin:fennel'
+ $ hg debugwalk -I 'rootfilesin:fennel'
+ $ hg debugwalk 'rootfilesin:skunk'
+ $ hg debugwalk -I 'rootfilesin:skunk'
+ $ hg debugwalk 'rootfilesin:beans'
+ 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
+ $ hg debugwalk -I 'rootfilesin:beans'
+ 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
+ $ hg debugwalk 'rootfilesin:mammals'
+ f mammals/skunk skunk
+ $ hg debugwalk -I 'rootfilesin:mammals'
+ f mammals/skunk skunk
+ $ hg debugwalk 'rootfilesin:mammals/'
+ f mammals/skunk skunk
+ $ hg debugwalk -I 'rootfilesin:mammals/'
+ f mammals/skunk skunk
+ $ hg debugwalk -X 'rootfilesin: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 .
f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
More information about the Mercurial-devel
mailing list