aboutsummaryrefslogtreecommitdiff
path: root/bbot/utility.txx
diff options
context:
space:
mode:
Diffstat (limited to 'bbot/utility.txx')
-rw-r--r--bbot/utility.txx144
1 files changed, 144 insertions, 0 deletions
diff --git a/bbot/utility.txx b/bbot/utility.txx
new file mode 100644
index 0000000..d641612
--- /dev/null
+++ b/bbot/utility.txx
@@ -0,0 +1,144 @@
+// file : bbot/utility.txx -*- C++ -*-
+// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <butl/fdstream>
+
+#include <butl/manifest-parser>
+#include <butl/manifest-serializer>
+
+#include <bbot/diagnostics>
+
+namespace bbot
+{
+ template <typename I, typename O, typename E, typename P, typename... A>
+ butl::process_exit::code_type
+ run_exit (tracer& t, I&& in, O&& out, E&& err, const P& p, A&&... args)
+ {
+ using namespace butl;
+
+ try
+ {
+ auto cmdc = [&t] (const char* cmd[], size_t n)
+ {
+ if (verb >= 2)
+ {
+ diag_record dr (t);
+ process::print (dr.os, cmd, n);
+ }
+ };
+
+ process_exit r (process_run (cmdc,
+ forward<I> (in),
+ forward<O> (out),
+ forward<E> (err),
+ dir_path (),
+ p,
+ forward<A> (args)...));
+
+ if (!r.normal ())
+ fail << "process " << p << " terminated abnormally: "
+ << r.description ();
+
+ return r.code ();
+ }
+ catch (const process_error& e)
+ {
+ fail << "unable to execute " << p << ": " << e << endf;
+ }
+ }
+
+ template <typename I, typename O, typename E, typename P, typename... A>
+ void
+ run (tracer& t, I&& in, O&& out, E&& err, const P& p, A&&... args)
+ {
+ if (run_exit (t,
+ forward<I> (in),
+ forward<O> (out),
+ forward<E> (err),
+ p,
+ forward<A> (args)...) != 0)
+ fail << "process " << p << " terminated with non-zero exit code";
+ }
+
+ template <typename T>
+ T
+ parse_manifest (const path& f, const char* what, bool ignore_unknown)
+ {
+ using namespace butl;
+
+ try
+ {
+ if (!file_exists (f))
+ fail << what << " manifest file " << f << " does not exist";
+
+ ifdstream ifs (f);
+ manifest_parser p (ifs, f.string ());
+ return T (p, ignore_unknown);
+ }
+ catch (const manifest_parsing& e)
+ {
+ fail << "invalid " << what << " manifest: "
+ << f << ':' << e.line << ':' << e.column << ": " << e.description
+ << endf;
+ }
+ catch (const io_error& e)
+ {
+ fail << "unable to read " << what << " manifest " << f << ": " << e
+ << endf;
+ }
+ catch (const system_error& e) // EACCES, etc.
+ {
+ fail << "unable to access " << what << " manifest " << f << ": " << e
+ << endf;
+ }
+ }
+
+ template <typename T>
+ void
+ serialize_manifest (const T& m, const path& f, const char* what)
+ {
+ using namespace std;
+ using namespace butl;
+
+ try
+ {
+ ofdstream ofs (f, ios::binary);
+ auto_rmfile arm (f); // Try to remove on failure ignoring errors.
+
+ serialize_manifest (m, ofs, f.string (), what);
+
+ ofs.close ();
+ arm.cancel ();
+ }
+ catch (const system_error& e) // EACCES, etc.
+ {
+ fail << "unable to access " << what << " manifest " << f << ": " << e;
+ }
+ }
+
+ template <typename T>
+ void
+ serialize_manifest (const T& m,
+ ostream& os,
+ const string& name,
+ const char* what)
+ {
+ using namespace std;
+ using namespace butl;
+
+ try
+ {
+ manifest_serializer s (os, name);
+ m.serialize (s);
+ }
+ catch (const manifest_serialization& e)
+ {
+ fail << "invalid " << what << " manifest: " << e.description;
+ }
+ catch (const io_error& e)
+ {
+ fail << "unable to write " << what << " manifest " << name << ": " << e;
+ }
+ }
+}