aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/build/script/runner.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-04-28 08:48:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-05-27 15:47:28 +0200
commitb808c255b6a9ddba085bf5646e7d20ec344f2e2d (patch)
tree32730291f7e6de8ef0a227905520dd66fb4ec0f3 /libbuild2/build/script/runner.cxx
parent3552356a87402727e663131994fa87f48b3cd4fb (diff)
Initial support for ad hoc recipes (still work in progress)
Diffstat (limited to 'libbuild2/build/script/runner.cxx')
-rw-r--r--libbuild2/build/script/runner.cxx133
1 files changed, 133 insertions, 0 deletions
diff --git a/libbuild2/build/script/runner.cxx b/libbuild2/build/script/runner.cxx
new file mode 100644
index 0000000..315a248
--- /dev/null
+++ b/libbuild2/build/script/runner.cxx
@@ -0,0 +1,133 @@
+// file : libbuild2/build/script/runner.cxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#include <libbuild2/build/script/runner.hxx>
+
+#include <libbutl/filesystem.mxx> // try_rmdir()
+
+#include <libbuild2/target.hxx>
+#include <libbuild2/script/run.hxx>
+
+using namespace butl;
+
+namespace build2
+{
+ namespace build
+ {
+ namespace script
+ {
+ void default_runner::
+ enter (environment&, const location&)
+ {
+ }
+
+ void default_runner::
+ leave (environment& env, const location& ll)
+ {
+ // Drop cleanups of target paths.
+ //
+ for (auto i (env.cleanups.begin ()); i != env.cleanups.end (); )
+ {
+ const target* m (&env.target);
+ for (; m != nullptr; m = m->adhoc_member)
+ {
+ if (const path_target* pm = m->is_a<path_target> ())
+ if (i->path == pm->path ())
+ break;
+ }
+
+ if (m != nullptr)
+ i = env.cleanups.erase (i);
+ else
+ ++i;
+ }
+
+ clean (env, ll);
+
+ // Remove the temporary directory, if created.
+ //
+ const dir_path& td (env.temp_dir.path);
+
+ if (!td.empty ())
+ {
+ // 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 ();
+
+ try
+ {
+ // Note that the temporary directory must be empty to date.
+ //
+ rmdir_status r (try_rmdir (td));
+
+ if (r != rmdir_status::success)
+ {
+ // 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.
+ //
+ 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::
+ run (environment& env,
+ const command_expr& expr,
+ size_t li,
+ const location& ll)
+ {
+ if (verb >= 3)
+ text << ": " << expr;
+
+ // Run the expression if we are not in the dry-run mode or if it
+ // executes the set or exit builtin and just print the expression
+ // otherwise at verbosity level 2 and up.
+ //
+ if (!env.context.dry_run ||
+ find_if (expr.begin (), expr.end (),
+ [] (const expr_term& et)
+ {
+ const string& p (et.pipe.back ().program.string ());
+ return p == "set" || p == "exit";
+ }) != expr.end ())
+ build2::script::run (env, expr, li, ll);
+ else if (verb >= 2)
+ text << expr;
+ }
+
+ bool default_runner::
+ run_if (environment& env,
+ const command_expr& expr,
+ size_t li, const location& ll)
+ {
+ if (verb >= 3)
+ text << ": ?" << expr;
+
+ return build2::script::run_if (env, expr, li, ll);
+ }
+ }
+ }
+}