Patchwork match: adding support for repository-root-based globs

login
register
mail settings
Submitter via Mercurial-devel
Date Nov. 3, 2016, 3:45 a.m.
Message ID <5a24706699632b6b91f1.1478144748@rdamazio.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/17311/
State Superseded
Headers show

Comments

via Mercurial-devel - Nov. 3, 2016, 3:45 a.m.
# HG changeset patch
# User Rodrigo Damazio Bovendorp <rdamazio@google.com>
# Date 1475944120 25200
#      Sat Oct 08 09:28:40 2016 -0700
# Node ID 5a24706699632b6b91f1079549e7ddd0ea952267
# Parent  b032a7b676c6637b2ac6f3ef29431013b15a08f9
match: adding support for repository-root-based globs

The broader plan is to add explicit base directories for all patterns:

Patch

============ ======== ======= ===========
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 5a2470669963 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 5a2470669963 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'), ('glob', '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 5a2470669963 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