From 5c186f901ea7d1b09ab551a3fd2a6c1fd2426d59 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 20 Jun 2017 20:33:52 +0300 Subject: Add support for build configuration warning-detecting regexes --- libbbot/manifest.cxx | 150 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 103 insertions(+), 47 deletions(-) (limited to 'libbbot/manifest.cxx') 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 +#include #include #include #include // isxdigit() @@ -14,6 +15,7 @@ #include // uint64_t #include // invalid_argument +#include #include #include // digit() #include @@ -33,8 +35,6 @@ namespace bbot using serialization = manifest_serialization; using name_value = manifest_name_value; - using strings = vector; - // 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& 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:: -- cgit v1.1