diff options
Diffstat (limited to 'bbot/utility.txx')
-rw-r--r-- | bbot/utility.txx | 144 |
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; + } + } +} |