aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/functions-filesystem.cxx107
-rw-r--r--libbuild2/functions-path.cxx126
-rw-r--r--libbuild2/functions-project-name.cxx2
-rw-r--r--tests/function/filesystem/testscript79
-rw-r--r--tests/function/path/testscript79
5 files changed, 206 insertions, 187 deletions
diff --git a/libbuild2/functions-filesystem.cxx b/libbuild2/functions-filesystem.cxx
index 701fa74..1594623 100644
--- a/libbuild2/functions-filesystem.cxx
+++ b/libbuild2/functions-filesystem.cxx
@@ -3,7 +3,6 @@
// license : MIT; see accompanying LICENSE file
#include <libbutl/filesystem.mxx>
-#include <libbutl/path-pattern.mxx>
#include <libbuild2/function.hxx>
#include <libbuild2/variable.hxx>
@@ -77,47 +76,6 @@ namespace build2
return r;
}
- using butl::path_match;
-
- // Return true if a path for a filesystem entry matches the pattern. See
- // path_match() overloads (below) for details.
- //
- static bool
- path_match (const path& entry,
- const path& pattern,
- const optional<dir_path>& start)
- {
- // If pattern and entry are both either absolute or relative and
- // non-empty, and the first pattern component is not a self-matching
- // wildcard, then ignore the start directory.
- //
- bool rel (pattern.relative () == entry.relative () &&
- !pattern.empty () && !entry.empty ());
-
- if (rel && !path_pattern_self_matching (pattern))
- return path_match (entry, pattern);
-
- // The start directory must be specified and be absolute.
- //
- if (!start || start->relative ())
- {
- diag_record dr (fail);
-
- // Print paths "as is".
- //
- if (!start)
- dr << "start directory is not specified";
- else
- dr << "start directory path '" << start->representation ()
- << "' is relative";
-
- dr << info << "pattern: '" << pattern.representation () << "'"
- << info << "entry: '" << entry.representation () << "'";
- }
-
- return path_match (entry, pattern, *start);
- }
-
void
filesystem_functions (function_map& m)
{
@@ -149,70 +107,5 @@ namespace build2
return path_search (convert<path> (move (pattern)),
convert<dir_path> (move (start)));
};
-
- // path_match
- //
- // Match a filesystem entry name against a name pattern (both are strings),
- // or a filesystem entry path against a path pattern. For the latter case
- // the start directory may also be required (see below). The semantics of
- // the pattern and name/entry arguments is determined according to the
- // following rules:
- //
- // - The arguments must be of the string or path types, or be untyped.
- //
- // - If one of the arguments is typed, then the other one must be of the
- // same type or be untyped. In the later case, an untyped argument is
- // converted to the type of the other argument.
- //
- // - If both arguments are untyped and the start directory is specified,
- // then the arguments are converted to the path type.
- //
- // - If both arguments are untyped and the start directory is not
- // specified, then, if one of the arguments is syntactically a path (the
- // value contains a directory separator), convert them to the path type,
- // otherwise to the string type (match as names).
- //
- // If pattern and entry paths are both either absolute or relative and
- // non-empty, and the first pattern component is not a self-matching
- // wildcard (doesn't contain ***), then the start directory is not
- // required, and is ignored if specified. Otherwise, the start directory
- // must be specified and be an absolute path.
- //
- // Name matching.
- //
- f["path_match"] = [](string name, string pattern)
- {
- return path_match (name, pattern);
- };
-
- // Path matching.
- //
- f["path_match"] = [](path ent, path pat, optional<dir_path> start)
- {
- return path_match (ent, pat, start);
- };
-
- // The semantics depends on the presence of the start directory or the
- // first two argument syntactic representation.
- //
- f["path_match"] = [](names ent, names pat, optional<names> start)
- {
- auto path_arg = [] (const names& a) -> bool
- {
- return a.size () == 1 &&
- (a[0].directory () ||
- a[0].value.find_first_of (path::traits_type::directory_separators) !=
- string::npos);
- };
-
- return start || path_arg (pat) || path_arg (ent)
- ? path_match (convert<path> (move (ent)), // Match as paths.
- convert<path> (move (pat)),
- start
- ? convert<dir_path> (move (*start))
- : optional<dir_path> ())
- : path_match (convert<string> (move (ent)), // Match as strings.
- convert<string> (move (pat)));
- };
}
}
diff --git a/libbuild2/functions-path.cxx b/libbuild2/functions-path.cxx
index 03f9be3..7188b62 100644
--- a/libbuild2/functions-path.cxx
+++ b/libbuild2/functions-path.cxx
@@ -2,6 +2,8 @@
// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
+#include <libbutl/path-pattern.mxx>
+
#include <libbuild2/function.hxx>
#include <libbuild2/variable.hxx>
@@ -95,6 +97,47 @@ namespace build2
}
}
+ using butl::path_match;
+
+ // Return true if a path matches the pattern. See path_match() overloads
+ // (below) for details.
+ //
+ static bool
+ path_match (const path& entry,
+ const path& pattern,
+ const optional<dir_path>& start)
+ {
+ // If pattern and entry are both either absolute or relative and
+ // non-empty, and the first pattern component is not a self-matching
+ // wildcard, then ignore the start directory.
+ //
+ bool rel (pattern.relative () == entry.relative () &&
+ !pattern.empty () && !entry.empty ());
+
+ if (rel && !path_pattern_self_matching (pattern))
+ return path_match (entry, pattern);
+
+ // The start directory must be specified and be absolute.
+ //
+ if (!start || start->relative ())
+ {
+ diag_record dr (fail);
+
+ // Print paths "as is".
+ //
+ if (!start)
+ dr << "start directory is not specified";
+ else
+ dr << "start directory path '" << start->representation ()
+ << "' is relative";
+
+ dr << info << "pattern: '" << pattern.representation () << "'"
+ << info << "entry: '" << entry.representation () << "'";
+ }
+
+ return path_match (entry, pattern, *start);
+ }
+
void
path_functions (function_map& m)
{
@@ -341,6 +384,89 @@ namespace build2
return extension (convert<path> (move (ns)));
};
+ // $path.match(<val>, <pat> [, <start>])
+ //
+ // Match a filesystem entry name against a name pattern (both are strings),
+ // or a filesystem entry path against a path pattern. For the latter case
+ // the start directory may also be required (see below). The semantics of
+ // the pattern and name/entry arguments is determined according to the
+ // following rules:
+ //
+ // - The arguments must be of the string or path types, or be untyped.
+ //
+ // - If one of the arguments is typed, then the other one must be of the
+ // same type or be untyped. In the later case, an untyped argument is
+ // converted to the type of the other argument.
+ //
+ // - If both arguments are untyped and the start directory is specified,
+ // then the arguments are converted to the path type.
+ //
+ // - If both arguments are untyped and the start directory is not
+ // specified, then, if one of the arguments is syntactically a path (the
+ // value contains a directory separator), convert them to the path type,
+ // otherwise to the string type (match as names).
+ //
+ // If pattern and entry paths are both either absolute or relative and
+ // non-empty, and the first pattern component is not a self-matching
+ // wildcard (doesn't contain ***), then the start directory is not
+ // required, and is ignored if specified. Otherwise, the start directory
+ // must be specified and be an absolute path.
+ //
+ // Name matching.
+ //
+ f[".match"] = [](string name, string pattern)
+ {
+ return path_match (name, pattern);
+ };
+
+ // Path matching.
+ //
+ f["match"] = [](path ent, path pat, optional<dir_path> start)
+ {
+ return path_match (ent, pat, start);
+ };
+
+ f["match"] = [](path ent, names pat, optional<names> start)
+ {
+ return path_match (ent,
+ convert<path> (move (pat)),
+ start
+ ? convert<dir_path> (move (*start))
+ : optional<dir_path> ());
+ };
+
+ f["match"] = [](names ent, path pat, optional<names> start)
+ {
+ return path_match (convert<path> (move (ent)),
+ pat,
+ start
+ ? convert<dir_path> (move (*start))
+ : optional<dir_path> ());
+ };
+
+ // The semantics depends on the presence of the start directory or the
+ // first two argument syntactic representation.
+ //
+ f[".match"] = [](names ent, names pat, optional<names> start)
+ {
+ auto path_arg = [] (const names& a) -> bool
+ {
+ return a.size () == 1 &&
+ (a[0].directory () ||
+ a[0].value.find_first_of (path::traits_type::directory_separators) !=
+ string::npos);
+ };
+
+ return start || path_arg (pat) || path_arg (ent)
+ ? path_match (convert<path> (move (ent)), // Match as paths.
+ convert<path> (move (pat)),
+ start
+ ? convert<dir_path> (move (*start))
+ : optional<dir_path> ())
+ : path_match (convert<string> (move (ent)), // Match as strings.
+ convert<string> (move (pat)));
+ };
+
// Path-specific overloads from builtins.
//
function_family b (m, "builtin", &path_thunk);
diff --git a/libbuild2/functions-project-name.cxx b/libbuild2/functions-project-name.cxx
index f70a1e7..6058742 100644
--- a/libbuild2/functions-project-name.cxx
+++ b/libbuild2/functions-project-name.cxx
@@ -14,7 +14,7 @@ namespace build2
{
function_family f (m, "project_name");
- f["string"] = [](project_name p) {return move (p).string ();};
+ f["string"] = [](project_name p) {return move (p).string ();};
f["base"] = [](project_name p, optional<string> ext)
{
diff --git a/tests/function/filesystem/testscript b/tests/function/filesystem/testscript
index ecda10e..41d4c59 100644
--- a/tests/function/filesystem/testscript
+++ b/tests/function/filesystem/testscript
@@ -71,82 +71,3 @@
EOE
}
}
-
-: path-match
-:
-{
- : string
- :
- : Test overloads for at least one of the first two arguments being of the
- : string type.
- :
- {
- : string-string
- :
- $* <'print $path_match([string] "b", [string] "b*")' >'true'
-
- : untyped-string
- :
- $* <'print $path_match("b", [string] "b*")' >'true'
-
- : string-untyped
- :
- $* <'print $path_match([string] "b", "b*")' >'true'
-
- : path-string
- :
- $* <'print $path_match([path] "b", [string] "b*")' >'true'
- }
-
- : path
- :
- : Test overloads for at least one of the first two arguments being of the
- : path type.
- :
- {
- : path-path
- :
- $* <'print $path_match([path] "a/b", [path] "b**")' >'true'
-
- : path-path-untyped
- :
- $* <'print $path_match([path] "a/b", [path] "b**", "$src_base")' >'true'
-
- : untyped-path
- :
- $* <'print $path_match("a/b", [path] "b**")' >'true'
-
- : untyped-path-dir
- :
- $* <'print $path_match("a/b", [path] "b**", $src_base)' >'true'
-
- : path-untyped
- :
- $* <'print $path_match([path] "a/b", "b**")' >'true'
- }
-
- : untyped
- :
- : Test overloads for the first two arguments being untyped.
- :
- {
- : converted-to-strings
- :
- $* <'print $path_match("b", "b**")' >'true'
-
- : converted-to-paths-due-to
- {
- : pattern
- :
- $* <'print $path_match("a/b/", "b**/")' >'true'
-
- : entry
- :
- $* <'print $path_match("a/b", "b**")' >'true'
-
- : start-dir
- :
- $* <'print $path_match("", "s***/", "$src_base")' >'true'
- }
- }
-}
diff --git a/tests/function/path/testscript b/tests/function/path/testscript
index fb01e37..8059f05 100644
--- a/tests/function/path/testscript
+++ b/tests/function/path/testscript
@@ -107,3 +107,82 @@ p = ($cxx.target.class != 'windows' ? /../foo : 'c:/../foo');
$* <"\$path.normalize\('$p')" 2>>"EOE" != 0
error: invalid path: '$p'
EOE
+
+: path-match
+:
+{
+ : string
+ :
+ : Test overloads for at least one of the first two arguments being of the
+ : string type.
+ :
+ {
+ : string-string
+ :
+ $* <'print $path.match([string] "b", [string] "b*")' >'true'
+
+ : untyped-string
+ :
+ $* <'print $path.match("b", [string] "b*")' >'true'
+
+ : string-untyped
+ :
+ $* <'print $path.match([string] "b", "b*")' >'true'
+
+ : path-string
+ :
+ $* <'print $match([path] "b", [string] "b*")' >'true'
+ }
+
+ : path
+ :
+ : Test overloads for at least one of the first two arguments being of the
+ : path type.
+ :
+ {
+ : path-path
+ :
+ $* <'print $match([path] "a/b", [path] "b**")' >'true'
+
+ : path-untyped-untyped
+ :
+ $* <'print $match([path] "a/b", "b**", "$src_base")' >'true'
+
+ : untyped-path
+ :
+ $* <'print $match("a/b", [path] "b**")' >'true'
+
+ : untyped-path-dir
+ :
+ $* <'print $match("a/b", [path] "b**", $src_base)' >'true'
+
+ : path-untyped
+ :
+ $* <'print $match([path] "a/b", "b**")' >'true'
+ }
+
+ : untyped
+ :
+ : Test overloads for the first two arguments being untyped.
+ :
+ {
+ : converted-to-strings
+ :
+ $* <'print $path.match("b", "b**")' >'true'
+
+ : converted-to-paths-due-to
+ {
+ : pattern
+ :
+ $* <'print $path.match("a/b/", "b**/")' >'true'
+
+ : entry
+ :
+ $* <'print $path.match("a/b", "b**")' >'true'
+
+ : start-dir
+ :
+ $* <'print $path.match("", "s***/", "$src_base")' >'true'
+ }
+ }
+}