From b27f36b7af5186ad66fd1afa6e7fdc742f2aa1bd Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 21 May 2020 22:47:10 +0300 Subject: Make build script to create special files in temporary directory --- libbuild2/build/script/runner.cxx | 97 ++++++++++++++++++++++++++++++++++++++- libbuild2/build/script/script.cxx | 4 +- libbuild2/build/script/script.hxx | 14 ++++-- 3 files changed, 108 insertions(+), 7 deletions(-) (limited to 'libbuild2/build/script') diff --git a/libbuild2/build/script/runner.cxx b/libbuild2/build/script/runner.cxx index 5535bbb..c4a93fd 100644 --- a/libbuild2/build/script/runner.cxx +++ b/libbuild2/build/script/runner.cxx @@ -3,8 +3,12 @@ #include +#include + #include +using namespace butl; + namespace build2 { namespace build @@ -12,15 +16,104 @@ namespace build2 namespace script { void default_runner:: - enter (environment&, const location&) + enter (environment& env, const location& ll) { - // Noop. + // 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 also a reason for not using the build2 + // filesystem API that considers the dry-run mode. + // + // Note that the directory auto-removal is active. + // + dir_path& td (env.temp_dir.path); + + try + { + td = dir_path::temp_path ("build2-build-script"); + } + catch (const system_error& e) + { + // While there can be no fault of the script being currently + // executed let's add the location anyway to ease the + // troubleshooting. And let's stick to that principle down the road. + // + fail (ll) << "unable to obtain temporary directory for buildscript " + << "execution" << e; + } + + mkdir_status r; + + try + { + r = try_mkdir (td); + } + catch (const system_error& e) + { + fail(ll) << "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 (ll) << "unable to cleanup temporary directory '" << td + << "': " << e; + } + + if (verb >= 3) + text << "mkdir " << td; } void default_runner:: leave (environment& env, const location& ll) { clean (env, ll); + + // Note that since the temporary directory may only contain special + // files that are created and registered for cleanup by the script + // running machinery and should all be removed by the above clean() + // function call, its removal failure may not be the script fault but + // potentially a bug or a filesystem problem. Thus, we don't ignore + // the errors and report them. + // + env.temp_dir.cancel (); + + const dir_path& td (env.temp_dir.path); + + try + { + // Note that the temporary directory must be empty to date. + // + rmdir_status r (try_rmdir (td)); + + if (r != rmdir_status::success) + { + diag_record dr (fail (ll)); + dr << "temporary directory '" << td + << (r == rmdir_status::not_exist + ? "' does not exist" + : "' is not empty"); + + if (r == rmdir_status::not_empty) + build2::script::print_dir (dr, td, ll); + } + } + catch (const system_error& e) + { + fail (ll) << "unable to remove temporary directory '" << td << "': " + << e; + } + + if (verb >= 3) + text << "rmdir " << td; } void default_runner:: diff --git a/libbuild2/build/script/script.cxx b/libbuild2/build/script/script.cxx index cbd41c7..b43203c 100644 --- a/libbuild2/build/script/script.cxx +++ b/libbuild2/build/script/script.cxx @@ -24,8 +24,8 @@ namespace build2 : build2::script::environment ( pt.ctx, cast (pt.ctx.global_scope["build.host"]), - work, - wd_name, + work, wd_name, + temp_dir.path, false /* temp_dir_keep */, redirect (redirect_type::none), redirect (redirect_type::merge, 2), redirect (redirect_type::pass)), diff --git a/libbuild2/build/script/script.hxx b/libbuild2/build/script/script.hxx index 29d62aa..f8306e1 100644 --- a/libbuild2/build/script/script.hxx +++ b/libbuild2/build/script/script.hxx @@ -9,6 +9,7 @@ #include #include +#include // auto_rmdir #include @@ -58,9 +59,6 @@ namespace build2 location end_loc; }; - //@@ Does environment need script? Can't we just pass it to parser along - // with environment. - // class environment: public build2::script::environment { public: @@ -83,6 +81,16 @@ namespace build2 // variable_map vars; + // Temporary directory for the script run (see build2::script:: + // environment::temp_dir for details). + // + // Currently this directory is removed regardless of the script + // execution success or failure. Later, to ease the troubleshooting, + // we may invent the build2 option suppressing the directory removal + // on failure. + // + auto_rmdir temp_dir; + virtual void set_variable (string&& name, names&&, const string& attrs) override; -- cgit v1.1