From 09c231965f9f8e8f1e86f127a22f112d63ef4d9b Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 20 Apr 2021 22:48:59 +0300 Subject: Add buildscript depdb builtin 'env' command --- libbuild2/build/script/parser.cxx | 29 ++++++++++++++++- libbuild2/build/script/parser.hxx | 13 +++++--- libbuild2/script/parser.cxx | 2 +- libbuild2/script/run.cxx | 2 +- libbuild2/script/script.cxx | 28 +++++++++++++---- libbuild2/script/script.hxx | 9 +++--- tests/recipe/buildscript/testscript | 62 +++++++++++++++++++++++++++++++++++++ 7 files changed, 127 insertions(+), 18 deletions(-) diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx index 4c11688..372c622 100644 --- a/libbuild2/build/script/parser.cxx +++ b/libbuild2/build/script/parser.cxx @@ -481,7 +481,7 @@ namespace build2 next (t, tt); if (tt != type::word || - (v != "clear" && v != "hash" && v != "string")) + (v != "clear" && v != "hash" && v != "string" && v != "env")) { fail (get_location (t)) << "expected 'depdb' builtin command instead of " << t; @@ -950,6 +950,33 @@ namespace build2 << "'depdb string' argument change forcing update of " << ctx.env.target;}); } + else if (cmd == "env") + { + sha256 cs; + const char* pf ("invalid 'depdb env' argument: "); + + try + { + // Skip . + // + for (auto i (ns.begin () + 1); i != ns.end (); ++i) + { + string vn (convert (move (*i))); + build2::script::verify_environment_var_name (vn, pf, ll); + hash_environment (cs, vn); + } + } + catch (const invalid_argument& e) + { + fail (ll) << pf << e; + } + + if (ctx.dd.expect (cs.string ()) != nullptr) + l4 ([&] { + ctx.trace (ll) + << "'depdb env' environment change forcing update of " + << ctx.env.target;}); + } else assert (false); } diff --git a/libbuild2/build/script/parser.hxx b/libbuild2/build/script/parser.hxx index b5a45ca..15429e3 100644 --- a/libbuild2/build/script/parser.hxx +++ b/libbuild2/build/script/parser.hxx @@ -194,13 +194,16 @@ namespace build2 // The depdb builtin can be used to change the default dependency // change tracking: // - // depdb clear - Cancels the default variables, targets, and - // prerequisites change tracking. Can only be - // the first depdb builtin call. + // depdb clear - Cancel the default variables, targets, and + // prerequisites change tracking. Can only be + // the first depdb builtin call. // - // depdb hash - Track the argument list change as a hash. + // depdb hash - Track the argument list change as a hash. // - // depdb string - Track the argument (single) change as string. + // depdb string - Track the argument (single) change as string. + // + // depdb env - Track the environment variables change as a + // hash. // optional depdb_clear_; // 'depdb clear' location if any. lines depdb_preamble_; // Note: excludes 'depdb clear'. diff --git a/libbuild2/script/parser.cxx b/libbuild2/script/parser.cxx index 41d3092..ebfd5fc 100644 --- a/libbuild2/script/parser.cxx +++ b/libbuild2/script/parser.cxx @@ -1437,7 +1437,7 @@ namespace build2 } else if (optional v = str ("--unset", "-u")) { - verify_environment_var_name (*v, o.c_str (), "env: ", i->second); + verify_environment_var_name (*v, "env: ", i->second, o.c_str ()); r.variables.add (move (*v)); } diff --git a/libbuild2/script/run.cxx b/libbuild2/script/run.cxx index 3faa35c..f36e979 100644 --- a/libbuild2/script/run.cxx +++ b/libbuild2/script/run.cxx @@ -781,7 +781,7 @@ namespace build2 // auto verify_name = [&ll] (const string& name, const char* opt) { - verify_environment_var_name (name, opt, "export: ", ll); + verify_environment_var_name (name, "export: ", ll, opt); }; // Parse options (variable set/unset cleanups and unsets). diff --git a/libbuild2/script/script.cxx b/libbuild2/script/script.cxx index db53418..298d71f 100644 --- a/libbuild2/script/script.cxx +++ b/libbuild2/script/script.cxx @@ -818,18 +818,34 @@ namespace build2 // void verify_environment_var_name (const string& name, - const char* opt, const char* prefix, - const location& l) + const location& l, + const char* opt) { if (name.empty ()) - fail (l) << prefix << "empty value for option " << opt; + { + diag_record dr (fail (l)); + dr << prefix << "empty "; + + if (opt == nullptr) + dr << "variable name"; + else + dr << "value for option " << opt; + } if (name.find ('=') != string::npos) - fail (l) << prefix << "invalid value '" << name << "' for option " - << opt << ": contains '='"; - } + { + diag_record dr (fail (l)); + dr << prefix << "invalid "; + + if (opt == nullptr) + dr << "variable name '" << name << "'"; + else + dr << "value '" << name << "' for option " << opt; + dr << ": contains '='"; + } + } void verify_environment_var_assignment (const string& var, diff --git a/libbuild2/script/script.hxx b/libbuild2/script/script.hxx index b4cb7fc..dd31e33 100644 --- a/libbuild2/script/script.hxx +++ b/libbuild2/script/script.hxx @@ -569,14 +569,15 @@ namespace build2 // Helpers. // - // Issue diagnostics with the specified prefix and fail if the string is - // not a valid variable name or assignment (empty, etc). + // Issue diagnostics with the specified prefix and fail if the string + // (potentially an option value) is not a valid variable name or + // assignment (empty, etc). // void verify_environment_var_name (const string&, - const char* opt, const char* prefix, - const location&); + const location&, + const char* opt = nullptr); void verify_environment_var_assignment (const string&, diff --git a/tests/recipe/buildscript/testscript b/tests/recipe/buildscript/testscript index 14036dd..3ccfdd5 100644 --- a/tests/recipe/buildscript/testscript +++ b/tests/recipe/buildscript/testscript @@ -306,6 +306,68 @@ posix = ($cxx.target.class != 'windows') $* clean 2>- } + : env + : + { + : invalid + : + { + cat <=buildfile; + foo: + {{ + s = $getenv(FOO) + + depdb clear + depdb env FOO=bar + echo "$s" >$path($>) + }} + EOI + + $* 2>>/EOE != 0; + buildfile:6:3: error: invalid 'depdb env' argument: invalid variable name 'FOO=bar': contains '=' + info: while updating file{foo} + info: while updating dir{./} + info: failed to update dir{./} + EOE + + $* clean 2>- + } + + : valid + : + { + cat <=buildfile; + foo: + {{ + s = $getenv(FOO) + + depdb clear + depdb env FOO + echo "$s" >$path($>) + }} + EOI + + export FOO=foo; + + $* 2>'echo file{foo}'; + cat <<'foo'; + + $* 2>/'info: dir{./} is up to date'; + + export FOO=bar; + + $* 2>'echo file{foo}'; + cat <<'bar'; + + export -u FOO; + + $* 2>'echo file{foo}'; + cat <<''; + + $* clean 2>- + } + } + : preamble : { -- cgit v1.1