aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-09-19 22:37:02 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2019-09-27 18:55:52 +0300
commitc3020dee6c91f2694cd098566716f2a4a7794dbe (patch)
tree0233483d45a111ea405a2b0708d39c90f57c78c6
parent41480b8da4a7d039bf3e1ba57339b228188d6b12 (diff)
Adapt to bracket expressions in wildcard patterns
-rw-r--r--mod/build-config-module.cxx34
-rw-r--r--mod/mod-builds.cxx81
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 <odb/transaction.hxx>
#include <libbutl/timestamp.mxx> // to_string()
-#include <libbutl/filesystem.mxx> // path_match()
+#include <libbutl/filesystem.mxx> // path_match(), path_pattern(), literal(),
+ // path_pattern_iterator
#include <libbbot/manifest.hxx> // 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 <typename T, typename C>
+static inline query<T>
+match (const C qc, const string& pattern)
+{
+ return qc + "SIMILAR TO" + query<T>::_val (transform (pattern));
+}
+
template <typename T>
static inline query<T>
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<T> (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<T> (qb::id.configuration, params.configuration ());
// Build machine name.
//
if (!params.machine ().empty ())
- q = q && qb::machine.like (transform (params.machine ()));
+ q = q && match<T> (qb::machine, params.machine ());
// Build target.
//
if (!params.target ().empty ())
- q = q && qb::target.like (transform (params.target ()));
+ q = q && match<T> (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<T> (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;