// file : bbot/utility.txx -*- C++ -*- // copyright : Copyright (c) 2014-2017 Code Synthesis Ltd // license : TBC; see accompanying LICENSE file #include #include #include #include namespace bbot { template process run_io_start (tracer& t, I&& in, O&& out, E&& err, const dir_path& cwd, P&& p, A&&... args) { try { return butl::process_start ( [&t] (const char* c[], size_t n) {run_trace (t, c, n);}, forward (in), forward (out), forward (err), cwd, p, forward (args)...); } catch (const process_error& e) { fail << "unable to execute " << p << ": " << e << endf; } } template process_exit::code_type run_io_finish_exit (tracer&, process& pr, P&& p) { try { pr.wait (); if (!pr.exit->normal ()) fail << "process " << p << " terminated abnormally: " << pr.exit->description (); return pr.exit->code (); } catch (const process_error& e) { fail << "unable to execute " << p << ": " << e << endf; } } template inline void run_io_finish (tracer& t, process& pr, P&& p) { if (run_io_finish_exit (t, pr, p) != 0) fail << "process " << p << " terminated with non-zero exit code"; } template inline process_exit::code_type run_io_exit (tracer& t, I&& in, O&& out, E&& err, const P& p, A&&... args) { process pr (run_io_start (t, forward (in), forward (out), forward (err), dir_path (), p, forward (args)...)); return run_io_finish_exit (t, pr, p); } template inline void run_io (tracer& t, I&& in, O&& out, E&& err, const P& p, A&&... args) { process pr (run_io_start (t, forward (in), forward (out), forward (err), dir_path (), p, forward (args)...)); run_io_finish (t, pr, p); } template 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 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 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; } } }