diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2017-06-20 20:33:52 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2017-06-21 13:09:10 +0300 |
commit | 5c186f901ea7d1b09ab551a3fd2a6c1fd2426d59 (patch) | |
tree | aa41f235d3ef632c481390745bc0d589bd9c554e /libbbot/manifest.cxx | |
parent | 4ef51955f2c0c2da17bb922d52fd39eae0bf4464 (diff) |
Add support for build configuration warning-detecting regexes
Diffstat (limited to 'libbbot/manifest.cxx')
-rw-r--r-- | libbbot/manifest.cxx | 150 |
1 files changed, 103 insertions, 47 deletions
diff --git a/libbbot/manifest.cxx b/libbbot/manifest.cxx index 56c5f1d..dae6e3e 100644 --- a/libbbot/manifest.cxx +++ b/libbbot/manifest.cxx @@ -4,6 +4,7 @@ #include <libbbot/manifest.hxx> +#include <regex> #include <vector> #include <string> #include <cctype> // isxdigit() @@ -14,6 +15,7 @@ #include <cstdint> // uint64_t #include <stdexcept> // invalid_argument +#include <libbutl/regex.hxx> #include <libbutl/base64.hxx> #include <libbutl/utility.hxx> // digit() #include <libbutl/tab-parser.hxx> @@ -33,8 +35,6 @@ namespace bbot using serialization = manifest_serialization; using name_value = manifest_name_value; - using strings = vector<string>; - // result_status // string @@ -390,6 +390,57 @@ namespace bbot if (nv.value != "1") bad_value ("unsupported format version"); + // Parse value represented as a whitespace-separated list of quoted + // strings (quoting is validated and preserved) and validate each string + // with the function specified. + // + auto parse_tab = [&bad_value] ( + const string& value, + const function<void (const string&)>& check, + const string& what) -> strings + { + strings r; + + // Note that when reporting errors we combine the manifest value + // position with the respective field and error positions. + // + try + { + istringstream is (value); + tab_parser parser (is, ""); + + // Here we naturally support multiline value manifest. + // + tab_fields tl; + while (!(tl = parser.next ()).empty ()) + { + for (auto& tf: tl) + { + try + { + check (tf.value); + } + catch (const invalid_argument& e) + { + bad_value (string ("invalid task ") + what + ": " + e.what (), + tf.column - 1, + tl.line - 1); + } + + r.emplace_back (move (tf.value)); + } + } + } + catch (const tab_parsing& e) + { + bad_value ("invalid task " + what + ": " + e.description, + e.column - 1, + e.line - 1); + } + + return r; + }; + // Parse the task manifest. // for (nv = p.next (); !nv.empty (); nv = p.next ()) @@ -483,46 +534,21 @@ namespace bbot if (!config.empty ()) bad_name ("task configuration redefinition"); - // Note that when reporting errors we combine the manifest value - // position with the respective field and error positions. - // - try - { - istringstream is (v); - tab_parser parser (is, ""); - - // Here we naturally support multiline config manifest. - // - tab_fields tl; - while (!(tl = parser.next ()).empty ()) - { - for (auto& tf: tl) - { - try - { - check_config (tf.value); - } - catch (const invalid_argument& e) - { - bad_value (string ("invalid task configuration: ") + e.what (), - tf.column - 1, - tl.line - 1); - } - - config.emplace_back (move (tf.value)); - } - } - } - catch (const tab_parsing& e) - { - bad_value ("invalid task configuration: " + e.description, - e.column - 1, - e.line - 1); - } + config = parse_tab (v, check_config, "configuration"); if (config.empty ()) bad_value ("empty task configuration"); } + else if (n == "warning-regex") + { + if (!warning_regex.empty ()) + bad_name ("task warning regex redefinition"); + + warning_regex = parse_tab (v, check_regex, "warning regex"); + + if (warning_regex.empty ()) + bad_value ("empty task warning regex"); + } else if (!iu) bad_name ("unknown name '" + n + "' in task manifest"); } @@ -561,21 +587,28 @@ namespace bbot if (target) s.next ("target", target->string ()); - // Recompose config string as a space-separated variable list, + // Serialize an optional value of the strings type as a space-separated + // string list. // - if (!config.empty ()) + auto serialize_list = [&s] (const char* name, const strings& value) { - string v; - for (auto b (config.cbegin ()), i (b), e (config.cend ()); i != e; ++i) + if (!value.empty ()) { - if (i != b) - v += ' '; + string v; + for (auto b (value.cbegin ()), i (b), e (value.cend ()); i != e; ++i) + { + if (i != b) + v += ' '; - v += *i; + v += *i; + } + + s.next (name, v); } + }; - s.next ("config", v); - } + serialize_list ("config", config); + serialize_list ("warning-regex", warning_regex); s.next ("", ""); // End of manifest. } @@ -586,6 +619,12 @@ namespace bbot return string_parser::unquote (config); } + strings task_manifest:: + unquoted_warning_regex () const + { + return string_parser::unquote (warning_regex); + } + void task_manifest:: check_config (const string& s) { @@ -609,6 +648,23 @@ namespace bbot throw invalid_argument ("no variable value"); } + void task_manifest:: + check_regex (const string& s) + { + try + { + regex re (string_parser::unquote (s)); + } + catch (const regex_error& e) + { + // Print regex_error description if meaningful (no space). + // + ostringstream os; + os << "invalid regex" << e; + throw invalid_argument (os.str ()); + } + } + // task_response_manifest // task_response_manifest:: |