From 2a0f39b29c1bea6a4497c0f1826052ffa453af9e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 21 Apr 2016 16:05:13 +0200 Subject: Move module implementation from brep/ to mod/ --- brep/.gitignore | 2 - brep/buildfile | 59 +-- brep/database | 26 -- brep/database-module | 55 --- brep/database-module.cxx | 50 --- brep/database.cxx | 60 --- brep/diagnostics | 306 ---------------- brep/diagnostics.cxx | 30 -- brep/mod-package-details | 42 --- brep/mod-package-details.cxx | 257 ------------- brep/mod-package-search | 42 --- brep/mod-package-search.cxx | 181 --------- brep/mod-package-version-details | 45 --- brep/mod-package-version-details.cxx | 319 ---------------- brep/mod-repository-details | 42 --- brep/mod-repository-details.cxx | 146 -------- brep/mod-repository-root | 60 --- brep/mod-repository-root.cxx | 263 ------------- brep/module | 201 ---------- brep/module.cxx | 410 --------------------- brep/options-types | 32 -- brep/options.cli | 211 ----------- brep/page | 402 -------------------- brep/page.cxx | 693 ----------------------------------- brep/services.cxx | 15 - brep/types-parsers | 57 --- brep/types-parsers.cxx | 114 ------ 27 files changed, 4 insertions(+), 4116 deletions(-) delete mode 100644 brep/database delete mode 100644 brep/database-module delete mode 100644 brep/database-module.cxx delete mode 100644 brep/database.cxx delete mode 100644 brep/diagnostics delete mode 100644 brep/diagnostics.cxx delete mode 100644 brep/mod-package-details delete mode 100644 brep/mod-package-details.cxx delete mode 100644 brep/mod-package-search delete mode 100644 brep/mod-package-search.cxx delete mode 100644 brep/mod-package-version-details delete mode 100644 brep/mod-package-version-details.cxx delete mode 100644 brep/mod-repository-details delete mode 100644 brep/mod-repository-details.cxx delete mode 100644 brep/mod-repository-root delete mode 100644 brep/mod-repository-root.cxx delete mode 100644 brep/module delete mode 100644 brep/module.cxx delete mode 100644 brep/options-types delete mode 100644 brep/options.cli delete mode 100644 brep/page delete mode 100644 brep/page.cxx delete mode 100644 brep/services.cxx delete mode 100644 brep/types-parsers delete mode 100644 brep/types-parsers.cxx (limited to 'brep') diff --git a/brep/.gitignore b/brep/.gitignore index 852a40d..687b168 100644 --- a/brep/.gitignore +++ b/brep/.gitignore @@ -1,5 +1,3 @@ -options -options.?xx package-odb* package.sql package-extra diff --git a/brep/buildfile b/brep/buildfile index 4caf93a..529916a 100644 --- a/brep/buildfile +++ b/brep/buildfile @@ -2,16 +2,10 @@ # copyright : Copyright (c) 2014-2016 Code Synthesis Ltd # license : MIT; see accompanying LICENSE file -define mod: libso -mod{*}: bin.libprefix = mod_ -mod{*}: install = libexec - define sql: file sql{*}: extension = sql sql{*}: install = data -./: lib{brep} mod{brep} sql{package package-extra} - # lib{brep} # import libs += libodb%lib{odb} @@ -28,57 +22,12 @@ lib{brep}: \ {hxx }{ types } \ {hxx }{ utility } \ {hxx }{ version } \ -$libs +{hxx }{ wrapper-traits } \ +$libs \ +sql{package package-extra} -libso{brep}: cxx.export.poptions = -I$out_root -I$src_root +lib{brep}: cxx.export.poptions = -I$out_root -I$src_root # Install into the brep/ subdirectory of, say, /usr/include/. # install.include = $install.include/brep - -# mod{brep} -# -import libs += libstudxml%lib{studxml} - -gen = {hxx ixx cxx}{ options } -src = \ - {hxx cxx}{ database } \ - {hxx cxx}{ database-module } \ - {hxx cxx}{ diagnostics } \ - {hxx cxx}{ mod-package-details } \ - {hxx cxx}{ mod-package-search } \ - {hxx cxx}{ mod-package-version-details } \ - {hxx cxx}{ mod-repository-details } \ - {hxx cxx}{ mod-repository-root } \ - {hxx cxx}{ module } \ - {hxx }{ options-types } \ - {hxx cxx}{ page } \ - { cxx}{ services } \ - {hxx cxx}{ types-parsers } \ - {hxx }{ wrapper-traits } \ - ../web/{hxx cxx}{ mime-url-encoding } \ - ../web/{hxx }{ module } \ - ../web/{hxx }{ xhtml } \ - ../web/{hxx cxx}{ xhtml-fragment } \ -../web/apache/{hxx }{ log } \ -../web/apache/{hxx ixx cxx}{ request } \ -../web/apache/{hxx txx cxx}{ service } \ -../web/apache/{hxx }{ stream } - -mod{brep}: $src $gen lib{brep} $libs - -# Don't install any of the mod{brep} headers. -# -$out_base/{$gen}: install = false -$src_base/{$src}: install = false - -# Set option prefix to the empty value to handle all unknown request parameters -# uniformly with a single catch block. -# -cli.options += --std c++11 -I $src_root --include-with-brackets \ ---include-prefix brep --guard-prefix BREP \ ---cxx-prologue "#include " \ ---cli-namespace brep::cli --generate-file-scanner --suppress-usage \ ---generate-modifier --generate-description --option-prefix "" - -{hxx ixx cxx}{options}: cli{options} diff --git a/brep/database b/brep/database deleted file mode 100644 index d29d4a5..0000000 --- a/brep/database +++ /dev/null @@ -1,26 +0,0 @@ -// file : brep/database -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BREP_DATABASE -#define BREP_DATABASE - -#include // database - -#include -#include - -#include - -namespace brep -{ - // Returns pointer to the shared database instance, creating one on the - // first call. On subsequent calls ensures passed host and port equals - // to ones of the existing database instance throwing runtime_error - // otherwise. Is not thread-safe. - // - shared_ptr - shared_database (const options::db&); -} - -#endif // BREP_DATABASE diff --git a/brep/database-module b/brep/database-module deleted file mode 100644 index 64d5aaf..0000000 --- a/brep/database-module +++ /dev/null @@ -1,55 +0,0 @@ -// file : brep/database-module -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BREP_DATABASE_MODULE -#define BREP_DATABASE_MODULE - -#include // database - -#include -#include - -#include -#include - -namespace brep -{ - // A module that utilises the database. Specifically, it will retry the - // request in the face of recoverable database failures (deadlock, loss of - // connection, etc) up to a certain number of times. - // - class database_module: public module - { - protected: - database_module () = default; - - // Create a shallow copy (handling instance) if initialized and a deep - // copy (context exemplar) otherwise. - // - explicit - database_module (const database_module&); - - // Required to avoid getting warning from clang that - // database_module::init() hides module::init() virtual functions. This - // way all functions get to the same scope and become overloaded set. - // - using module::init; - - void - init (const options::db&); - - virtual bool - handle (request&, response&) = 0; - - protected: - size_t retry_; - shared_ptr db_; - - private: - virtual bool - handle (request&, response&, log&); - }; -} - -#endif // BREP_DATABASE_MODULE diff --git a/brep/database-module.cxx b/brep/database-module.cxx deleted file mode 100644 index 630fd89..0000000 --- a/brep/database-module.cxx +++ /dev/null @@ -1,50 +0,0 @@ -// file : brep/database-module.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include - -#include -#include - -namespace brep -{ - // While currently the user-defined copy constructor is not required (we - // don't need to deep copy nullptr's), it is a good idea to keep the - // placeholder ready for less trivial cases. - // - database_module:: - database_module (const database_module& r) - : module (r), - retry_ (r.retry_), - db_ (r.initialized_ ? r.db_ : nullptr) - { - } - - void database_module:: - init (const options::db& o) - { - retry_ = o.db_retry (); - db_ = shared_database (o); - } - - bool database_module:: - handle (request& rq, response& rs, log& l) - try - { - return module::handle (rq, rs, l); - } - catch (const odb::recoverable& e) - { - if (retry_-- > 0) - { - MODULE_DIAG; - l1 ([&]{trace << e.what () << "; " << retry_ + 1 << " retries left";}); - throw retry (); - } - - throw; - } -} diff --git a/brep/database.cxx b/brep/database.cxx deleted file mode 100644 index 4b56c37..0000000 --- a/brep/database.cxx +++ /dev/null @@ -1,60 +0,0 @@ -// file : brep/database.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include - -#include -#include - -namespace brep -{ - namespace options - { - bool - operator< (const db& x, const db& y) - { - int r; - if ((r = x.db_user ().compare (y.db_user ())) != 0 || - (r = x.db_password ().compare (y.db_password ())) != 0 || - (r = x.db_name ().compare (y.db_name ())) != 0 || - (r = x.db_host ().compare (y.db_host ()))) - return r < 0; - - return x.db_port () < y.db_port (); - } - } - - using namespace odb; - - shared_ptr - shared_database (const options::db& o) - { - static std::map> databases; - - auto i (databases.find (o)); - if (i != databases.end ()) - { - if (shared_ptr d = i->second.lock ()) - return d; - } - - unique_ptr - f (new pgsql::connection_pool_factory (o.db_max_connections ())); - - shared_ptr d ( - make_shared ( - o.db_user (), - o.db_password (), - o.db_name (), - o.db_host (), - o.db_port (), - "options='-c default_transaction_isolation=serializable'", - move (f))); - - databases[o] = d; - return d; - } -} diff --git a/brep/diagnostics b/brep/diagnostics deleted file mode 100644 index b5b1b36..0000000 --- a/brep/diagnostics +++ /dev/null @@ -1,306 +0,0 @@ -// file : brep/diagnostics -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BREP_DIAGNOSTICS -#define BREP_DIAGNOSTICS - -#include - -#include -#include - -namespace brep -{ - struct location - { - location (): line (0), column (0) {} - location (string f, uint64_t l, uint64_t c) - : file (move (f)), line (l), column (c) {} - - string file; - uint64_t line; - uint64_t column; - }; - - enum class severity {error, warning, info, trace}; - - struct diag_entry - { - severity sev; - const char* name {nullptr}; // E.g., a function name in tracing. - location loc; - string msg; - }; - - using diag_data = vector; - - // - // - template struct diag_prologue; - template struct diag_mark; - - using diag_epilogue = function; - - struct diag_record - { - template - friend const diag_record& - operator<< (const diag_record& r, const T& x) - { - r.os_ << x; - return r; - } - - diag_record () = default; - - template - explicit - diag_record (const diag_prologue& p) {*this << p;} // See below. - - template - explicit - diag_record (const diag_mark& m) {*this << m;} // See below. - - ~diag_record () noexcept(false); - - void - append (const diag_epilogue& e) const - { - if (epilogue_ == nullptr) // Keep the first epilogue (think 'fail'). - epilogue_ = &e; - - if (!data_.empty ()) - { - data_.back ().msg = os_.str (); - - // Reset the stream. There got to be a more efficient way to do it. - // - os_.clear (); - os_.str (""); - } - - data_.push_back (diag_entry ()); - } - - diag_entry& - current () const {return data_.back ();} - - // Move constructible-only type. - // - /* - @@ libstdc++ doesn't yet have the ostringstream move support. - - diag_record (diag_record&& r) - : data_ (move (r.data_)), os_ (move (r.os_)) - { - epilogue_ = r.epilogue_; - r.data_.clear (); // Empty. - } - */ - - diag_record (diag_record&& r): data_ (move (r.data_)) - { - if (!data_.empty ()) - os_ << r.os_.str (); - - epilogue_ = r.epilogue_; - r.data_.clear (); // Empty. - } - - diag_record& operator= (diag_record&&) = delete; - - diag_record (const diag_record&) = delete; - diag_record& operator= (const diag_record&) = delete; - - private: - mutable diag_data data_; - mutable std::ostringstream os_; - mutable const diag_epilogue* epilogue_ {nullptr}; - }; - - // Base (B) should provide operator() that configures diag_record. - // - template - struct diag_prologue: B - { - diag_prologue (const diag_epilogue& e): B (), epilogue_ (e) {} - - template - diag_prologue (const 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: - const diag_epilogue& epilogue_; - }; - - // Base (B) should provide operator() that returns diag_prologue. - // - 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 (); - } - }; - - // Prologues. - // - struct simple_prologue_base - { - explicit - simple_prologue_base (severity s, const char* name) - : sev_ (s), name_ (name) {} - - void - operator() (const diag_record& r) const - { - diag_entry& e (r.current ()); - e.sev = sev_; - e.name = name_; - } - - private: - severity sev_; - const char* name_; - }; - typedef diag_prologue simple_prologue; - - struct location_prologue_base - { - location_prologue_base (severity s, - const char* name, - const location& l) - : sev_ (s), name_ (name), loc_ (l) {} - - void - operator() (const diag_record& r) const - { - diag_entry& e (r.current ()); - e.sev = sev_; - e.name = name_; - e.loc = loc_; //@@ I think we can probably move it. - } - - private: - severity sev_; - const char* name_; - const location loc_; - }; - typedef diag_prologue location_prologue; - - // Marks. - // - struct basic_mark_base - { - explicit - basic_mark_base (severity s, - const diag_epilogue& e, - const char* name = nullptr, - const void* data = nullptr) - : sev_ (s), epilogue_ (e), name_ (name), data_ (data) {} - - simple_prologue - operator() () const - { - return simple_prologue (epilogue_, sev_, name_); - } - - location_prologue - operator() (const location& l) const - { - return location_prologue (epilogue_, sev_, name_, l); - } - - template - location_prologue - operator() (const L& l) const - { - // get_location() is the user-supplied ADL-searched function. - // - return location_prologue ( - epilogue_, sev_, name_, get_location (l, data_)); - } - - private: - severity sev_; - const diag_epilogue& epilogue_; - const char* name_; - const void* data_; - }; - typedef diag_mark basic_mark; - - template - struct fail_mark_base - { - explicit - fail_mark_base (const char* name = nullptr, const void* data = nullptr) - : name_ (name), data_ (data) {} - - simple_prologue - operator() () const - { - return simple_prologue (epilogue_, severity::error, name_); - } - - location_prologue - operator() (const location& l) const - { - return location_prologue (epilogue_, severity::error, name_, l); - } - - template - location_prologue - operator() (const L& l) const - { - return location_prologue ( - epilogue_, severity::error, name_, get_location (l, data_)); - } - - static void - epilogue (diag_data&& d) {throw E (move (d));} - - private: - const diag_epilogue epilogue_ {&epilogue}; - const char* name_; - const void* data_; - }; - - template - using fail_mark = diag_mark>; -} - -#endif // BREP_DIAGNOSTICS diff --git a/brep/diagnostics.cxx b/brep/diagnostics.cxx deleted file mode 100644 index b0d122f..0000000 --- a/brep/diagnostics.cxx +++ /dev/null @@ -1,30 +0,0 @@ -// file : brep/diagnostics.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -using namespace std; - -namespace brep -{ - 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 (!data_.empty () && - (!uncaught_exception () /*|| exception_unwinding_dtor*/)) - { - data_.back ().msg = os_.str (); // Save last message. - - assert (epilogue_ != nullptr); - (*epilogue_) (move (data_)); // Can throw. - } - } -} diff --git a/brep/mod-package-details b/brep/mod-package-details deleted file mode 100644 index 4dc6b18..0000000 --- a/brep/mod-package-details +++ /dev/null @@ -1,42 +0,0 @@ -// file : brep/mod-package-details -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BREP_MOD_PACKAGE_DETAILS -#define BREP_MOD_PACKAGE_DETAILS - -#include -#include - -#include -#include - -namespace brep -{ - class package_details: public database_module - { - public: - package_details () = default; - - // Create a shallow copy (handling instance) if initialized and a deep - // copy (context exemplar) otherwise. - // - explicit - package_details (const package_details&); - - virtual bool - handle (request&, response&); - - virtual const cli::options& - cli_options () const {return options::package_details::description ();} - - private: - virtual void - init (cli::scanner&); - - private: - shared_ptr options_; - }; -} - -#endif // BREP_MOD_PACKAGE_DETAILS diff --git a/brep/mod-package-details.cxx b/brep/mod-package-details.cxx deleted file mode 100644 index 10bd72c..0000000 --- a/brep/mod-package-details.cxx +++ /dev/null @@ -1,257 +0,0 @@ -// file : brep/mod-package-details.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -using namespace odb::core; -using namespace brep::cli; - -// While currently the user-defined copy constructor is not required (we don't -// need to deep copy nullptr's), it is a good idea to keep the placeholder -// ready for less trivial cases. -// -brep::package_details:: -package_details (const package_details& r) - : database_module (r), - options_ (r.initialized_ ? r.options_ : nullptr) -{ -} - -void brep::package_details:: -init (scanner& s) -{ - MODULE_DIAG; - - options_ = make_shared ( - s, unknown_mode::fail, unknown_mode::fail); - - database_module::init (*options_); - - if (options_->root ().empty ()) - options_->root (dir_path ("/")); -} - -template -static inline query -search_params (const brep::string& n, const brep::string& q) -{ - using query = query; - - return "(" + - (q.empty () - ? query ("NULL") - : "plainto_tsquery (" + query::_val (q) + ")") + - "," + - query::_val (n) + - ")"; -} - -bool brep::package_details:: -handle (request& rq, response& rs) -{ - using namespace web; - using namespace web::xhtml; - - MODULE_DIAG; - - const size_t res_page (options_->search_results ()); - const dir_path& root (options_->root ()); - - const string& name (*rq.path ().rbegin ()); - const string ename (mime_url_encode (name)); - - params::package_details params; - bool full; - - try - { - name_value_scanner s (rq.parameters ()); - params = params::package_details ( - s, unknown_mode::fail, unknown_mode::fail); - - full = params.form () == page_form::full; - } - catch (const cli::exception& e) - { - throw invalid_request (400, e.what ()); - } - - size_t page (params.page ()); - const string& squery (params.query ()); - - auto url ( - [&ename](bool f = false, - const string& q = "", - size_t p = 0, - const string& a = "") -> string - { - string s ("?"); - string u (ename); - - if (f) { u += "?f=full"; s = "&"; } - if (!q.empty ()) { u += s + "q=" + mime_url_encode (q); s = "&"; } - if (p > 0) { u += s + "p=" + to_string (p); s = "&"; } - if (!a.empty ()) { u += '#' + a; } - return u; - }); - - xml::serializer s (rs.content (), name); - - s << HTML - << HEAD - << TITLE - << name; - - if (!squery.empty ()) - s << " " << squery; - - s << ~TITLE - << CSS_LINKS (path ("package-details.css"), root) - // - // This hack is required to avoid the "flash of unstyled content", which - // happens due to the presence of the autofocus attribute in the input - // element of the search form. The problem appears in Firefox and has a - // (4-year old, at the time of this writing) bug report: - // - // https://bugzilla.mozilla.org/show_bug.cgi?id=712130. - // - << SCRIPT << " " << ~SCRIPT - << ~HEAD - << BODY - << DIV_HEADER (root, options_->logo (), options_->menu ()) - << DIV(ID="content"); - - if (full) - s << CLASS("full"); - - s << DIV(ID="heading") - << H1 << A(HREF=url ()) << name << ~A << ~H1 - << A(HREF=url (!full, squery, page)) - << (full ? "[brief]" : "[full]") - << ~A - << ~DIV; - - session sn; - transaction t (db_->begin ()); - - shared_ptr pkg; - { - latest_package lp; - if (!db_->query_one ( - query( - "(" + query::_val (name) + ")"), lp)) - throw invalid_request (404, "Package '" + name + "' not found"); - - pkg = db_->load (lp.id); - } - - const auto& licenses (pkg->license_alternatives); - - if (page == 0) - { - // Display package details on the first page only. - // - s << H2 << pkg->summary << ~H2; - - static const string id ("description"); - if (const auto& d = pkg->description) - s << (full - ? P_DESCRIPTION (*d, id) - : P_DESCRIPTION (*d, options_->package_description (), - url (!full, squery, page, id))); - - s << TABLE(CLASS="proplist", ID="package") - << TBODY - << TR_LICENSE (licenses) - << TR_URL (pkg->url) - << TR_EMAIL (pkg->email) - << TR_TAGS (pkg->tags, root) - << ~TBODY - << ~TABLE; - } - - auto pkg_count ( - db_->query_value ( - search_params (name, squery))); - - s << FORM_SEARCH (squery) - << DIV_COUNTER (pkg_count, "Version", "Versions"); - - // Enclose the subsequent tables to be able to use nth-child CSS selector. - // - s << DIV; - for (const auto& pr: - db_->query ( - search_params (name, squery) + - "ORDER BY rank DESC, version_epoch DESC, " - "version_canonical_upstream DESC, version_canonical_release DESC, " - "version_revision DESC" + - "OFFSET" + to_string (page * res_page) + - "LIMIT" + to_string (res_page))) - { - shared_ptr p (db_->load (pr.id)); - - s << TABLE(CLASS="proplist version") - << TBODY - << TR_VERSION (name, p->version.string (), root) - - // @@ Shouldn't we skip low priority row ? Don't think so, why? - // - << TR_PRIORITY (p->priority); - - // Comparing objects of the license_alternatives class as being of the - // vector> class, so comments are not considered. - // - if (p->license_alternatives != licenses) - s << TR_LICENSE (p->license_alternatives); - - assert (p->internal ()); - - // @@ Shouldn't we make package location to be a link to the proper - // place of the About page, describing corresponding repository? - // Yes, I think that's sounds reasonable, once we have about. - // Or maybe it can be something more valuable like a link to the - // repository package search page ? - // - // @@ In most cases package location will be the same for all versions - // of the same package. Shouldn't we put package location to the - // package summary part and display it here only if it differs - // from the one in the summary ? - // - // Hm, I am not so sure about this. Consider: stable/testing/unstable. - // - s << TR_LOCATION (p->internal_repository.object_id (), root) - << TR_DEPENDS (p->dependencies, root) - << TR_REQUIRES (p->requirements) - << ~TBODY - << ~TABLE; - } - s << ~DIV; - - t.commit (); - - s << DIV_PAGER (page, pkg_count, res_page, options_->search_pages (), - url (full, squery)) - << ~DIV - << ~BODY - << ~HTML; - - return true; -} diff --git a/brep/mod-package-search b/brep/mod-package-search deleted file mode 100644 index bb762cd..0000000 --- a/brep/mod-package-search +++ /dev/null @@ -1,42 +0,0 @@ -// file : brep/mod-package-search -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BREP_MOD_PACKAGE_SEARCH -#define BREP_MOD_PACKAGE_SEARCH - -#include -#include - -#include -#include - -namespace brep -{ - class package_search: public database_module - { - public: - package_search () = default; - - // Create a shallow copy (handling instance) if initialized and a deep - // copy (context exemplar) otherwise. - // - explicit - package_search (const package_search&); - - virtual bool - handle (request&, response&); - - virtual const cli::options& - cli_options () const {return options::package_search::description ();} - - private: - virtual void - init (cli::scanner&); - - private: - shared_ptr options_; - }; -} - -#endif // BREP_MOD_PACKAGE_SEARCH diff --git a/brep/mod-package-search.cxx b/brep/mod-package-search.cxx deleted file mode 100644 index 9769783..0000000 --- a/brep/mod-package-search.cxx +++ /dev/null @@ -1,181 +0,0 @@ -// file : brep/mod-package-search.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -using namespace odb::core; -using namespace brep::cli; - -// While currently the user-defined copy constructor is not required (we don't -// need to deep copy nullptr's), it is a good idea to keep the placeholder -// ready for less trivial cases. -// -brep::package_search:: -package_search (const package_search& r) - : database_module (r), - options_ (r.initialized_ ? r.options_ : nullptr) -{ -} - -void brep::package_search:: -init (scanner& s) -{ - MODULE_DIAG; - - options_ = make_shared ( - s, unknown_mode::fail, unknown_mode::fail); - - database_module::init (*options_); - - if (options_->root ().empty ()) - options_->root (dir_path ("/")); - - // Check that the database schema matches the current one. It's enough to - // perform the check in just a single module implementation (and we don't - // do in the dispatcher because it doesn't use the database). - // - // Note that the failure can be reported by each web server worker process. - // While it could be tempting to move the check to the - // repository_root::version() function, it would be wrong. The function can - // be called by a different process (usually the web server root one) not - // having the proper permissions to access the database. - // - if (schema_catalog::current_version (*db_) != db_->schema_version ()) - fail << "database schema differs from the current one (module " - << BREP_VERSION_STR << ")"; -} - -template -static inline query -search_param (const brep::string& q) -{ - using query = query; - return "(" + - (q.empty () - ? query ("NULL") - : "plainto_tsquery (" + query::_val (q) + ")") + - ")"; -} - -bool brep::package_search:: -handle (request& rq, response& rs) -{ - using namespace web::xhtml; - - MODULE_DIAG; - - const size_t res_page (options_->search_results ()); - const dir_path& root (options_->root ()); - - params::package_search params; - - try - { - name_value_scanner s (rq.parameters ()); - params = params::package_search ( - s, unknown_mode::fail, unknown_mode::fail); - } - catch (const unknown_argument& e) - { - throw invalid_request (400, e.what ()); - } - - size_t page (params.page ()); - const string& squery (params.query ()); - string squery_param (squery.empty () - ? "" - : "?q=" + web::mime_url_encode (squery)); - - - static const string title ("Packages"); - xml::serializer s (rs.content (), title); - - s << HTML - << HEAD - << TITLE - << title; - - if (!squery.empty ()) - s << " " << squery; - - s << ~TITLE - << CSS_LINKS (path ("package-search.css"), root) - // - // This hack is required to avoid the "flash of unstyled content", which - // happens due to the presence of the autofocus attribute in the input - // element of the search form. The problem appears in Firefox and has a - // (4-year old, at the time of this writing) bug report: - // - // https://bugzilla.mozilla.org/show_bug.cgi?id=712130. - // - << SCRIPT << " " << ~SCRIPT - << ~HEAD - << BODY - << DIV_HEADER (root, options_->logo (), options_->menu ()) - << DIV(ID="content"); - - session sn; - transaction t (db_->begin ()); - - auto pkg_count ( - db_->query_value ( - search_param (squery))); - - s << FORM_SEARCH (squery) - << DIV_COUNTER (pkg_count, "Package", "Packages"); - - // Enclose the subsequent tables to be able to use nth-child CSS selector. - // - s << DIV; - for (const auto& pr: - db_->query ( - search_param (squery) + - "ORDER BY rank DESC, name" + - "OFFSET" + to_string (page * res_page) + - "LIMIT" + to_string (res_page))) - { - shared_ptr p (db_->load (pr.id)); - - s << TABLE(CLASS="proplist package") - << TBODY - << TR_NAME (p->id.name, squery_param, root) - << TR_SUMMARY (p->summary) - << TR_LICENSE (p->license_alternatives) - << TR_TAGS (p->tags, root) - << TR_DEPENDS (p->dependencies, root) - << TR_REQUIRES (p->requirements) - << ~TBODY - << ~TABLE; - } - s << ~DIV; - - t.commit (); - - s << DIV_PAGER (page, pkg_count, res_page, options_->search_pages (), - root.string () + squery_param) - << ~DIV - << ~BODY - << ~HTML; - - return true; -} diff --git a/brep/mod-package-version-details b/brep/mod-package-version-details deleted file mode 100644 index a463511..0000000 --- a/brep/mod-package-version-details +++ /dev/null @@ -1,45 +0,0 @@ -// file : brep/mod-package-version-details -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BREP_MOD_PACKAGE_VERSION_DETAILS -#define BREP_MOD_PACKAGE_VERSION_DETAILS - -#include -#include - -#include -#include - -namespace brep -{ - class package_version_details: public database_module - { - public: - package_version_details () = default; - - // Create a shallow copy (handling instance) if initialized and a deep - // copy (context exemplar) otherwise. - // - explicit - package_version_details (const package_version_details&); - - virtual bool - handle (request&, response&); - - virtual const cli::options& - cli_options () const - { - return options::package_version_details::description (); - } - - private: - virtual void - init (cli::scanner&); - - private: - shared_ptr options_; - }; -} - -#endif // BREP_MOD_PACKAGE_VERSION_DETAILS diff --git a/brep/mod-package-version-details.cxx b/brep/mod-package-version-details.cxx deleted file mode 100644 index 21da41f..0000000 --- a/brep/mod-package-version-details.cxx +++ /dev/null @@ -1,319 +0,0 @@ -// file : brep/mod-package-version-details.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -using namespace std; -using namespace odb::core; -using namespace brep::cli; - -// While currently the user-defined copy constructor is not required (we don't -// need to deep copy nullptr's), it is a good idea to keep the placeholder -// ready for less trivial cases. -// -brep::package_version_details:: -package_version_details (const package_version_details& r) - : database_module (r), - options_ (r.initialized_ ? r.options_ : nullptr) -{ -} - -void brep::package_version_details:: -init (scanner& s) -{ - MODULE_DIAG; - - options_ = make_shared ( - s, unknown_mode::fail, unknown_mode::fail); - - database_module::init (*options_); - - if (options_->root ().empty ()) - options_->root (dir_path ("/")); -} - -bool brep::package_version_details:: -handle (request& rq, response& rs) -{ - using namespace web; - using namespace web::xhtml; - using brep::version; // Not to confuse with module::version. - - MODULE_DIAG; - - const dir_path& root (options_->root ()); - - auto i (rq.path ().rbegin ()); - version ver; - - try - { - ver = version (*i++); - } - catch (const invalid_argument& ) - { - throw invalid_request (400, "invalid package version format"); - } - - const string& sver (ver.string ()); - - assert (i != rq.path ().rend ()); - const string& name (*i); - - params::package_version_details params; - bool full; - - try - { - name_value_scanner s (rq.parameters ()); - params = params::package_version_details ( - s, unknown_mode::fail, unknown_mode::fail); - - full = params.form () == page_form::full; - } - catch (const unknown_argument& e) - { - throw invalid_request (400, e.what ()); - } - - auto url ( - [&sver](bool f = false, const string& a = "") -> string - { - string u (sver); - - if (f) { u += "?f=full"; } - if (!a.empty ()) { u += '#' + a; } - return u; - }); - - const string title (name + " " + sver); - xml::serializer s (rs.content (), title); - - s << HTML - << HEAD - << TITLE << title << ~TITLE - << CSS_LINKS (path ("package-version-details.css"), root) - << ~HEAD - << BODY - << DIV_HEADER (root, options_->logo (), options_->menu ()) - << DIV(ID="content"); - - if (full) - s << CLASS("full"); - - s << DIV(ID="heading") - << H1 - << A(HREF=root / path (mime_url_encode (name))) << name << ~A - << "/" - << A(HREF=url ()) << sver << ~A - << ~H1 - << A(HREF=url (!full)) << (full ? "[brief]" : "[full]") << ~A - << ~DIV; - - bool not_found (false); - shared_ptr pkg; - - session sn; - transaction t (db_->begin ()); - - try - { - pkg = db_->load (package_id (name, ver)); - - // If the requested package turned up to be an "external" one just - // respond that no "internal" package is present. - // - not_found = !pkg->internal (); - } - catch (const object_not_persistent& ) - { - not_found = true; - } - - if (not_found) - throw invalid_request (404, "Package '" + title + "' not found"); - - s << H2 << pkg->summary << ~H2; - - static const string id ("description"); - if (const auto& d = pkg->description) - s << (full - ? P_DESCRIPTION (*d, id) - : P_DESCRIPTION (*d, options_->package_description (), - url (!full, id))); - - assert (pkg->location && pkg->sha256sum); - - s << TABLE(CLASS="proplist", ID="version") - << TBODY - - // Repeat version here since it can be cut out in the header. - // - << TR_VERSION (pkg->version.string ()) - - << TR_PRIORITY (pkg->priority) - << TR_LICENSES (pkg->license_alternatives) - << TR_LOCATION (pkg->internal_repository.object_id (), root) - << TR_DOWNLOAD (pkg->internal_repository.load ()->location.string () + - "/" + pkg->location->string ()) - << TR_SHA256SUM (*pkg->sha256sum) - << ~TBODY - << ~TABLE - - << TABLE(CLASS="proplist", ID="package") - << TBODY - << TR_URL (pkg->url) - << TR_EMAIL (pkg->email); - - const auto& pu (pkg->package_url); - if (pu && *pu != pkg->url) - s << TR_URL (*pu, "pkg-url"); - - const auto& pe (pkg->package_email); - if (pe && *pe != pkg->email) - s << TR_EMAIL (*pe, "pkg-email"); - - s << TR_TAGS (pkg->tags, root) - << ~TBODY - << ~TABLE; - - const auto& ds (pkg->dependencies); - if (!ds.empty ()) - { - s << H3 << "Depends" << ~H3 - << TABLE(CLASS="proplist", ID="depends") - << TBODY; - - for (const auto& da: ds) - { - s << TR(CLASS="depends") - << TH; - - if (da.conditional) - s << "?"; - - s << ~TH - << TD - << SPAN(CLASS="value"); - - for (const auto& d: da) - { - if (&d != &da[0]) - s << " | "; - - shared_ptr p (d.package.load ()); - assert (p->internal () || !p->other_repositories.empty ()); - - shared_ptr r ( - p->internal () - ? p->internal_repository.load () - : p->other_repositories[0].load ()); - - const auto& dcon (d.constraint); - const string& dname (p->id.name); - string ename (mime_url_encode (dname)); - - if (r->url) - { - string u (*r->url + ename); - s << A(HREF=u) << dname << ~A; - - if (dcon) - s << ' ' << A(HREF=u + "/" + p->version.string ()) << *dcon << ~A; - } - else if (p->internal ()) - { - path u (root / path (ename)); - s << A(HREF=u) << dname << ~A; - - if (dcon) - s << ' ' << A(HREF=u / path (p->version.string ())) << *dcon << ~A; - } - else - // Display the dependency as a plain text if no repository URL - // available. - // - s << d; - } - - s << ~SPAN - << SPAN_COMMENT (da.comment) - << ~TD - << ~TR; - } - - s << ~TBODY - << ~TABLE; - } - - t.commit (); - - const auto& rm (pkg->requirements); - if (!rm.empty ()) - { - s << H3 << "Requires" << ~H3 - << TABLE(CLASS="proplist", ID="requires") - << TBODY; - - for (const auto& ra: rm) - { - s << TR(CLASS="requires") - << TH; - - if (ra.conditional) - s << "?"; - - s << ~TH - << TD - << SPAN(CLASS="value"); - - for (const auto& r: ra) - { - if (&r != &ra[0]) - s << " | "; - - s << r; - } - - s << ~SPAN - << SPAN_COMMENT (ra.comment) - << ~TD - << ~TR; - } - - s << ~TBODY - << ~TABLE; - } - - const auto& ch (pkg->changes); - if (!ch.empty ()) - s << H3 << "Changes" << ~H3 - << (full - ? PRE_CHANGES (ch) - : PRE_CHANGES (ch, - options_->package_changes (), - url (!full, "changes"))); - - s << ~DIV - << ~BODY - << ~HTML; - - return true; -} diff --git a/brep/mod-repository-details b/brep/mod-repository-details deleted file mode 100644 index 49ad629..0000000 --- a/brep/mod-repository-details +++ /dev/null @@ -1,42 +0,0 @@ -// file : brep/mod-repository-details -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BREP_MOD_REPOSITORY_DETAILS -#define BREP_MOD_REPOSITORY_DETAILS - -#include -#include - -#include -#include - -namespace brep -{ - class repository_details: public database_module - { - public: - repository_details () = default; - - // Create a shallow copy (handling instance) if initialized and a deep - // copy (context exemplar) otherwise. - // - explicit - repository_details (const repository_details&); - - virtual bool - handle (request&, response&); - - virtual const cli::options& - cli_options () const {return options::repository_details::description ();} - - private: - virtual void - init (cli::scanner&); - - private: - shared_ptr options_; - }; -} - -#endif // BREP_MOD_REPOSITORY_DETAILS diff --git a/brep/mod-repository-details.cxx b/brep/mod-repository-details.cxx deleted file mode 100644 index b0e2b95..0000000 --- a/brep/mod-repository-details.cxx +++ /dev/null @@ -1,146 +0,0 @@ -// file : brep/mod-repository-details.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include // tzset() - -#include -#include // max() - -#include - -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -using namespace std; -using namespace odb::core; -using namespace brep::cli; - -// While currently the user-defined copy constructor is not required (we don't -// need to deep copy nullptr's), it is a good idea to keep the placeholder -// ready for less trivial cases. -// -brep::repository_details:: -repository_details (const repository_details& r) - : database_module (r), - options_ (r.initialized_ ? r.options_ : nullptr) -{ -} - -void brep::repository_details:: -init (scanner& s) -{ - MODULE_DIAG; - - options_ = make_shared ( - s, unknown_mode::fail, unknown_mode::fail); - - database_module::init (*options_); - - if (options_->root ().empty ()) - options_->root (dir_path ("/")); - - tzset (); // To use butl::to_stream() later on. -} - -bool brep::repository_details:: -handle (request& rq, response& rs) -{ - using namespace web::xhtml; - - MODULE_DIAG; - - const dir_path& root (options_->root ()); - - // Make sure no parameters passed. - // - try - { - name_value_scanner s (rq.parameters ()); - params::repository_details (s, unknown_mode::fail, unknown_mode::fail); - } - catch (const unknown_argument& e) - { - throw invalid_request (400, e.what ()); - } - - static const string title ("About"); - xml::serializer s (rs.content (), title); - - s << HTML - << HEAD - << TITLE << title << ~TITLE - << CSS_LINKS (path ("repository-details.css"), root) - << ~HEAD - << BODY - << DIV_HEADER (root, options_->logo (), options_->menu ()) - << DIV(ID="content"); - - transaction t (db_->begin ()); - - using query = query; - - for (const auto& r: - db_->query ( - query::internal + "ORDER BY" + query::priority)) - { - //@@ Feels like a lot of trouble (e.g., id_attribute()) for very - // dubious value. A link to the package search page just for - // this repository would probably be more useful. - // - string id (html_id (r.name)); - s << H1(ID=id) - << A(HREF="#" + web::mime_url_encode (id)) << r.display_name << ~A - << ~H1; - - if (r.summary) - s << H2 << *r.summary << ~H2; - - if (r.description) - s << P_DESCRIPTION (*r.description); - - if (r.email) - { - const email& e (*r.email); - - s << P - << A(HREF="mailto:" + e) << e << ~A; - - if (!e.comment.empty ()) - s << " (" << e.comment << ")"; - - s << ~P; - } - - ostringstream o; - butl::to_stream (o, - max (r.packages_timestamp, r.repositories_timestamp), - "%Y-%m-%d %H:%M:%S%[.N] %Z", - true, - true); - - s << P << o.str () << ~P; - } - - t.commit (); - - s << ~DIV - << ~BODY - << ~HTML; - - return true; -} diff --git a/brep/mod-repository-root b/brep/mod-repository-root deleted file mode 100644 index f2c2ba0..0000000 --- a/brep/mod-repository-root +++ /dev/null @@ -1,60 +0,0 @@ -// file : brep/mod-repository-root -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BREP_MOD_REPOSITORY_ROOT -#define BREP_MOD_REPOSITORY_ROOT - -#include -#include - -#include -#include - -namespace brep -{ - class package_search; - class package_details; - class package_version_details; - class repository_details; - - class repository_root: public module - { - public: - repository_root (); - - // Create a shallow copy (handling instance) if initialized and a deep - // copy (context exemplar) otherwise. - // - explicit - repository_root (const repository_root&); - - private: - virtual bool - handle (request&, response&); - - virtual const cli::options& - cli_options () const {return options::repository_root::description ();} - - virtual option_descriptions - options (); - - virtual void - init (const name_values&); - - virtual void - init (cli::scanner&); - - virtual void - version (); - - private: - shared_ptr package_search_; - shared_ptr package_details_; - shared_ptr package_version_details_; - shared_ptr repository_details_; - shared_ptr options_; - }; -} - -#endif // BREP_MOD_REPOSITORY_ROOT diff --git a/brep/mod-repository-root.cxx b/brep/mod-repository-root.cxx deleted file mode 100644 index 7d0adc9..0000000 --- a/brep/mod-repository-root.cxx +++ /dev/null @@ -1,263 +0,0 @@ -// file : brep/mod-repository-root.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace brep::cli; - -namespace brep -{ - // request_proxy - // - class request_proxy: public request - { - public: - request_proxy (request& r, const name_values& p) - : request_ (r), parameters_ (p) {} - - virtual const path_type& - path () {return request_.path ();} - - virtual const name_values& - parameters () {return parameters_;} - - virtual const name_values& - cookies () {return request_.cookies ();} - - virtual istream& - content (bool buffer) {return request_.content (buffer);} - - private: - request& request_; - const name_values& parameters_; - }; - - // repository_root - // - repository_root:: - repository_root () - : package_search_ (make_shared ()), - package_details_ (make_shared ()), - package_version_details_ (make_shared ()), - repository_details_ (make_shared ()) - { - } - - repository_root:: - repository_root (const repository_root& r) - : module (r), - // - // Deep/shallow-copy sub-modules depending on whether this is an - // exemplar/handler. - // - package_search_ ( - r.initialized_ - ? r.package_search_ - : make_shared (*r.package_search_)), - package_details_ ( - r.initialized_ - ? r.package_details_ - : make_shared (*r.package_details_)), - package_version_details_ ( - r.initialized_ - ? r.package_version_details_ - : make_shared ( - *r.package_version_details_)), - repository_details_ ( - r.initialized_ - ? r.repository_details_ - : make_shared (*r.repository_details_)), - options_ ( - r.initialized_ - ? r.options_ - : nullptr) - { - } - - // Return amalgamation of repository_root and all its sub-modules option - // descriptions. - // - option_descriptions repository_root:: - options () - { - option_descriptions r (module::options ()); - append (r, package_search_->options ()); - append (r, package_details_->options ()); - append (r, package_version_details_->options ()); - append (r, repository_details_->options ()); - return r; - } - - // Initialize sub-modules and parse own configuration options. - // - void repository_root:: - init (const name_values& v) - { - auto sub_init ([this, &v](module& m) - { - m.init (filter (v, m.options ()), *log_); - }); - - // Initialize sub-modules. - // - sub_init (*package_search_); - sub_init (*package_details_); - sub_init (*package_version_details_); - sub_init (*repository_details_); - - // Parse own configuration options. - // - module::init ( - filter (v, convert (options::repository_root::description ()))); - } - - void repository_root:: - init (scanner& s) - { - MODULE_DIAG; - - options_ = make_shared ( - s, unknown_mode::fail, unknown_mode::fail); - - if (options_->root ().empty ()) - options_->root (dir_path ("/")); - } - - bool repository_root:: - handle (request& rq, response& rs) - { - MODULE_DIAG; - - const dir_path& root (options_->root ()); - - const path& rpath (rq.path ()); - if (!rpath.sub (root)) - return false; - - const path& lpath (rpath.leaf (root)); - - // Delegate the request handling to the sub-module. Intercept exception - // handling to add sub-module attribution. - // - auto handle = [&rs, this](module& m, request& rq, const char* name) -> bool - { - try - { - return m.handle (rq, rs, *log_); - } - catch (const invalid_request&) - { - // Preserve invalid_request exception type, so the web server can - // properly respond to the client with a 4XX error code. - // - throw; - } - catch (const std::exception& e) - { - // All exception types inherited from std::exception (and different - // from invalid_request) are handled by the web server as - // std::exception. The only sensible way to handle them is to respond - // to the client with the internal server error (500) code. By that - // reason it is valid to reduce all these types to a single one. - // Note that the server_error exception is handled internally by the - // module::handle() function call. - // - throw runtime_error (string (name) + ": " + e.what ()); - } - }; - - if (lpath.empty ()) - { - // Dispatch request handling to the repository_details or the - // package_search module depending on the function name passed as a - // first HTTP request parameter. The parameter should have no value - // specified. Example: cppget.org/?about - // - const name_values& params (rq.parameters ()); - if (!params.empty () && !params.front ().value) - { - if (params.front ().name == "about") - { - // Cleanup not to confuse the selected module with the unknown - // parameter. - // - name_values p (params); - p.erase (p.begin ()); - - request_proxy rp (rq, p); - repository_details m (*repository_details_); - return handle (m, rp, "repository_details"); - } - - throw invalid_request (400, "unknown function"); - } - else - { - package_search m (*package_search_); - return handle (m, rq, "package_search"); - } - } - else - { - // Dispatch request handling to the package_details or the - // package_version_details module depending on the HTTP request URL path. - // - auto i (lpath.begin ()); - assert (i != lpath.end ()); - - const string& n (*i++); // Package name. - - // Check if this is a package name and not a brep static content files - // (CSS) directory name, a repository directory name, or a special file - // name (the one starting with '.'). - // - // @@ Shouldn't we validate that the package name is not "@", is not - // digit-only, does not start with '.' while parsing and serializing - // the package manifest ? Probably also need to mention these - // contraints in the manifest.txt file. - // - if (n != "@" && n.find_first_not_of ("0123456789") != string::npos && - n[0] != '.') - { - if (i == lpath.end ()) - { - package_details m (*package_details_); - return handle (m, rq, "package_details"); - } - else if (++i == lpath.end ()) - { - package_version_details m (*package_version_details_); - return handle (m, rq, "package_version_details"); - } - } - } - - return false; - } - - void repository_root:: - version () - { - MODULE_DIAG; - - info << "module " << BREP_VERSION_STR - << ", libbrep " << LIBBREP_VERSION_STR - << ", libbpkg " << LIBBPKG_VERSION_STR - << ", libbutl " << LIBBUTL_VERSION_STR; - } -} diff --git a/brep/module b/brep/module deleted file mode 100644 index 7e5763a..0000000 --- a/brep/module +++ /dev/null @@ -1,201 +0,0 @@ -// file : brep/module -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BREP_MODULE -#define BREP_MODULE - -#include - -#include -#include - -#include -#include - -namespace brep -{ - // Bring in commonly used names from the web namespace. - // - // @@ Maybe doing using namespace is the right way to handle this. - // There will, however, most likely be a conflict between - // web::module and our module. Or maybe not, need to try. - // - using web::status_code; - using web::invalid_request; - using web::sequence_error; - using web::option_descriptions; - using web::name_value; - using web::name_values; - using web::request; - using web::response; - using web::log; - - // This exception indicated a server error (5XX). In particular, - // it is thrown by the fail diagnostics stream and is caught by the - // module implementation where it is both logged as an error and - // returned to the user with the 5XX status code. - // - struct server_error - { - diag_data data; - - server_error (diag_data&& d): data (move (d)) {} - }; - - // Every module member function that needs to produce any diagnostics - // shall begin with: - // - // MODULE_DIAG; - // - // This will instantiate the fail, error, warn, info, and trace - // diagnostics streams with the function's name. - // -#define MODULE_DIAG \ - const fail_mark fail (__PRETTY_FUNCTION__); \ - const basic_mark error (severity::error, \ - this->log_writer_, \ - __PRETTY_FUNCTION__); \ - const basic_mark warn (severity::warning, \ - this->log_writer_, \ - __PRETTY_FUNCTION__); \ - const basic_mark info (severity::info, \ - this->log_writer_, \ - __PRETTY_FUNCTION__); \ - const basic_mark trace (severity::trace, \ - this->log_writer_, \ - __PRETTY_FUNCTION__) - - // Adaptation of the web::module to our needs. - // - class module: public web::module - { - // Diagnostics. - // - protected: - // Trace verbosity level. - // - // 0 - tracing disabled. - // 1 - brief information regarding irregular situations, which not being - // an error can be of some interest. - // 2 - @@ TODO: document - // - // While uint8 is more than enough, use uint16 for the ease of printing. - // - uint16_t verb_ = 0; - - template void l1 (const F& f) const {if (verb_ >= 1) f ();} - template void l2 (const F& f) const {if (verb_ >= 2) f ();} - - // Set to true when the module is successfully initialized. - // - bool initialized_ {false}; - - // Implementation details. - // - protected: - module (); - module (const module& ); - - static name_values - filter (const name_values&, const option_descriptions&); - - static option_descriptions - convert (const cli::options&); - - static void - append (option_descriptions& dst, const cli::options& src); - - static void - append (option_descriptions& dst, const option_descriptions& src); - - // Can be used by module implementation to parse HTTP request parameters. - // - class name_value_scanner: public cli::scanner - { - public: - name_value_scanner (const name_values&) noexcept; - - virtual bool - more (); - - virtual const char* - peek (); - - virtual const char* - next (); - - virtual void - skip (); - - private: - const name_values& name_values_; - name_values::const_iterator i_; - bool name_; - }; - - public: - virtual const cli::options& - cli_options () const = 0; - - virtual void - init (cli::scanner&) = 0; - - // Can be overriden by custom request dispatcher to initialize - // sub-modules. - // - virtual void - init (const name_values&); - - virtual void - init (const name_values&, log&); - - virtual bool - handle (request&, response&) = 0; - - virtual bool - handle (request&, response&, log&); - - // web::module interface. - // - public: - // Custom request dispatcher can aggregate its own option descriptions - // with sub-modules option descriptions. In this case it should still call - // the base implementation in order to include the brep::module's options. - // - virtual option_descriptions - options (); - - private: - virtual void - version (log&); - - // Can be overriden by the module implementation to log version, etc. - // - virtual void - version () {} - - name_values - expand_options (const name_values&); - - // Diagnostics implementation details. - // - protected: - log* log_ {nullptr}; // Diagnostics backend provided by the web server. - - private: - // Extract function name from a __PRETTY_FUNCTION__. - // Throw invalid_argument if fail to parse. - // - static string - func_name (const char* pretty_name); - - void - log_write (const diag_data&) const; - - protected: - const diag_epilogue log_writer_; - }; -} - -#endif // BREP_MODULE diff --git a/brep/module.cxx b/brep/module.cxx deleted file mode 100644 index 68969eb..0000000 --- a/brep/module.cxx +++ /dev/null @@ -1,410 +0,0 @@ -// file : brep/module.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include -#include - -#include -#include // strchr() -#include // bind() - -#include -#include - -#include - -using namespace std; -using namespace placeholders; // For std::bind's _1, etc. - -namespace brep -{ - // module - // - bool module:: - handle (request& rq, response& rs, log& l) - { - log_ = &l; - - try - { - // Web server should terminate if initialization failed. - // - assert (initialized_); - - return handle (rq, rs); - } - catch (const server_error& e) - { - log_write (e.data); - - try - { - static const char* sev_str[] = {"error", "warning", "info", "trace"}; - ostream& o (rs.content (500, "text/plain;charset=utf-8")); - - for (const auto& d: e.data) - { - string name; - - try - { - name = func_name (d.name); - } - catch (const invalid_argument&) - { - // Log "pretty" function description, see in log file & fix. - name = d.name; - } - - o << name << ": " << sev_str[static_cast (d.sev)] << ": " - << d.msg << endl; - } - } - catch (const sequence_error&) - { - // We tried to return the error status/description but some - // content has already been written. Nothing we can do about - // it. - } - } - - return true; - } - - option_descriptions module:: - convert (const cli::options& o) - { - option_descriptions r; - append (r, o); - return r; - } - - void module:: - append (option_descriptions& dst, const cli::options& src) - { - for (const auto& o: src) - { - bool v (!o.flag ()); - auto i (dst.emplace (o.name (), v)); - assert (i.first->second == v); // Consistent option/flag. - - for (const auto& a: o.aliases ()) - { - i = dst.emplace (a, v); - assert (i.first->second == v); - } - } - } - - void module:: - append (option_descriptions& dst, const option_descriptions& src) - { - for (const auto& o: src) - { - auto i (dst.emplace (o)); - assert (i.first->second == o.second); // Consistent option/flag. - } - } - - name_values module:: - filter (const name_values& v, const option_descriptions& d) - { - name_values r; - for (const auto& nv: v) - { - if (d.find (nv.name) != d.end ()) - r.push_back (nv); - } - - return r; - } - - // Convert CLI option descriptions to the general interface of option - // descriptions, extend with brep::module own option descriptions. - // - option_descriptions module:: - options () - { - option_descriptions r ({{"conf", true}}); - append (r, options::module::description ()); - append (r, cli_options ()); - return r; - } - - // Expand option list parsing configuration files. - // - name_values module:: - expand_options (const name_values& v) - { - using namespace cli; - - vector argv; - for (const auto& nv: v) - { - argv.push_back (nv.name.c_str ()); - - if (nv.value) - argv.push_back (nv.value->c_str ()); - } - - int argc (argv.size ()); - argv_file_scanner s (0, argc, const_cast (argv.data ()), "conf"); - - name_values r; - const option_descriptions& o (options ()); - - while (s.more ()) - { - string n (s.next ()); - auto i (o.find (n)); - - if (i == o.end ()) - throw unknown_argument (n); - - optional v; - if (i->second) - v = s.next (); - - r.emplace_back (move (n), move (v)); - } - - return r; - } - - // Parse options with a cli-generated scanner. Options verb and conf are - // recognized by brep::module::init while others to be interpreted by the - // derived init(). If there is an option which can not be interpreted - // neither by brep::module nor by the derived class, then the web server - // is terminated with a corresponding error message being logged. Though - // this should not happen if the options() function returned the correct - // set of options. - // - void module:: - init (const name_values& options, log& log) - { - assert (!initialized_); - - log_ = &log; - - try - { - name_values opts (expand_options (options)); - - // Read module implementation configuration. - // - init (opts); - - // Read brep::module configuration. - // - static option_descriptions od ( - convert (options::module::description ())); - - name_values mo (filter (opts, od)); - name_value_scanner s (mo); - options::module o (s, cli::unknown_mode::fail, cli::unknown_mode::fail); - - verb_ = o.verbosity (); - initialized_ = true; - } - catch (const server_error& e) - { - log_write (e.data); - throw runtime_error ("initialization failed"); - } - catch (const cli::exception& e) - { - ostringstream o; - e.print (o); - throw runtime_error (o.str ()); - } - } - - void module:: - init (const name_values& options) - { - name_value_scanner s (options); - init (s); - assert (!s.more ()); // Module didn't handle its options. - } - - module:: - module (): log_writer_ (bind (&module::log_write, this, _1)) {} - - // Custom copy constructor is required to initialize log_writer_ properly. - // - module:: - module (const module& m): module () - { - verb_ = m.verb_; - initialized_ = m.initialized_; - } - -// For function func declared like this: -// using B = std::string (*)(int); -// using A = B (*)(int,int); -// A func(B (*)(char),B (*)(wchar_t)); -// __PRETTY_FUNCTION__ looks like this: -// virtual std::string (* (* brep::search::func(std::string (* (*)(char))(int) -// ,std::string (* (*)(wchar_t))(int)) const)(int, int))(int) -// - string module:: - func_name (const char* pretty_name) - { - const char* e (strchr (pretty_name, ')')); - - if (e && e > pretty_name) - { - // Position e at last matching '(' which is the beginning of the - // argument list.. - // - size_t d (1); - - do - { - switch (*--e) - { - case ')': ++d; break; - case '(': --d; break; - } - } - while (d && e > pretty_name); - - if (!d && e > pretty_name) - { - // Position e at the character following the function name. - // - while (e > pretty_name && - (*e != '(' || *(e - 1) == ' ' || *(e - 1) == ')')) - --e; - - if (e > pretty_name) - { - // Position b at the beginning of the qualified function name. - // - const char* b (e); - while (--b > pretty_name && *b != ' '); - if (*b == ' ') ++b; - - return string (b, e - b); - } - } - } - - throw invalid_argument ("::brep::module::func_name"); - } - - void module:: - log_write (const diag_data& d) const - { - if (log_ == nullptr) - return; // No backend yet. - - //@@ Cast log_ to apache::log and write the records. - // - auto al (dynamic_cast (log_)); - - if (al) - { - // Considered using lambda for mapping but looks too verbose while can - // be a bit safer in runtime. - // - // Use APLOG_INFO (as opposed to APLOG_TRACE1) as a mapping for - // severity::trace. "LogLevel trace1" configuration directive switches - // on the avalanche of log messages from various modules. Would be good - // to avoid wading through them. - // - static int s[] = {APLOG_ERR, APLOG_WARNING, APLOG_INFO, APLOG_INFO}; - - for (const auto& e: d) - { - string name; - - try - { - name = func_name (e.name); - } - catch (const invalid_argument&) - { - // Log "pretty" function description, see in log file & fix. - name = e.name; - } - - al->write (e.loc.file.c_str (), - e.loc.line, - name.c_str (), - s[static_cast (e.sev)], - e.msg.c_str ()); - } - } - } - - void module:: - version (log& l) - { - log_ = &l; - version (); - } - - // module::name_value_scanner - // - module::name_value_scanner:: - name_value_scanner (const name_values& nv) noexcept - : name_values_ (nv), - i_ (nv.begin ()), - name_ (true) - { - } - - bool module::name_value_scanner:: - more () - { - return i_ != name_values_.end (); - } - - const char* module::name_value_scanner:: - peek () - { - if (i_ != name_values_.end ()) - return name_ ? i_->name.c_str () : i_->value->c_str (); - else - throw cli::eos_reached (); - } - - const char* module::name_value_scanner:: - next () - { - if (i_ != name_values_.end ()) - { - const char* r (name_ ? i_->name.c_str () : i_->value->c_str ()); - skip (); - return r; - } - else - throw cli::eos_reached (); - } - - void module::name_value_scanner:: - skip () - { - if (i_ != name_values_.end ()) - { - if (name_) - { - if (i_->value) - name_ = false; - else - ++i_; - } - else - { - ++i_; - name_ = true; - } - } - else - throw cli::eos_reached (); - } -} diff --git a/brep/options-types b/brep/options-types deleted file mode 100644 index 922637b..0000000 --- a/brep/options-types +++ /dev/null @@ -1,32 +0,0 @@ -// file : brep/options-types -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BREP_OPTIONS_TYPES -#define BREP_OPTIONS_TYPES - -#include -#include - -namespace brep -{ - // brep types - // - enum class page_form - { - full, - brief - }; - - struct page_menu - { - string label; - string link; - - page_menu () = default; - page_menu (string b, string l): label (move (b)), link (move (l)) {} - }; - -} - -#endif // BREP_OPTIONS_TYPES diff --git a/brep/options.cli b/brep/options.cli deleted file mode 100644 index d63a561..0000000 --- a/brep/options.cli +++ /dev/null @@ -1,211 +0,0 @@ -// file : brep/options.cli -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -include ; - -include ; - -include ; - -namespace brep -{ - // Web module configuration options. - // - namespace options - { - // Option groups. - // - class module - { - dir_path root = "/" - { - "" - "Repository root. That is, this is the part of the URL between the - host name and the start of the repository. For example, root value - '\cb{/pkg}' means the repository URL is http://example.org/pkg/. - Specify '\cb{/}' to use the web server root (http://example.org/)." - } - - uint16_t verbosity = 0 - { - "", - "Trace verbosity level. Level 0 disables tracing, which is also the - default." - } - }; - - class db - { - string db-user - { - "", - "Database user name. If not specified, then operating system (login) - name is used." - } - - string db-password - { - "", - "Database password. If not specified, then login without password is - expected to work." - } - - string db-name = "brep" - { - "", - "Database name. If not specified, then '\cb{brep}' is used by - default." - } - - string db-host - { - "", - "Database host name, address, or socket. If not specified, then - connect to \cb{localhost} using the operating system-default - mechanism (Unix-domain socket, etc)." - } - - uint16_t db-port = 0 - { - "", - "Database port number. If not specified, the default port is used." - } - - size_t db-max-connections = 5 - { - "", - "The maximum number of concurrent database connections per web server - process. If 0, then no limitation is applied. The default is 5." - } - - size_t db-retry = 10 - { - "", - "The maximum number of times to retry database transactions in the - face of recoverable failures (deadlock, loss of connection, etc). The - default is 10." - } - }; - - class page - { - web::xhtml::fragment logo - { - "", - "Web page logo. It is displayed in the page header aligned to the left - edge. The value is treated as an XHTML5 fragment." - } - - vector menu; - { - "", - "Web page menu. Each entry is displayed in the page header in the - order specified and aligned to the right edge. A link target that - starts with '\cb{/}' or contains '\cb{:}' is used as is. Otherwise, - it is prefixed with the repository web interface root." - } - }; - - class search - { - uint16_t search-results = 10 - { - "", - "Number of results per page. The default is 10." - } - - uint16_t search-pages = 5 - { - "", - "Number of pages in navigation (pager). The default is 5." - } - }; - - class package - { - uint16_t package-description = 500 - { - "", - "Number of package description characters to display in brief pages. - The default is 500 (~ 80 characters * 6 lines)." - } - - uint16_t package-changes = 5000; - { - "", - "Number of package changes characters to display in brief pages. The - default is 5000 (~ 80 chars x 60 lines)." - } - }; - - // Module options. - // - class package_search: search, db, page, module - { - }; - - class package_details: package, search, db, page, module - { - }; - - class package_version_details: package, db, page, module - { - }; - - class repository_details: db, page, module - { - }; - - class repository_root: module - { - }; - } - - // Web module HTTP request parameters. - // - namespace params - { - // Use parameters long names in the C++ code, short aliases (if present) - // in HTTP URL. - // - class package_search - { - // Display package search result list starting from this page. - // - uint16_t page | p; - - // Package search criteria. - // - string query | q; - }; - - class package_details - { - // Display package version search result list starting from this page. - // - uint16_t page | p; - - // Package version search criteria. - // - string query | q; - - // Page form. - // - page_form form | f = page_form::brief; - }; - - class package_version_details - { - // Page form. - // - page_form form | f = page_form::brief; - }; - - class repository_details - { - // No parameters so far. - // - }; - } -} diff --git a/brep/page b/brep/page deleted file mode 100644 index 512c11a..0000000 --- a/brep/page +++ /dev/null @@ -1,402 +0,0 @@ -// file : brep/page -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BREP_PAGE -#define BREP_PAGE - -#include - -#include - -#include -#include - -#include -#include // page_menu - -namespace brep -{ - // Page common building blocks. - // - - // Generates CSS link elements. - // - class CSS_LINKS - { - public: - CSS_LINKS (const path& p, const dir_path& r): path_ (p), root_ (r) {} - - void - operator() (xml::serializer&) const; - - private: - const path& path_; - const dir_path& root_; - }; - - // Generates page header element. - // - class DIV_HEADER - { - public: - DIV_HEADER (const dir_path& root, - const web::xhtml::fragment& logo, - const vector& menu): - root_ (root), logo_ (logo), menu_ (menu) {} - - void - operator() (xml::serializer&) const; - - private: - const dir_path& root_; - const web::xhtml::fragment& logo_; - const vector& menu_; - }; - - // Generates package search form element. - // - class FORM_SEARCH - { - public: - FORM_SEARCH (const string& q): query_ (q) {} - - void - operator() (xml::serializer&) const; - - private: - const string& query_; - }; - - // Generates counter element. - // - // It could be redunant to distinguish between singular and plural word forms - // if it wouldn't be so cheap in English, and phrase '1 Packages' wouldn't - // look that ugly. - // - class DIV_COUNTER - { - public: - DIV_COUNTER (size_t c, const char* s, const char* p) - : count_ (c), singular_ (s), plural_ (p) {} - - void - operator() (xml::serializer&) const; - - private: - size_t count_; - const char* singular_; - const char* plural_; - }; - - // Generates package name element. - // - class TR_NAME - { - public: - TR_NAME (const string& n, const string& q, const dir_path& r) - : name_ (n), query_param_ (q), root_ (r) {} - - void - operator() (xml::serializer&) const; - - private: - const string& name_; - const string& query_param_; - const dir_path& root_; - }; - - // Generates package version element. - // - class TR_VERSION - { - public: - // Display the version as a link to the package version details page. - // - TR_VERSION (const string& p, const string& v, const dir_path& r) - : package_ (&p), version_ (v), root_ (&r) {} - - // Display the version as a regular text. - // - TR_VERSION (const string& v) - : package_ (nullptr), version_ (v), root_ (nullptr) {} - - void - operator() (xml::serializer&) const; - - private: - const string* package_; - const string& version_; - const dir_path* root_; - }; - - // Generates package summary element. - // - class TR_SUMMARY - { - public: - TR_SUMMARY (const string& s): summary_ (s) {} - - void - operator() (xml::serializer&) const; - - private: - const string& summary_; - }; - - // Generates package license alternatives element. - // - class TR_LICENSE - { - public: - TR_LICENSE (const license_alternatives& l): licenses_ (l) {} - - void - operator() (xml::serializer&) const; - - private: - const license_alternatives& licenses_; - }; - - // Generates package license alternatives elements. Differs from TR_LICENSE - // by producing multiple rows instead of a single one. - // - class TR_LICENSES - { - public: - TR_LICENSES (const license_alternatives& l): licenses_ (l) {} - - void - operator() (xml::serializer&) const; - - private: - const license_alternatives& licenses_; - }; - - // Generates package tags element. - // - class TR_TAGS - { - public: - TR_TAGS (const strings& ts, const dir_path& r): tags_ (ts), root_ (r) {} - - void - operator() (xml::serializer&) const; - - private: - const strings& tags_; - const dir_path& root_; - }; - - // Generates package dependencies element. - // - class TR_DEPENDS - { - public: - TR_DEPENDS (const dependencies& d, const dir_path& r) - : dependencies_ (d), root_ (r) {} - - void - operator() (xml::serializer&) const; - - private: - const dependencies& dependencies_; - const dir_path& root_; - }; - - // Generates package requirements element. - // - class TR_REQUIRES - { - public: - TR_REQUIRES (const requirements& r): requirements_ (r) {} - - void - operator() (xml::serializer&) const; - - private: - const requirements& requirements_; - }; - - // Generates url element. - // - class TR_URL - { - public: - TR_URL (const url& u, const char* l = "url"): url_ (u), label_ (l) {} - - void - operator() (xml::serializer&) const; - - private: - const url& url_; - const char* label_; - }; - - // Generates email element. - // - class TR_EMAIL - { - public: - TR_EMAIL (const email& e, const char* l = "email") - : email_ (e), label_ (l) {} - - void - operator() (xml::serializer&) const; - - private: - const email& email_; - const char* label_; - }; - - // Generates package version priority element. - // - class TR_PRIORITY - { - public: - TR_PRIORITY (const priority& p): priority_ (p) {} - - void - operator() (xml::serializer&) const; - - private: - const priority& priority_; - }; - - // Generates package location element. - // - class TR_LOCATION - { - public: - TR_LOCATION (const string& n, const dir_path& r) - : name_ (n), root_ (r) {} - - void - operator() (xml::serializer&) const; - - private: - const string& name_; - const dir_path& root_; - }; - - // Generates package download URL element. - // - class TR_DOWNLOAD - { - public: - TR_DOWNLOAD (const string& u): url_ (u) {} - - void - operator() (xml::serializer&) const; - - private: - const string& url_; - }; - - // Generates sha256sum element. - // - class TR_SHA256SUM - { - public: - TR_SHA256SUM (const string& s): sha256sum_ (s) {} - - void - operator() (xml::serializer&) const; - - private: - const string& sha256sum_; - }; - - // Generates comment element. - // - class SPAN_COMMENT - { - public: - SPAN_COMMENT (const string& c): comment_ (c) {} - - void - operator() (xml::serializer&) const; - - private: - const string& comment_; - }; - - // Generates package description element. - // - class P_DESCRIPTION - { - public: - // Genereate full description. - // - P_DESCRIPTION (const string& d, const string& id = "") - : description_ (d), length_ (d.size ()), url_ (nullptr), id_ (id) {} - - // Genereate brief description. - // - P_DESCRIPTION (const string& d, size_t l, const string& u) - : description_ (d), length_ (l), url_ (&u) {} - - void - operator() (xml::serializer&) const; - - private: - const string& description_; - size_t length_; - const string* url_; // Full page url. - string id_; - }; - - // Generates package description element. - // - class PRE_CHANGES - { - public: - // Genereate full changes info. - // - PRE_CHANGES (const string& c) - : changes_ (c), length_ (c.size ()), url_ (nullptr) {} - - // Genereate brief changes info. - // - PRE_CHANGES (const string& c, size_t l, const string& u) - : changes_ (c), length_ (l), url_ (&u) {} - - void - operator() (xml::serializer&) const; - - private: - const string& changes_; - size_t length_; - const string* url_; // Full page url. - }; - - // Generates paging element. - // - class DIV_PAGER - { - public: - DIV_PAGER (size_t current_page, - size_t item_count, - size_t item_per_page, - size_t page_number_count, - const string& url); - - void - operator() (xml::serializer&) const; - - private: - size_t current_page_; - size_t item_count_; - size_t item_per_page_; - size_t page_number_count_; - const string& url_; - }; - - // Convert the argument to a string representing the valid HTML 5 'id' - // attribute value. - // - string - html_id (const string&); -} - -#endif // BREP_PAGE diff --git a/brep/page.cxx b/brep/page.cxx deleted file mode 100644 index 689ee20..0000000 --- a/brep/page.cxx +++ /dev/null @@ -1,693 +0,0 @@ -// file : brep/page.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include -#include // hex, uppercase, right -#include -#include // setw(), setfill() -#include // min() - -#include - -#include -#include - -#include -#include - -using namespace std; -using namespace xml; -using namespace web; -using namespace web::xhtml; - -namespace brep -{ - // CSS_LINKS - // - void CSS_LINKS:: - operator() (serializer& s) const - { - static const path css ("@"); - - s << *LINK(REL="stylesheet", TYPE="text/css", HREF=root_ / css / path_); - } - - // DIV_HEADER - // - void DIV_HEADER:: - operator() (serializer& s) const - { - if (!logo_.empty () || !menu_.empty ()) - { - s << DIV(ID="header-bar") - << DIV(ID="header"); - - if (!logo_.empty ()) - s << DIV(ID="header-logo") << logo_ << ~DIV; - - if (!menu_.empty ()) - { - s << DIV(ID="header-menu") - << DIV(ID="header-menu-body"); - - for (const auto& m: menu_) - { - const string& l (m.link[0] == '/' || m.link.find (':') != string::npos - ? m.link - : root_.string () + m.link); - - s << A(HREF=l) << m.label << ~A; - } - - s << ~DIV - << ~DIV; - } - - s << ~DIV - << ~DIV; - } - } - - // FORM_SEARCH - // - void FORM_SEARCH:: - operator() (serializer& s) const - { - // The 'action' attribute is optional in HTML5. While the standard doesn't - // specify browser behavior explicitly for the case the attribute is - // ommited, the only reasonable behavior is to default it to the current - // document URL. - // - s << FORM(ID="search") - << TABLE(CLASS="form-table") - << TBODY - << TR - << TD(ID="search-txt") - << *INPUT(TYPE="search", NAME="q", VALUE=query_, - AUTOFOCUS="autofocus") - << ~TD - << TD(ID="search-btn") - << *INPUT(TYPE="submit", VALUE="Search") - << ~TD - << ~TR - << ~TBODY - << ~TABLE - << ~FORM; - } - - // DIV_COUNTER - // - void DIV_COUNTER:: - operator() (serializer& s) const - { - s << DIV(ID="count") - << count_ << " " - << (count_ % 10 == 1 && count_ % 100 != 11 ? singular_ : plural_) - << ~DIV; - } - - // TR_NAME - // - void TR_NAME:: - operator() (serializer& s) const - { - s << TR(CLASS="name") - << TH << "name" << ~TH - << TD - << SPAN(CLASS="value") - << A - << HREF - - // Propagate search criteria to the package details page. - // - << root_ / path (mime_url_encode (name_)) << query_param_ - - << ~HREF - << name_ - << ~A - << ~SPAN - << ~TD - << ~TR; - } - - void TR_VERSION:: - operator() (serializer& s) const - { - s << TR(CLASS="version") - << TH << "version" << ~TH - << TD - << SPAN(CLASS="value"); - - if (package_ == nullptr) - s << version_; - else - { - assert (root_ != nullptr); - s << A(HREF=*root_ / path (mime_url_encode (*package_)) / path (version_)) - << version_ - << ~A; - } - - s << ~SPAN - << ~TD - << ~TR; - } - - // TR_SUMMARY - // - void TR_SUMMARY:: - operator() (serializer& s) const - { - s << TR(CLASS="summary") - << TH << "summary" << ~TH - << TD << SPAN(CLASS="value") << summary_ << ~SPAN << ~TD - << ~TR; - } - - // TR_LICENSE - // - void TR_LICENSE:: - operator() (serializer& s) const - { - s << TR(CLASS="license") - << TH << "license" << ~TH - << TD - << SPAN(CLASS="value"); - - for (const auto& la: licenses_) - { - if (&la != &licenses_[0]) - s << " " << EM << "or" << ~EM << " "; - - bool m (la.size () > 1); - - if (m) - s << "("; - - for (const auto& l: la) - { - if (&l != &la[0]) - s << " " << EM << "and" << ~EM << " "; - - s << l; - } - - if (m) - s << ")"; - } - - s << ~SPAN - << ~TD - << ~TR; - } - - // TR_LICENSES - // - void TR_LICENSES:: - operator() (serializer& s) const - { - for (const auto& la: licenses_) - { - s << TR(CLASS="license") - << TH << "license" << ~TH - << TD - << SPAN(CLASS="value"); - - for (const auto& l: la) - { - if (&l != &la[0]) - s << " " << EM << "and" << ~EM << " "; - - s << l; - } - - s << ~SPAN - << SPAN_COMMENT (la.comment) - << ~TD - << ~TR; - } - } - - // TR_TAGS - // - void TR_TAGS:: - operator() (serializer& s) const - { - if (!tags_.empty ()) - { - s << TR(CLASS="tags") - << TH << "tags" << ~TH - << TD - << SPAN(CLASS="value"); - - for (const auto& t: tags_) - { - if (&t != &tags_[0]) - s << " "; - - s << A << HREF << root_ << "?q=" << mime_url_encode (t) << ~HREF - << t - << ~A; - } - - s << ~SPAN - << ~TD - << ~TR; - } - } - - // TR_DEPENDS - // - void TR_DEPENDS:: - operator() (serializer& s) const - { - s << TR(CLASS="depends") - << TH << "depends" << ~TH - << TD - << SPAN(CLASS="value") - << dependencies_.size (); - - if (!dependencies_.empty ()) - s << "; "; - - for (const auto& d: dependencies_) - { - if (&d != &dependencies_[0]) - s << ", "; - - if (d.conditional) - s << "?"; - - // Suppress package name duplicates. - // - set names; - for (const auto& da: d) - names.emplace (da.name ()); - - bool mult (names.size () > 1); - - if (mult) - s << "("; - - bool first (true); - for (const auto& da: d) - { - string n (da.name ()); - if (names.find (n) != names.end ()) - { - names.erase (n); - - if (first) - first = false; - else - s << " | "; - - shared_ptr p (da.package.load ()); - assert (p->internal () || !p->other_repositories.empty ()); - - shared_ptr r ( - p->internal () - ? p->internal_repository.load () - : p->other_repositories[0].load ()); - - auto en (mime_url_encode (n)); - - if (r->url) - s << A(HREF=*r->url + en) << n << ~A; - else if (p->internal ()) - s << A(HREF=root_ / path (en)) << n << ~A; - else - // Display the dependency as a plain text if no repository URL - // available. - // - s << n; - } - } - - if (mult) - s << ")"; - } - - s << ~SPAN - << ~TD - << ~TR; - } - - // TR_REQUIRES - // - void TR_REQUIRES:: - operator() (serializer& s) const - { - // If there are no requirements, then we omit it, unlike depends, where we - // show 0 explicitly. - // - if (requirements_.empty ()) - return; - - s << TR(CLASS="requires") - << TH << "requires" << ~TH - << TD - << SPAN(CLASS="value") - << requirements_.size () << "; "; - - for (const auto& r: requirements_) - { - if (&r != &requirements_[0]) - s << ", "; - - if (r.conditional) - s << "?"; - - if (r.empty ()) - { - // If there is no requirement alternatives specified, then - // print the comment first word. - // - const auto& c (r.comment); - if (!c.empty ()) - { - auto n (c.find (' ')); - s << string (c, 0, n); - - if (n != string::npos) - s << "..."; - } - } - else - { - bool mult (r.size () > 1); - - if (mult) - s << "("; - - for (const auto& ra: r) - { - if (&ra != &r[0]) - s << " | "; - - s << ra; - } - - if (mult) - s << ")"; - } - } - - s << ~SPAN - << ~TD - << ~TR; - } - - // TR_URL - // - void TR_URL:: - operator() (serializer& s) const - { - s << TR(CLASS=label_) - << TH << label_ << ~TH - << TD - << SPAN(CLASS="value") << A(HREF=url_) << url_ << ~A << ~SPAN - << SPAN_COMMENT (url_.comment) - << ~TD - << ~TR; - } - - // TR_EMAIL - // - void TR_EMAIL:: - operator() (serializer& s) const - { - s << TR(CLASS=label_) - << TH << label_ << ~TH - << TD - << SPAN(CLASS="value") - << A(HREF="mailto:" + email_) << email_ << ~A - << ~SPAN - << SPAN_COMMENT (email_.comment) - << ~TD - << ~TR; - } - - // TR_PRIORITY - // - void TR_PRIORITY:: - operator() (serializer& s) const - { - static const strings priority_names ({"low", "medium", "high", "security"}); - assert (priority_ < priority_names.size ()); - - s << TR(CLASS="priority") - << TH << "priority" << ~TH - << TD - << SPAN(CLASS="value") << priority_names[priority_] << ~SPAN - << SPAN_COMMENT (priority_.comment) - << ~TD - << ~TR; - } - - // TR_LOCATION - // - void TR_LOCATION:: - operator() (serializer& s) const - { - s << TR(CLASS="location") - << TH << "location" << ~TH - << TD - << SPAN(CLASS="value") - << A - << HREF - << root_ << "?about#" << mime_url_encode (html_id (name_)) - << ~HREF - << name_ - << ~A - << ~SPAN - << ~TD - << ~TR; - } - - // TR_DOWNLOAD - // - void TR_DOWNLOAD:: - operator() (serializer& s) const - { - s << TR(CLASS="download") - << TH << "download" << ~TH - << TD - << SPAN(CLASS="value") << A(HREF=url_) << url_ << ~A << ~SPAN - << ~TD - << ~TR; - } - - // TR_SHA256SUM - // - void TR_SHA256SUM:: - operator() (serializer& s) const - { - s << TR(CLASS="sha256") - << TH << "sha256" << ~TH - << TD << SPAN(CLASS="value") << sha256sum_ << ~SPAN << ~TD - << ~TR; - } - - // SPAN_COMMENT - // - void SPAN_COMMENT:: - operator() (serializer& s) const - { - if (size_t l = comment_.size ()) - s << SPAN(CLASS="comment") - << (comment_.back () == '.' ? string (comment_, 0, l - 1) : comment_) - << ~SPAN; - } - - // P_DESCRIPTION - // - void P_DESCRIPTION:: - operator() (serializer& s) const - { - if (description_.empty ()) - return; - - auto n (description_.find_first_of (" \t\n", length_)); - bool full (n == string::npos); // Description length is below the limit. - - // Truncate description if length exceed the limit. - // - const string& d (full ? description_ : string (description_, 0, n)); - - // Format the description into paragraphs, recognizing a blank line as - // paragraph separator, and replacing single newlines with a space. - // - s << P; - - if (!id_.empty ()) - s << ID(id_); - - bool nl (false); // The previous character is '\n'. - for (const auto& c: d) - { - if (c == '\n') - { - if (nl) - { - s << ~P << P; - nl = false; - } - else - nl = true; // Delay printing until the next character. - } - else - { - if (nl) - { - s << ' '; // Replace the previous newline with a space. - nl = false; - } - - s << c; - } - } - - if (!full) - { - assert (url_ != nullptr); - s << "... " << A(HREF=*url_) << "More" << ~A; - } - - s << ~P; - } - - // PRE_CHANGES - // - void PRE_CHANGES:: - operator() (serializer& s) const - { - if (changes_.empty ()) - return; - - auto n (changes_.find_first_of (" \t\n", length_)); - bool full (n == string::npos); // Changes length is below the limit. - - // Truncate changes if length exceed the limit. - // - const string& c (full ? changes_ : string (changes_, 0, n)); - s << PRE(ID="changes") << c; - - if (!full) - { - assert (url_ != nullptr); - s << "... " << A(HREF=*url_) << "More" << ~A; - } - - s << ~PRE; - } - - // DIV_PAGER - // - DIV_PAGER:: - DIV_PAGER (size_t current_page, - size_t item_count, - size_t item_per_page, - size_t page_number_count, - const string& url) - : current_page_ (current_page), - item_count_ (item_count), - item_per_page_ (item_per_page), - page_number_count_ (page_number_count), - url_ (url) - { - } - - void DIV_PAGER:: - operator() (serializer& s) const - { - if (item_count_ == 0 || item_per_page_ == 0) - return; - - size_t pcount (item_count_ / item_per_page_); // Page count. - - if (item_count_ % item_per_page_) - ++pcount; - - if (pcount > 1) - { - auto url ( - [this](size_t page) -> string - { - return page == 0 - ? url_ - : url_ + (url_.find ('?') == string::npos ? "?p=" : "&p=") + - to_string (page); - }); - - s << DIV(ID="pager"); - - if (current_page_ > 0) - s << A(ID="prev", HREF=url (current_page_ - 1)) << "Prev" << ~A; - - if (page_number_count_) - { - size_t offset (page_number_count_ / 2); - size_t from (current_page_ > offset ? current_page_ - offset : 0); - size_t to (min (from + page_number_count_, pcount)); - - for (size_t p (from); p < to; ++p) - { - s << A(HREF=url (p)); - - if (p == current_page_) - s << ID("curr"); - - s << p + 1 - << ~A; - } - } - - if (current_page_ < pcount - 1) - s << A(ID="next", HREF=url (current_page_ + 1)) << "Next" << ~A; - - s << ~DIV; - } - } - - // Convert the argument to a string conformant to the section - // "3.2.5.1 The id attribute" of the HTML 5 specification at - // http://www.w3.org/TR/html5/dom.html#the-id-attribute. - // - string - html_id (const string& v) - { - ostringstream o; - o << hex << uppercase << right << setfill ('0'); - - // Replace space characters (as specified at - // http://www.w3.org/TR/html5/infrastructure.html#space-character) with - // the respective escape sequences. - // - for (auto c: v) - { - switch (c) - { - case ' ': - case '\t': - case '\n': - case '\r': - case '\f': - case '~': - { - // We use '~' as an escape character because it doesn't require - // escaping in URLs. - // - o << "~" << setw (2) << static_cast (c); - break; - } - default: o << c; break; - } - } - - return o.str (); - } -} diff --git a/brep/services.cxx b/brep/services.cxx deleted file mode 100644 index 94c7fc6..0000000 --- a/brep/services.cxx +++ /dev/null @@ -1,15 +0,0 @@ -// file : brep/services.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include // AP_MODULE_DECLARE_DATA - -#include - -#include -#include - -#include - -static brep::repository_root mod; -web::apache::service AP_MODULE_DECLARE_DATA brep_module ("brep", mod); diff --git a/brep/types-parsers b/brep/types-parsers deleted file mode 100644 index 78b7088..0000000 --- a/brep/types-parsers +++ /dev/null @@ -1,57 +0,0 @@ -// file : brep/types-parsers -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -// CLI parsers, included into the generated source files. -// - -#ifndef BREP_TYPES_PARSERS -#define BREP_TYPES_PARSERS - -#include - -#include -#include - -#include - -namespace brep -{ - namespace cli - { - class scanner; - - template - struct parser; - - template <> - struct parser - { - static void - parse (dir_path&, scanner&); - }; - - template <> - struct parser - { - static void - parse (page_form&, scanner&); - }; - - template <> - struct parser - { - static void - parse (page_menu&, scanner&); - }; - - template <> - struct parser - { - static void - parse (web::xhtml::fragment&, scanner&); - }; - } -} - -#endif // BREP_TYPES_PARSERS diff --git a/brep/types-parsers.cxx b/brep/types-parsers.cxx deleted file mode 100644 index 67f4812..0000000 --- a/brep/types-parsers.cxx +++ /dev/null @@ -1,114 +0,0 @@ -// file : brep/types-parsers.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include - -using namespace std; -using namespace web::xhtml; - -namespace brep -{ - namespace cli - { - // Parse path. - // - template - static void - parse_path (T& x, scanner& s) - { - const char* o (s.next ()); - - if (!s.more ()) - throw missing_value (o); - - const char* v (s.next ()); - - try - { - x = T (v); - } - catch (const invalid_path&) - { - throw invalid_value (o, v); - } - } - - void parser:: - parse (dir_path& x, scanner& s) - { - parse_path (x, s); - } - - // Parse page_form. - // - void parser:: - parse (page_form& x, scanner& s) - { - const char* o (s.next ()); - - if (!s.more ()) - throw missing_value (o); - - const string v (s.next ()); - if (v == "full") - x = page_form::full; - else if (v == "brief") - x = page_form::brief; - else - throw invalid_value (o, v); - } - - // Parse page_menu. - // - void parser:: - parse (page_menu& x, scanner& s) - { - const char* o (s.next ()); - - if (!s.more ()) - throw missing_value (o); - - const string v (s.next ()); - - auto p (v.find ('=')); - if (p != string::npos) - { - string label (v, 0, p); - string link (v, p + 1); - - if (!label.empty ()) - { - x = page_menu (move (label), move (link)); - return; - } - } - - throw invalid_value (o, v); - } - - // Parse web::xhtml::fragment. - // - void parser:: - parse (fragment& x, scanner& s) - { - const char* o (s.next ()); - - if (!s.more ()) - throw missing_value (o); - - const char* v (s.next ()); - - try - { - x = fragment (v, o); - } - catch (const xml::parsing&) - { - throw invalid_value (o, v); - } - } - } -} -- cgit v1.1