From c3020dee6c91f2694cd098566716f2a4a7794dbe Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 19 Sep 2019 22:37:02 +0300 Subject: Adapt to bracket expressions in wildcard patterns --- mod/build-config-module.cxx | 34 +++++++++++-------- mod/mod-builds.cxx | 81 ++++++++++++++++++++++++++++++++------------- 2 files changed, 79 insertions(+), 36 deletions(-) diff --git a/mod/build-config-module.cxx b/mod/build-config-module.cxx index d21849e..1efc514 100644 --- a/mod/build-config-module.cxx +++ b/mod/build-config-module.cxx @@ -362,36 +362,44 @@ namespace brep } path build_config_module:: - dash_components_to_path (const string& s) + dash_components_to_path (const string& pattern) { string r; - for (size_t i (0); i != s.size (); ++i) + size_t nstar (0); + for (const path_pattern_term& pt: path_pattern_iterator (pattern)) { - char c (s[i]); - - switch (c) + switch (pt.type) { - case '-': + case path_pattern_term_type::star: { - r += '/'; + // Replace ** with */**/* and skip all the remaining stars that may + // follow in this sequence. + // + if (nstar == 0) + r += "*"; + else if (nstar == 1) + r += "/**/*"; // The first star is already copied. + break; } - case '*': + case path_pattern_term_type::literal: { - if (s[i + 1] == '*') // Can be '\0'. + // Replace '-' with '/' and fall through otherwise. + // + if (get_literal (pt) == '-') { - r += "*/**/*"; - ++i; + r += '/'; break; } } // Fall through. default: { - r += c; - break; + r.append (pt.begin, pt.end); // Copy the pattern term as is. } } + + nstar = pt.star () ? nstar + 1 : 0; } // Append the trailing slash to match the resulting paths as directories. diff --git a/mod/mod-builds.cxx b/mod/mod-builds.cxx index 71e7f7b..640c172 100644 --- a/mod/mod-builds.cxx +++ b/mod/mod-builds.cxx @@ -13,7 +13,8 @@ #include #include // to_string() -#include // path_match() +#include // path_match(), path_pattern(), literal(), + // path_pattern_iterator #include // to_result_status(), to_string(result_status) @@ -66,32 +67,69 @@ init (scanner& s) options_->root (dir_path ("/")); } -// Transform the wildcard to the LIKE-pattern. +// Transform the wildcard to the SIMILAR TO-pattern. // static string -transform (const string& s) +transform (const string& pattern) { - if (s.empty ()) + if (pattern.empty ()) return "%"; string r; - for (char c: s) + for (const path_pattern_term& pt: path_pattern_iterator (pattern)) { - switch (c) + switch (pt.type) { - case '*': c = '%'; break; - case '?': c = '_'; break; - case '\\': - case '%': - case '_': r += '\\'; break; - } + case path_pattern_term_type::question: r += '_'; break; + case path_pattern_term_type::star: r += '%'; break; + case path_pattern_term_type::bracket: + { + // Copy the bracket expression translating the inverse character, if + // present. + // + size_t n (r.size ()); + r.append (pt.begin, pt.end); + + if (r[n + 1] == '!') // ...[!... ? + r[n + 1] = '^'; + + break; + } + case path_pattern_term_type::literal: + { + char c (get_literal (pt)); + + // Escape the special characters. + // + // Note that '.' is not a special character for SIMILAR TO. + // + switch (c) + { + case '\\': + case '%': + case '_': + case '|': + case '+': + case '{': + case '(': r += '\\'; break; + } - r += c; + r += c; + break; + } + } } return r; } +template +static inline query +match (const C qc, const string& pattern) +{ + return qc + "SIMILAR TO" + query::_val (transform (pattern)); +} + template static inline query build_query (const brep::cstrings* configs, @@ -124,8 +162,7 @@ build_query (const brep::cstrings* configs, // Package name. // if (!params.name ().empty ()) - q = q && pid.name.like (package_name (transform (params.name ()), - package_name::raw_string)); + q = q && match (pid.name, params.name ()); // Package version. // @@ -167,17 +204,17 @@ build_query (const brep::cstrings* configs, // Build configuration name. // if (!params.configuration ().empty ()) - q = q && qb::id.configuration.like (transform (params.configuration ())); + q = q && match (qb::id.configuration, params.configuration ()); // Build machine name. // if (!params.machine ().empty ()) - q = q && qb::machine.like (transform (params.machine ())); + q = q && match (qb::machine, params.machine ()); // Build target. // if (!params.target ().empty ()) - q = q && qb::target.like (transform (params.target ())); + q = q && match (qb::target, params.target ()); // Build result. // @@ -250,8 +287,7 @@ package_query (const brep::params::builds& params, // Package name. // if (!params.name ().empty ()) - q = q && qp::id.name.like ( - package_name (transform (params.name ()), package_name::raw_string)); + q = q && match (qp::id.name, params.name ()); // Package version. // @@ -466,9 +502,8 @@ handle (request& rq, response& rs) // We will not display hidden configurations, unless the configuration is // specified explicitly. // - bool exclude_hidden ( - params.configuration ().empty () || - params.configuration ().find_first_of ("*?") != string::npos); + bool exclude_hidden (params.configuration ().empty () || + path_pattern (params.configuration ())); cstrings conf_names; -- cgit v1.1