aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-12-01 19:35:43 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-12-01 22:30:21 +0300
commit49531f69ed251f0caf030e19afbf6a0fd1868aa6 (patch)
treeaae14a5edc1772d30f75aa21de131eb7d7f15ce1
parentabfee51c362cb1ed2e8eb62fec12b3eb5ca03fb0 (diff)
Change path_search() to only match directory absent components in 'match absent' mode
-rw-r--r--libbutl/filesystem.cxx29
-rw-r--r--libbutl/filesystem.mxx8
-rw-r--r--tests/wildcard/testscript134
3 files changed, 115 insertions, 56 deletions
diff --git a/libbutl/filesystem.cxx b/libbutl/filesystem.cxx
index 736426b..2fae1f9 100644
--- a/libbutl/filesystem.cxx
+++ b/libbutl/filesystem.cxx
@@ -1737,32 +1737,11 @@ namespace butl
// component omitted, unless this is the only pattern component.
//
if ((fl & path_match_flags::match_absent) != path_match_flags::none &&
+ pc.to_directory () &&
+ (!pattern_dir.empty () || !simple) &&
pc.string ().find_first_not_of ('*') == string::npos &&
- (!pattern_dir.empty () || !simple))
- {
- // Stripping the (leading) absent-matching pattern component and calling
- // search() with the resulting pattern and the same pattern dir works in
- // most cases, except for a simple pattern. In the latter case, the
- // pattern becomes empty and its type information gets lost. In other
- // words, the patterns a/b/*/ and a/b/* become indistinguishable. Thus,
- // for such a corner case we will strip the leaf from the pattern dir
- // and use it as a pattern, stripping the trailing separator, if
- // required. So for the above examples the search() calls will be as
- // follows:
- //
- // search(b/, a/)
- // search(b, a/)
- //
- const dir_path& d (!simple ? pattern_dir : pattern_dir.directory ());
-
- const path& p (
- !simple ? pattern.leaf (pc) :
- pattern.to_directory () ? pattern_dir.leaf () :
- path (pattern_dir.leaf ().string ())); // Strip the trailing separator.
-
- if (!search (p, d, fl, func, filesystem))
- return false;
- }
+ !search (pattern.leaf (pc), pattern_dir, fl, func, filesystem))
+ return false;
return true;
}
diff --git a/libbutl/filesystem.mxx b/libbutl/filesystem.mxx
index f05e569..cf041c2 100644
--- a/libbutl/filesystem.mxx
+++ b/libbutl/filesystem.mxx
@@ -714,8 +714,12 @@ LIBBUTL_MODEXPORT namespace butl
// set, the `a/*/b` pattern matches not only `a/x/b` path, but also `a/b`.
//
// Note that this does not apply to single-component patterns and the
- // pattern type is always preserved. In particular, the `a/b/*` pattern
- // matches `a/b` but not `a/b/`.
+ // pattern type is always preserved. In particular, the `a/*/` pattern
+ // matches `a/` but not `a`.
+ //
+ // Finally, keep in mind that only absent directory components can be
+ // matched this way. In particular, pattern `a*/*` does not match `ab`
+ // (but `a*/*/` matches `ab/`).
//
match_absent = 0x2,
diff --git a/tests/wildcard/testscript b/tests/wildcard/testscript
index 885a7d5..bc90468 100644
--- a/tests/wildcard/testscript
+++ b/tests/wildcard/testscript
@@ -1154,7 +1154,7 @@
: ignorable-components
:
{
- test.options += -i
+ test.options += -i -n
: middle
:
@@ -1164,25 +1164,58 @@
$* a/**/b a/b >/ a/b
$* a/**/b a/x/b >/ a/x/b
- $* a/***/b a/b >>/EOE
+ $* a/***/b a/b >>/EOO
a/b
a/b
- EOE
+ EOO
+
+ : multiple
+ :
+ {
+ $* a/**/*/b a/b >/ a/b
+
+ $* a/**/*/b a/x/b >>/EOO
+ a/x/b
+ a/x/b
+ EOO
+ }
}
: top-level
:
if ($cxx.target.class != 'windows')
{
- $* -n /*/a /a > /a
- $* -n /*/a /b/a > /b/a
+ $* /*/a /a > /a
+ $* /*/a /b/a > /b/a
+
+ : multiple
+ :
+ {
+ $* /*/*/a /a > /a
+
+ $* /*/*/a /b/a >>EOO
+ /b/a
+ /b/a
+ EOO
+ }
}
: leading
:
{
- $* -n */a a >/ a
- $* -n */a b/a >/ b/a
+ $* */a a >/ a
+ $* */a b/a >/ b/a
+
+ : multiple
+ :
+ {
+ $* */*/a a >/ a
+
+ $* */*/a b/a >>/EOO
+ b/a
+ b/a
+ EOO
+ }
}
: trailing
@@ -1190,45 +1223,88 @@
{
: file
:
+ : Test that the pattern star-only component of the file type does not
+ : match an absent component.
+ :
{
- $* -n a/* a >/ a
- $* -n a/* a/b >/ a/b
+ $* a/* a/b >/ a/b
+
+ $* a/* a == 1
+ $* a/* a/ == 1
+ $* a/* a/b/ == 1
+
+ : multiple
+ :
+ {
+ $* a/*/* a/b >/ a/b
- $* -n a/* a/ == 1
- $* -n a/* a/b/ == 1
+ $* a/*/* a == 1
+ $* a/*/* a/ == 1
+ $* a/*/* a/b/ == 1
+ }
}
: dir
:
{
- $* -n a/*/ a/ >/ a/
- $* -n a/*/ a/b >/ a/
+ $* a/*/ a/ >/ a/
+ $* a/*/ a/b >/ a/
- $* -n a/*/ a/b/ >>/EOE
+ $* a/*/ a/b/ >>/EOO
a/b/
a/
- EOE
+ EOO
+
+ $* a/*/ a == 1
- $* -n a/*/ a == 1
+ : multiple
+ :
+ {
+ $* a/*/*/ a/ >/ a/
+ $* a/*/*/ a/b >/ a/
+
+ $* a/*/*/ a/b/ >>/EOO
+ a/b/
+ a/b/
+ a/
+ EOO
+
+ $* a/*/*/ a == 1
+ }
}
}
: leading-trailing
{
- $* -n */* a >/ a
- $* -n */* a/b >/ a/b
-
- $* -n */a/* a >/ a
- $* -n */a/* a/b >/ a/b
- $* -n */a/* b/a >/ b/a
- $* -n */a/* c/a/b >/ c/a/b
-
- $* -n **/a/** a >/ a
- $* -n **/a/** a/b/c/d >/ a/b/c/d
- $* -n **/a/** d/c/b/a >/ d/c/b/a
- $* -n **/a/** d/c/b/a/b/c/d >/ d/c/b/a/b/c/d
- }
+ : adjacent
+ :
+ {
+ $* */* a >/ a
+ $* */* a/b >/ a/b
+
+ $* */* a/ == 1
+ }
+ : apart
+ :
+ {
+ $* */a/* a/b >/ a/b
+ $* */a/* c/a/b >/ c/a/b
+ $* */a/* a == 1
+ $* */a/* b/a == 1
+ $* */a/* b/a/ == 1
+
+ : recursive
+ :
+ {
+ $* **/a/** a/b/c/d >/ a/b/c/d
+ $* **/a/** d/c/b/a/b/c/d >/ d/c/b/a/b/c/d
+
+ $* **/a/** a == 1
+ $* **/a/** d/c/b/a == 1
+ }
+ }
+ }
}
}