From 8749eeea8723196fa38a9eb7917775cfe8b87ad7 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 22 Nov 2016 12:09:27 +0200 Subject: Use diagnostics facility from libbutl --- bpkg/archive.cxx | 7 +- bpkg/auth.cxx | 6 +- bpkg/checksum.cxx | 9 +- bpkg/database.cxx | 3 +- bpkg/diagnostics | 246 +++++++++------------------------------------- bpkg/diagnostics.cxx | 32 +----- bpkg/fetch.cxx | 11 +-- bpkg/manifest-utility.cxx | 3 +- bpkg/pkg-verify.cxx | 5 +- bpkg/rep-create.cxx | 6 +- bpkg/types | 12 ++- bpkg/utility | 45 +-------- bpkg/utility.cxx | 9 +- 13 files changed, 85 insertions(+), 309 deletions(-) diff --git a/bpkg/archive.cxx b/bpkg/archive.cxx index 89bb0ed..ee3feab 100644 --- a/bpkg/archive.cxx +++ b/bpkg/archive.cxx @@ -125,12 +125,11 @@ namespace bpkg // archive name. So print the error message whatever the child exit status // is. // - error << "unable to extract " << f << " from " << a; - throw failed (); + fail << "unable to extract " << f << " from " << a << endf; } catch (const process_error& e) { - error << "unable to extract " << f << " from " << a << ": " << e.what (); - throw failed (); + fail << "unable to extract " << f << " from " << a << ": " << e.what () + << endf; } } diff --git a/bpkg/auth.cxx b/bpkg/auth.cxx index 4ea0e4b..8cb1ed4 100644 --- a/bpkg/auth.cxx +++ b/bpkg/auth.cxx @@ -420,10 +420,8 @@ namespace bpkg // parsing diagnostics since we were probably parsing garbage. // if (pr.wait ()) - { - error << "invalid certificate for " << repo << ": " << e.what (); - throw failed (); - } + fail << "invalid certificate for " << repo << ": " << e.what () + << endf; // Fall through. } diff --git a/bpkg/checksum.cxx b/bpkg/checksum.cxx index 1254749..3d90edc 100644 --- a/bpkg/checksum.cxx +++ b/bpkg/checksum.cxx @@ -384,10 +384,8 @@ namespace bpkg // While it is reasonable to assuming the child process issued diagnostics, // issue something just in case. // - error << "unable to calculate SHA256 sum using '" << sha256_path << "'" << - info << "re-run with -v for more information"; - - throw failed (); + fail << "unable to calculate SHA256 sum using '" << sha256_path << "'" << + info << "re-run with -v for more information" << endf; } struct memstreambuf: streambuf @@ -425,8 +423,7 @@ namespace bpkg } catch (const io_error& e) { - error << "unable read " << f << ": " << e.what (); - throw failed (); + fail << "unable read " << f << ": " << e.what () << endf; } } } diff --git a/bpkg/database.cxx b/bpkg/database.cxx index 418265c..c5b17a8 100644 --- a/bpkg/database.cxx +++ b/bpkg/database.cxx @@ -98,8 +98,7 @@ namespace bpkg } catch (const database_exception& e) { - error << f << ": " << e.message (); - throw failed (); + fail << f << ": " << e.message () << endf; } } } diff --git a/bpkg/diagnostics b/bpkg/diagnostics index cbf4509..79c87aa 100644 --- a/bpkg/diagnostics +++ b/bpkg/diagnostics @@ -5,16 +5,16 @@ #ifndef BPKG_DIAGNOSTICS #define BPKG_DIAGNOSTICS -#include - #include +#include + #include #include namespace bpkg { - struct diag_record; + using butl::diag_record; // Throw this exception to terminate the process. The handler should // assume that the diagnostics has already been issued. @@ -70,153 +70,10 @@ namespace bpkg template inline void l5 (const F& f) {if (verb >= 5) f ();} template inline void l6 (const F& f) {if (verb >= 6) f ();} - // Diagnostic facility, base infrastructure (potentially reusable). + // Diagnostic facility, base infrastructure. // - extern ostream* diag_stream; - - template struct diag_prologue; - template struct diag_mark; - - typedef void (*diag_epilogue) (const diag_record&); - - struct diag_record - { - template - friend const diag_record& - operator<< (const diag_record& r, const T& x) - { - r.os_ << x; - return r; - } - - diag_record (): empty_ (true), epilogue_ (nullptr) {} - - template - explicit - diag_record (const diag_prologue& p) - : empty_ (true), epilogue_ (nullptr) {*this << p;} - - template - explicit - diag_record (const diag_mark& m) - : empty_ (true), epilogue_ (nullptr) {*this << m;} - - ~diag_record () noexcept(false); - - void - append (diag_epilogue e) const - { - if (e != nullptr) - { - assert (epilogue_ == nullptr); // No multiple epilogues support. - epilogue_ = e; - } - - if (empty_) - empty_ = false; - else - os_ << "\n "; - } - - // Move constructible-only type. - // - /* - @@ libstdc++ doesn't yet have the ostringstream move support. - - diag_record (diag_record&& r) - : os_ (move (r.os_)) - { - empty_ = r.empty_; - r.empty_ = true; - - epilogue_ = r.epilogue_; - r.epilogue_ = nullptr; - } - */ - - diag_record (diag_record&& r) - { - empty_ = r.empty_; - epilogue_ = r.epilogue_; - - if (!empty_) - { - os_ << r.os_.str (); - r.empty_ = true; - r.epilogue_ = nullptr; - } - } - - diag_record& operator= (diag_record&&) = delete; - - diag_record (const diag_record&) = delete; - diag_record& operator= (const diag_record&) = delete; - - public: - mutable std::ostringstream os_; - - private: - mutable bool empty_; - mutable diag_epilogue epilogue_; - }; - - template - struct diag_prologue: B - { - diag_prologue (diag_epilogue e = nullptr): B (), epilogue_ (e) {} - - template - diag_prologue (A&&... a) - : B (forward (a)...), epilogue_ (nullptr) {} - - template - diag_prologue (diag_epilogue e, A&&... a) - : B (forward (a)...), epilogue_ (e) {} - - template - diag_record - operator<< (const T& x) const - { - diag_record r; - r.append (epilogue_); - B::operator() (r); - r << x; - return r; - } - - friend const diag_record& - operator<< (const diag_record& r, const diag_prologue& p) - { - r.append (p.epilogue_); - p (r); - return r; - } - - private: - diag_epilogue epilogue_; - }; - - template - struct diag_mark: B - { - diag_mark (): B () {} - - template - diag_mark (A&&... a): B (forward (a)...) {} - - template - diag_record - operator<< (const T& x) const - { - return B::operator() () << x; - } - - friend const diag_record& - operator<< (const diag_record& r, const diag_mark& m) - { - return r << m (); - } - }; + using butl::diag_stream; + using butl::diag_epilogue; // Diagnostic facility, project specifics. // @@ -233,7 +90,6 @@ namespace bpkg const char* type_; const char* name_; }; - typedef diag_prologue simple_prologue; class location { @@ -262,33 +118,37 @@ namespace bpkg const char* name_; const location loc_; }; - typedef diag_prologue location_prologue; struct basic_mark_base { + using simple_prologue = butl::diag_prologue; + using location_prologue = butl::diag_prologue; + explicit basic_mark_base (const char* type, const char* name = nullptr, - const void* data = nullptr) - : type_ (type), name_ (name), data_ (data) {} + const void* data = nullptr, + diag_epilogue* epilogue = nullptr) + : type_ (type), name_ (name), data_ (data), epilogue_ (epilogue) {} simple_prologue operator() () const { - return simple_prologue (type_, name_); + return simple_prologue (epilogue_, type_, name_); } location_prologue operator() (const location& l) const { - return location_prologue (type_, name_, l); + return location_prologue (epilogue_, type_, name_, l); } template location_prologue operator() (const L& l) const { - return location_prologue (type_, name_, get_location (l, data_)); + return location_prologue ( + epilogue_, type_, name_, get_location (l, data_)); } template @@ -296,6 +156,7 @@ namespace bpkg operator() (F&& f, L&& l, C&& c) const { return location_prologue ( + epilogue_, type_, name_, location (forward (f), forward (l), forward (c))); @@ -305,8 +166,9 @@ namespace bpkg const char* type_; const char* name_; const void* data_; + diag_epilogue* const epilogue_; }; - typedef diag_mark basic_mark; + using basic_mark = butl::diag_mark; extern const basic_mark error; extern const basic_mark warn; @@ -315,8 +177,8 @@ namespace bpkg // trace // - // Also implement the ODB tracer interface so that we can use - // it to trace database statement execution. + // Also implement the ODB tracer interface so that we can use it to trace + // database statement execution. // struct trace_mark_base: basic_mark_base, odb::tracer { @@ -335,60 +197,40 @@ namespace bpkg virtual void deallocate (odb::connection&, const odb::statement&); }; - typedef diag_mark trace_mark; - - typedef trace_mark tracer; + using trace_mark = butl::diag_mark; + using tracer = trace_mark; // fail // - template - struct fail_mark_base + struct fail_mark_base: basic_mark_base { explicit - fail_mark_base (const void* data = nullptr): data_ (data) {} - - simple_prologue - operator() () const - { - return simple_prologue (&epilogue, "error", nullptr); - } - - location_prologue - operator() (const location& l) const - { - return location_prologue (&epilogue, "error", nullptr, l); - } + fail_mark_base (const char* type, + const void* data = nullptr) + : basic_mark_base (type, + nullptr, + data, + [](const diag_record&) {throw failed ();}) {} + }; - template - location_prologue - operator() (const L& l) const - { - return location_prologue ( - &epilogue, "error", nullptr, get_location (l, data_)); - } + using fail_mark = butl::diag_mark; - template - location_prologue - operator() (F&& f, L&& l, C&& c) const + struct fail_end_base + { + [[noreturn]] void + operator() (const diag_record& r) const { - return location_prologue ( - &epilogue, - "error", - nullptr, - location (forward (f), forward (l), forward (c))); + // If we just throw then the record's destructor will see an active + // exception and will not flush the record. + // + r.flush (); + throw failed (); } - - static void - epilogue (const diag_record&) {throw E ();} - - private: - const void* data_; }; + using fail_end = butl::diag_noreturn_end; - template - using fail_mark = diag_mark>; - - extern const fail_mark fail; + extern const fail_mark fail; + extern const fail_end endf; } #endif // BPKG_DIAGNOSTICS diff --git a/bpkg/diagnostics.cxx b/bpkg/diagnostics.cxx index 9d1f96d..82ebb8c 100644 --- a/bpkg/diagnostics.cxx +++ b/bpkg/diagnostics.cxx @@ -48,29 +48,6 @@ namespace bpkg // uint16_t verb; - // Diagnostic facility, base infrastructure. - // - ostream* diag_stream = &cerr; - - diag_record:: - ~diag_record () noexcept(false) - { - // Don't flush the record if this destructor was called as part of - // the stack unwinding. Right now this means we cannot use this - // mechanism in destructors, which is not a big deal, except for - // one place: exception_guard. So for now we are going to have - // this ugly special check which we will be able to get rid of - // once C++17 uncaught_exceptions() becomes available. - // - if (!empty_ && (!uncaught_exception () || exception_unwinding_dtor)) - { - *diag_stream << os_.str () << endl; - - if (epilogue_ != nullptr) - epilogue_ (*this); // Can throw. - } - } - // Diagnostic facility, project specifics. // @@ -120,8 +97,9 @@ namespace bpkg } const basic_mark error ("error"); - const basic_mark warn ("warning"); - const basic_mark info ("info"); - const basic_mark text (nullptr); - const fail_mark fail; + const basic_mark warn ("warning"); + const basic_mark info ("info"); + const basic_mark text (nullptr); + const fail_mark fail ("error"); + const fail_end endf; } diff --git a/bpkg/fetch.cxx b/bpkg/fetch.cxx index 47f4f9b..4ad476b 100644 --- a/bpkg/fetch.cxx +++ b/bpkg/fetch.cxx @@ -632,9 +632,8 @@ namespace bpkg // While it is reasonable to assuming the child process issued // diagnostics, some may not mention the URL. // - error << "unable to fetch " << url << - info << "re-run with -v for more information"; - throw failed (); + fail << "unable to fetch " << url << + info << "re-run with -v for more information" << endf; } static path @@ -682,14 +681,12 @@ namespace bpkg } catch (const manifest_parsing& e) { - error (e.name, e.line, e.column) << e.description; + fail (e.name, e.line, e.column) << e.description << endf; } catch (const io_error& e) { - error << "unable to read from " << f << ": " << e.what (); + fail << "unable to read from " << f << ": " << e.what () << endf; } - - throw failed (); } static const path repositories ("repositories"); diff --git a/bpkg/manifest-utility.cxx b/bpkg/manifest-utility.cxx index 41215cf..95b0089 100644 --- a/bpkg/manifest-utility.cxx +++ b/bpkg/manifest-utility.cxx @@ -78,7 +78,6 @@ namespace bpkg } catch (const invalid_argument& e) { - error << "invalid repository location '" << s << "': " << e.what (); - throw failed (); + fail << "invalid repository location '" << s << "': " << e.what () << endf; } } diff --git a/bpkg/pkg-verify.cxx b/bpkg/pkg-verify.cxx index 9097dab..c26f8e9 100644 --- a/bpkg/pkg-verify.cxx +++ b/bpkg/pkg-verify.cxx @@ -106,9 +106,8 @@ namespace bpkg { // Note: this is not an "invalid package" case, so no diag check. // - error << "unable to extract manifest file from " << af << ": " - << e.what (); - throw failed (); + fail << "unable to extract manifest file from " << af << ": " + << e.what () << endf; } package_manifest diff --git a/bpkg/rep-create.cxx b/bpkg/rep-create.cxx index ac58936..43f052c 100644 --- a/bpkg/rep-create.cxx +++ b/bpkg/rep-create.cxx @@ -167,8 +167,7 @@ namespace bpkg } catch (const system_error& e) { - error << "unable to scan directory " << d << ": " << e.what (); - throw failed (); + fail << "unable to scan directory " << d << ": " << e.what () << endf; } int @@ -278,7 +277,6 @@ namespace bpkg } catch (const invalid_path& e) { - error << "invalid path: '" << e.path << "'"; - throw failed (); + fail << "invalid path: '" << e.path << "'" << endf; } } diff --git a/bpkg/types b/bpkg/types index 8bff6bb..e20acfb 100644 --- a/bpkg/types +++ b/bpkg/types @@ -82,11 +82,21 @@ namespace bpkg using paths = std::vector; using dir_paths = std::vector; +} +// In order to be found (via ADL) these have to be either in std:: or in +// butl::. The latter is bad idea since libbutl includes the default +// implementation. +// +namespace std +{ // Custom path printing (with trailing slash for directories). // inline ostream& - operator<< (ostream& os, const path& p) {return os << p.representation ();} + operator<< (ostream& os, const ::butl::path& p) + { + return os << p.representation (); + } } #endif // BPKG_TYPES diff --git a/bpkg/utility b/bpkg/utility index b7dbf36..950a36a 100644 --- a/bpkg/utility +++ b/bpkg/utility @@ -11,7 +11,7 @@ #include // assert() #include // make_move_iterator() -#include // casecmp(), reverse_iterate() +#include // casecmp(), reverse_iterate(), etc #include // uncaught_exception() @@ -35,6 +35,9 @@ namespace bpkg using butl::casecmp; using butl::reverse_iterate; + using butl::exception_guard; + using butl::make_exception_guard; + // Widely-used paths. // extern const dir_path bpkg_dir; // .bpkg/ @@ -112,46 +115,6 @@ namespace bpkg bool quiet = false, const strings& pvars = strings (), const strings& cvars = strings ()); - - // Call a function if there is an exception. - // - - // True means we are in the body of a destructor that is being - // called as part of the exception stack unwindining. Used to - // compensate for the deficiencies of uncaught_exception() until - // C++17 uncaught_exceptions() becomes available. - // - // @@ MT: will have to be TLS. - // - extern bool exception_unwinding_dtor; - - template - struct exception_guard; - - template - inline exception_guard - make_exception_guard (F f) - { - return exception_guard (std::move (f)); - } - - template - struct exception_guard - { - exception_guard (F f): f_ (std::move (f)) {} - ~exception_guard () - { - if (std::uncaught_exception ()) - { - exception_unwinding_dtor = true; - f_ (); - exception_unwinding_dtor = false; - } - } - - private: - F f_; - }; } #endif // BPKG_UTILITY diff --git a/bpkg/utility.cxx b/bpkg/utility.cxx index 206b358..98b5125 100644 --- a/bpkg/utility.cxx +++ b/bpkg/utility.cxx @@ -68,8 +68,7 @@ namespace bpkg } catch (const system_error& e) { - error << "unable to stat path " << f << ": " << e.what (); - throw failed (); + fail << "unable to stat path " << f << ": " << e.what () << endf; } } @@ -82,8 +81,7 @@ namespace bpkg } catch (const system_error& e) { - error << "unable to stat path " << d << ": " << e.what (); - throw failed (); + fail << "unable to stat path " << d << ": " << e.what () << endf; } } @@ -96,8 +94,7 @@ namespace bpkg } catch (const system_error& e) { - error << "unable to scan directory " << d << ": " << e.what (); - throw failed (); + fail << "unable to scan directory " << d << ": " << e.what () << endf; } } -- cgit v1.1