aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/build/script/script.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-05-26 14:55:40 +0300
committerBoris Kolpackov <boris@codesynthesis.com>2020-05-27 14:38:01 +0200
commitd6581aa9be74e83cc689bfdaae9aaf2e78287975 (patch)
treee741d2c6fcdb567d8c7b897d17f3f0ca2358d307 /libbuild2/build/script/script.cxx
parente6470e37093084251b7ee60a904a78e54d13e31b (diff)
Create build script temporary directory on demand
Diffstat (limited to 'libbuild2/build/script/script.cxx')
-rw-r--r--libbuild2/build/script/script.cxx95
1 files changed, 91 insertions, 4 deletions
diff --git a/libbuild2/build/script/script.cxx b/libbuild2/build/script/script.cxx
index d27a30a..e344b59 100644
--- a/libbuild2/build/script/script.cxx
+++ b/libbuild2/build/script/script.cxx
@@ -3,9 +3,11 @@
#include <libbuild2/build/script/script.hxx>
+#include <libbutl/filesystem.mxx>
+
#include <libbuild2/target.hxx>
-#include <libbuild2/script/parser.hxx>
+#include <libbuild2/build/script/parser.hxx>
using namespace std;
@@ -32,7 +34,9 @@ namespace build2
target (t),
vars (context, false /* global */)
{
- // Set special variables.
+ // Set special variables. Note that the $~ variable is set later and
+ // only if the temporary directory is required for the script
+ // execution (see create_temp_dir() for details).
//
{
// $>
@@ -64,8 +68,76 @@ namespace build2
}
void environment::
- set_variable (string&& nm, names&& val, const string& attrs)
+ create_temp_dir ()
+ {
+ // Create the temporary directory for this run regardless of the
+ // dry-run mode, since some commands still can be executed (see run()
+ // for details). This is also the reason why we are not using the
+ // build2 filesystem API that considers the dry-run mode.
+ //
+ // Note that the directory auto-removal is active.
+ //
+ dir_path& td (temp_dir.path);
+
+ assert (td.empty ()); // Must be called once.
+
+ try
+ {
+ td = dir_path::temp_path ("buildscript");
+ }
+ catch (const system_error& e)
+ {
+ fail << "unable to obtain temporary directory for buildscript "
+ << "execution" << e;
+ }
+
+ mkdir_status r;
+
+ try
+ {
+ r = try_mkdir (td);
+ }
+ catch (const system_error& e)
+ {
+ fail << "unable to create temporary directory '" << td << "': "
+ << e << endf;
+ }
+
+ // Note that the temporary directory can potentially stay after some
+ // abnormally terminated script run. Clean it up and reuse if that's
+ // the case.
+ //
+ if (r == mkdir_status::already_exists)
+ try
+ {
+ butl::rmdir_r (td, false /* dir */);
+ }
+ catch (const system_error& e)
+ {
+ fail << "unable to cleanup temporary directory '" << td << "': "
+ << e;
+ }
+
+ // Set the $~ special variable.
+ //
+ value& v (assign (var_pool.insert<dir_path> ("~")));
+ v = td;
+
+ if (verb >= 3)
+ text << "mkdir " << td;
+ }
+
+ void environment::
+ set_variable (string&& nm,
+ names&& val,
+ const string& attrs,
+ const location& ll)
{
+ // Check if we are trying to modify any of the special variables.
+ //
+ if (parser::special_variable (nm))
+ fail (ll) << "attempt to set '" << nm << "' special variable";
+
// Set the variable value and attributes.
//
const variable& var (var_pool.insert (move (nm)));
@@ -80,7 +152,22 @@ namespace build2
lhs.assign (move (val), &var);
else
{
- build2::script::parser p (context);
+ // If there is an error in the attributes string, our diagnostics
+ // will look like this:
+ //
+ // <attributes>:1:1 error: unknown value attribute x
+ // buildfile:10:1 info: while parsing attributes '[x]'
+ //
+ // Note that the attributes parsing error is the only reason for a
+ // failure.
+ //
+ auto df = make_diag_frame (
+ [attrs, &ll](const diag_record& dr)
+ {
+ dr << info (ll) << "while parsing attributes '" << attrs << "'";
+ });
+
+ parser p (context);
p.apply_value_attributes (&var,
lhs,
value (move (val)),