From 0d3248f51515d92d5229cd5e6ef30f1f963d7a5f Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 30 Sep 2019 16:34:41 +0300 Subject: Rename $filesystem.path_match() to $path.match() --- libbuild2/functions-path.cxx | 126 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) (limited to 'libbuild2/functions-path.cxx') 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 + #include #include @@ -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& 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 (move (ns))); }; + // $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[".match"] = [](string name, string pattern) + { + return path_match (name, pattern); + }; + + // Path matching. + // + f["match"] = [](path ent, path pat, optional start) + { + return path_match (ent, pat, start); + }; + + f["match"] = [](path ent, names pat, optional start) + { + return path_match (ent, + convert (move (pat)), + start + ? convert (move (*start)) + : optional ()); + }; + + f["match"] = [](names ent, path pat, optional start) + { + return path_match (convert (move (ent)), + pat, + start + ? convert (move (*start)) + : optional ()); + }; + + // The semantics depends on the presence of the start directory or the + // first two argument syntactic representation. + // + f[".match"] = [](names ent, names pat, optional 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 (move (ent)), // Match as paths. + convert (move (pat)), + start + ? convert (move (*start)) + : optional ()) + : path_match (convert (move (ent)), // Match as strings. + convert (move (pat))); + }; + // Path-specific overloads from builtins. // function_family b (m, "builtin", &path_thunk); -- cgit v1.1