From 03905bcf1bcfd9e7932fcac4283c5817058a25ce Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 14 Nov 2015 16:29:22 +0200 Subject: Invent root path web interface configuration option --- brep/buildfile | 8 +++- brep/module.cxx | 3 +- brep/options.cli | 3 ++ brep/package-details.cxx | 42 +++++++++++-------- brep/package-search.cxx | 31 +++++++++----- brep/package-version-details.cxx | 81 ++++++++++++++++++++---------------- brep/page | 36 +++++++++++----- brep/page.cxx | 89 +++++++++++++++++++++------------------- brep/services.cxx | 6 +-- brep/types-parsers | 31 ++++++++++++++ brep/types-parsers.cxx | 47 +++++++++++++++++++++ 11 files changed, 257 insertions(+), 120 deletions(-) create mode 100644 brep/types-parsers create mode 100644 brep/types-parsers.cxx (limited to 'brep') diff --git a/brep/buildfile b/brep/buildfile index 808de15..6676095 100644 --- a/brep/buildfile +++ b/brep/buildfile @@ -22,7 +22,9 @@ libso{brep}: cxx.export.poptions = -I$out_root -I$src_root import libs += libstudxml%lib{studxml} brep = cxx{diagnostics module services package-search package-details \ - package-version-details shared-database page} cli.cxx{options} + package-version-details shared-database page types-parsers} \ + cli.cxx{options} + web = ../web/apache/cxx{request service} ../web/cxx{mime-url-encoding} libso{brep-apache}: $brep $web libso{brep} $libs @@ -36,6 +38,8 @@ libso{brep-apache}: $brep $web libso{brep} $libs # ::cli::unknown_mode opt_mode, # cli.options += -I $src_root --include-with-brackets --include-prefix brep \ ---guard-prefix BREP --generate-file-scanner --suppress-usage --option-prefix "" +--guard-prefix BREP --cxx-prologue "#include " \ +--cli-namespace brep::cli --generate-file-scanner --suppress-usage \ +--option-prefix "" cli.cxx{options}: cli{options} diff --git a/brep/module.cxx b/brep/module.cxx index fa7f479..850f593 100644 --- a/brep/module.cxx +++ b/brep/module.cxx @@ -22,10 +22,11 @@ using namespace std; using namespace placeholders; // For std::bind's _1, etc. -using namespace cli; namespace brep { + using namespace cli; + // module // void module:: diff --git a/brep/options.cli b/brep/options.cli index 86cb70c..6c3c7f1 100644 --- a/brep/options.cli +++ b/brep/options.cli @@ -5,6 +5,8 @@ include ; include ; // uint16_t +include ; + namespace brep { // Web module configuration options. @@ -14,6 +16,7 @@ namespace brep class module { std::uint16_t verb = 0; + butl::dir_path root = "/"; }; class db diff --git a/brep/package-details.cxx b/brep/package-details.cxx index 12480c8..ef787b0 100644 --- a/brep/package-details.cxx +++ b/brep/package-details.cxx @@ -7,6 +7,7 @@ #include #include // make_shared(), shared_ptr #include // size_t +#include #include @@ -25,11 +26,12 @@ #include using namespace std; -using namespace cli; using namespace odb::core; namespace brep { + using namespace cli; + void package_details:: init (scanner& s) { @@ -65,7 +67,15 @@ namespace brep MODULE_DIAG; + // The module options object is not changed after being created once per + // server process. + // + static const size_t rp (options_->results_on_page ()); + static const dir_path& rt (options_->root ()); + const string& name (*rq.path ().rbegin ()); + const string en (mime_url_encode (name)); + params::package_details pr; try @@ -81,8 +91,6 @@ namespace brep const string& sq (pr.query ()); // Search query. size_t pg (pr.page ()); bool f (pr.full ()); - string en (mime_url_encode (name)); - size_t rp (options_->results_on_page ()); auto url ( [&en](bool f = false, @@ -101,19 +109,20 @@ namespace brep }); serializer s (rs.content (), name); - const string title (sq.empty () ? name : name + " " + sq); + const string& title (sq.empty () ? name : name + " " + sq); + static const path sp ("package-details.css"); s << HTML << HEAD << TITLE << title << ~TITLE - << CSS_LINKS ("/package-details.css") + << CSS_LINKS (sp, rt) << ~HEAD << BODY - << DIV_HEADER () + << DIV_HEADER (rt) << DIV(ID="content"); if (f) - s << CLASS << "full" << ~CLASS; + s << CLASS("full"); s << DIV(ID="heading") << H1 << A(HREF=url ()) << name << ~A << ~H1 @@ -136,7 +145,7 @@ namespace brep p = db_->load (lp.id); } - const license_alternatives& ll (p->license_alternatives); + const auto& ll (p->license_alternatives); if (pg == 0) { @@ -144,20 +153,19 @@ namespace brep // s << H2 << p->summary << ~H2; + static const size_t dl (options_->description_length ()); + if (const auto& d = p->description) s << (f ? P_DESCRIPTION (*d) - : P_DESCRIPTION ( - *d, - options_->description_length (), - url (!f, sq, pg, "description"))); + : P_DESCRIPTION (*d, dl, url (!f, sq, pg, "description"))); s << TABLE(CLASS="proplist", ID="package") << TBODY << TR_LICENSE (ll) << TR_URL (p->url) << TR_EMAIL (p->email) - << TR_TAGS (p->tags) + << TR_TAGS (p->tags, rt) << ~TBODY << ~TABLE; } @@ -186,7 +194,7 @@ namespace brep s << TABLE(CLASS="proplist version") << TBODY - << TR_VERSION (name, p->version.string ()) + << TR_VERSION (name, p->version.string (), rt) // @@ Shouldn't we skip low priority row ? Don't think so, why? // @@ -212,7 +220,7 @@ namespace brep // Hm, I am not so sure about this. Consider: stable/testing/unstable. // s << TR_LOCATION (p->internal_repository.object_id ()) - << TR_DEPENDS (p->dependencies) + << TR_DEPENDS (p->dependencies, rt) << TR_REQUIRES (p->requirements) << ~TBODY << ~TABLE; @@ -221,7 +229,9 @@ namespace brep t.commit (); - s << DIV_PAGER (pg, pc, rp, options_->pages_in_pager (), url (f, sq)) + static const size_t pp (options_->pages_in_pager ()); + + s << DIV_PAGER (pg, pc, rp, pp, url (f, sq)) << ~DIV << ~BODY << ~HTML; diff --git a/brep/package-search.cxx b/brep/package-search.cxx index 47f53e9..b0352f3 100644 --- a/brep/package-search.cxx +++ b/brep/package-search.cxx @@ -5,7 +5,7 @@ #include #include -#include // make_shared() +#include // make_shared(), shared_ptr #include // size_t #include @@ -25,11 +25,12 @@ #include using namespace std; -using namespace cli; using namespace odb::core; namespace brep { + using namespace cli; + void package_search:: init (scanner& s) { @@ -62,6 +63,12 @@ namespace brep MODULE_DIAG; + // The module options object is not changed after being created once per + // server process. + // + static const size_t rp (options_->results_on_page ()); + static const dir_path& rt (options_->root ()); + params::package_search pr; try @@ -75,22 +82,23 @@ namespace brep } const string& sq (pr.query ()); // Search query. - size_t pg (pr.page ()); string qp (sq.empty () ? "" : "q=" + mime_url_encode (sq)); - size_t rp (options_->results_on_page ()); + size_t pg (pr.page ()); serializer s (rs.content (), "Packages"); const string& title ( sq.empty () ? s.output_name () : s.output_name () + " " + sq); + static const path sp ("package-search.css"); + s << HTML << HEAD << TITLE << title << ~TITLE - << CSS_LINKS ("/package-search.css") + << CSS_LINKS (sp, rt) << ~HEAD << BODY - << DIV_HEADER () + << DIV_HEADER (rt) << DIV(ID="content"); session sn; @@ -119,11 +127,11 @@ namespace brep s << TABLE(CLASS="proplist package") << TBODY - << TR_NAME (p->id.name, qp) + << TR_NAME (p->id.name, qp, rt) << TR_SUMMARY (p->summary) << TR_LICENSE (p->license_alternatives) - << TR_TAGS (p->tags) - << TR_DEPENDS (p->dependencies) + << TR_TAGS (p->tags, rt) + << TR_DEPENDS (p->dependencies, rt) << TR_REQUIRES (p->requirements) << ~TBODY << ~TABLE; @@ -132,9 +140,10 @@ namespace brep t.commit (); - string url (qp.empty () ? "/" : ("/?" + qp)); + static const size_t pp (options_->pages_in_pager ()); + const string& u (qp.empty () ? rt.string () : (rt.string () + "?" + qp)); - s << DIV_PAGER (pg, pc, rp, options_->pages_in_pager (), url) + s << DIV_PAGER (pg, pc, rp, pp, u) << ~DIV << ~BODY << ~HTML; diff --git a/brep/package-version-details.cxx b/brep/package-version-details.cxx index ce25a44..b8f30ff 100644 --- a/brep/package-version-details.cxx +++ b/brep/package-version-details.cxx @@ -26,11 +26,12 @@ #include using namespace std; -using namespace cli; using namespace odb::core; namespace brep { + using namespace cli; + void package_version_details:: init (scanner& s) { @@ -51,6 +52,11 @@ namespace brep MODULE_DIAG; + // The module options object is not changed after being created once per + // server process. + // + static const dir_path& rt (options_->root ()); + auto i (rq.path ().rbegin ()); version v; @@ -63,8 +69,11 @@ namespace brep throw invalid_request (400, "invalid package version format"); } + const string& vs (v.string ()); + assert (i != rq.path ().rend ()); const string& n (*i); // Package name. + const string name (n + " " + vs); params::package_version_details pr; @@ -80,7 +89,6 @@ namespace brep } bool f (pr.full ()); - const string& vs (v.string ()); auto url ([&vs](bool f = false, const string& a = "") -> string { @@ -91,27 +99,25 @@ namespace brep return u; }); - const string name (n + " " + vs); serializer s (rs.content (), name); + static const path go ("go"); + static const path sp ("package-version-details.css"); s << HTML << HEAD << TITLE << name << ~TITLE - << CSS_LINKS ("/package-version-details.css") + << CSS_LINKS (sp, rt) << ~HEAD << BODY - << DIV_HEADER () + << DIV_HEADER (rt) << DIV(ID="content"); if (f) - s << CLASS << "full" << ~CLASS; + s << CLASS("full"); s << DIV(ID="heading") << H1 - << A - << HREF << "/go/" << mime_url_encode (n) << ~HREF - << n - << ~A + << A(HREF=rt / go / path (mime_url_encode (n))) << n << ~A << "/" << A(HREF=url ()) << vs << ~A << ~H1 @@ -143,17 +149,18 @@ namespace brep s << H2 << p->summary << ~H2; + static const size_t dl (options_->description_length ()); + if (const auto& d = p->description) s << (f ? P_DESCRIPTION (*d) - : P_DESCRIPTION ( - *d, options_->description_length (), url (!f, "description"))); + : P_DESCRIPTION (*d, dl, url (!f, "description"))); // Link to download from the internal repository. // assert (p->location); - const string du (p->internal_repository.load ()->location.string () + - "/" + p->location->string ()); + const string du (p->internal_repository.load ()->location.string () + "/" + + p->location->string ()); s << TABLE(CLASS="proplist", ID="version") << TBODY @@ -180,7 +187,7 @@ namespace brep if (p->package_email && *p->package_email != p->email) s << TR_EMAIL (*p->package_email, "pkg-email"); - s << TR_TAGS (p->tags) + s << TR_TAGS (p->tags, rt) << ~TBODY << ~TABLE; @@ -210,32 +217,36 @@ namespace brep s << " | "; shared_ptr p (d.package.load ()); - string en (mime_url_encode (p->id.name)); - assert (p->internal () || !p->other_repositories.empty ()); + shared_ptr r ( p->internal () ? p->internal_repository.load () : p->other_repositories[0].load ()); - optional u (r->url); // Repository web interface URL. - if (!u && p->internal ()) - u = ""; // Make URL to reference the current web interface. + const auto& dc (d.constraint); + const string& dn (p->id.name); + string en (mime_url_encode (dn)); - if (u) + if (r->url) { - s << A << HREF << *u << "/go/" << en << ~HREF << p->id.name << ~A; + string u (*r->url + "go/" + en); + s << A(HREF=u) << dn << ~A; - if (d.constraint) - { + if (dc) s << ' ' << A - << HREF - << *u << "/go/" << en << "/" << p->version.string () - << ~HREF - << *d.constraint + << HREF << u << "/" << p->version.string () << ~HREF + << *dc << ~A; - } + } + else if (p->internal ()) + { + path u (rt / go / path (en)); + s << A(HREF=u) << dn << ~A; + + if (dc) + s << ' ' << A(HREF=u / path (p->version.string ())) << *dc << ~A; } else // Display the dependency as a plain text in no repository URL @@ -256,15 +267,15 @@ namespace brep t.commit (); - const auto& rt (p->requirements); + const auto& rm (p->requirements); - if (!rt.empty ()) + if (!rm.empty ()) { s << H3 << "Requires" << ~H3 << TABLE(CLASS="proplist", ID="requires") << TBODY; - for (const auto& ra: rt) + for (const auto& ra: rm) { s << TR(CLASS="requires") << TH; @@ -294,14 +305,14 @@ namespace brep << ~TABLE; } - const string& ch (p->changes); + static const size_t cl (options_->changes_length ()); + const auto& ch (p->changes); if (!ch.empty ()) s << H3 << "Changes" << ~H3 << (f ? PRE_CHANGES (ch) - : PRE_CHANGES ( - ch, options_->changes_length (), url (!f, "changes"))); + : PRE_CHANGES (ch, cl, url (!f, "changes"))); s << ~DIV << ~BODY diff --git a/brep/page b/brep/page index 309caa9..c968389 100644 --- a/brep/page +++ b/brep/page @@ -22,21 +22,29 @@ namespace brep class CSS_LINKS { public: - CSS_LINKS (const char* u): url_ (u) {} + CSS_LINKS (const path& p, const dir_path& r): + path_ (p), root_ (r) {} void operator() (xml::serializer& s) const; private: - const char* url_; + const path& path_; + const dir_path& root_; }; // Generates page header element. // - struct DIV_HEADER + class DIV_HEADER { + public: + DIV_HEADER (const dir_path& r): root_ (r) {} + void operator() (xml::serializer& s) const; + + private: + const dir_path& root_; }; // Generates package search form element. @@ -79,8 +87,8 @@ namespace brep class TR_NAME { public: - TR_NAME (const std::string& n, const std::string& q) - : name_ (n), query_param_ (q) {} + TR_NAME (const std::string& n, const std::string& q, const dir_path& r) + : name_ (n), query_param_ (q), root_ (r) {} void operator() (xml::serializer& s) const; @@ -88,6 +96,7 @@ namespace brep private: const std::string& name_; const std::string& query_param_; + const dir_path& root_; }; // Generates package version element. @@ -97,12 +106,15 @@ namespace brep public: // Display the version as a link to the package version details page. // - TR_VERSION (const std::string& p, const std::string& v) - : package_ (&p), version_ (v) {} + TR_VERSION (const std::string& p, + const std::string& v, + const dir_path& r) + : package_ (&p), version_ (v), root_ (&r) {} // Display the version as a regular text. // - TR_VERSION (const std::string& v): package_ (nullptr), version_ (v) {} + TR_VERSION (const std::string& v) + : package_ (nullptr), version_ (v), root_ (nullptr) {} void operator() (xml::serializer& s) const; @@ -110,6 +122,7 @@ namespace brep private: const std::string* package_; const std::string& version_; + const dir_path* root_; }; // Generates package summary element. @@ -160,13 +173,14 @@ namespace brep class TR_TAGS { public: - TR_TAGS (const strings& ts): tags_ (ts) {} + TR_TAGS (const strings& ts, const dir_path& r): tags_ (ts), root_ (r) {} void operator() (xml::serializer& s) const; private: const strings& tags_; + const dir_path& root_; }; // Generates package dependencies element. @@ -174,13 +188,15 @@ namespace brep class TR_DEPENDS { public: - TR_DEPENDS (const dependencies& d): dependencies_ (d) {} + TR_DEPENDS (const dependencies& d, const dir_path& r) + : dependencies_ (d), root_ (r) {} void operator() (xml::serializer& s) const; private: const dependencies& dependencies_; + const dir_path& root_; }; // Generates package requirements element. diff --git a/brep/page.cxx b/brep/page.cxx index 81a7de5..fbbcda8 100644 --- a/brep/page.cxx +++ b/brep/page.cxx @@ -7,8 +7,8 @@ #include #include #include // shared_ptr +#include // size_t #include -#include // move() #include // min() #include @@ -26,13 +26,17 @@ using namespace web::xhtml; namespace brep { + static const path go ("go"); + // CSS_LINKS // void CSS_LINKS:: operator() (serializer& s) const { - s << *LINK(REL="stylesheet", TYPE="text/css", HREF="/common.css") - << *LINK(REL="stylesheet", TYPE="text/css", HREF=url_); + static const path c ("common.css"); + + s << *LINK(REL="stylesheet", TYPE="text/css", HREF=root_ / c) + << *LINK(REL="stylesheet", TYPE="text/css", HREF=root_ / path_); } // DIV_HEADER @@ -40,10 +44,12 @@ namespace brep void DIV_HEADER:: operator() (serializer& s) const { + static const path a ("about"); + s << DIV(ID="header") << DIV(ID="header-menu") - << A(HREF="/") << "packages" << ~A - << A(HREF="/about") << "about" << ~A + << A(HREF=root_) << "packages" << ~A + << A(HREF=root_ / a) << "about" << ~A << ~DIV << ~DIV; } @@ -97,7 +103,7 @@ namespace brep << SPAN(CLASS="value") << A << HREF - << "/go/" << mime_url_encode (name_); + << root_ / go / path (mime_url_encode (name_)); // Propagate search criteria to the package details page. // @@ -123,12 +129,11 @@ namespace brep if (package_ == nullptr) s << version_; else - s << A - << HREF - << "/go/" << mime_url_encode (*package_) << "/" << version_ - << ~HREF - << version_ - << ~A; + { + assert (root_ != nullptr); + path p (mime_url_encode (*package_)); + s << A(HREF=*root_ / go / p / path (version_)) << version_ << ~A; + } s << ~SPAN << ~TD @@ -156,28 +161,28 @@ namespace brep << TD << SPAN(CLASS="value"); - for (const auto& la: licenses_) - { - if (&la != &licenses_[0]) - s << " " << EM << "or" << ~EM << " "; - - bool m (la.size () > 1); + for (const auto& la: licenses_) + { + if (&la != &licenses_[0]) + s << " " << EM << "or" << ~EM << " "; - if (m) - s << "("; + bool m (la.size () > 1); - for (const auto& l: la) - { - if (&l != &la[0]) - s << " " << EM << "and" << ~EM << " "; + if (m) + s << "("; - s << l; - } + for (const auto& l: la) + { + if (&l != &la[0]) + s << " " << EM << "and" << ~EM << " "; - if (m) - s << ")"; + s << l; } + if (m) + s << ")"; + } + s << ~SPAN << ~TD << ~TR; @@ -227,7 +232,10 @@ namespace brep if (&t != &tags_[0]) s << " "; - s << A << HREF << "/?q=" << mime_url_encode (t) << ~HREF << t << ~A; + s << A + << HREF << root_ << "?q=" << mime_url_encode (t) << ~HREF + << t + << ~A; } s << ~SPAN @@ -283,22 +291,19 @@ namespace brep 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 ()); - optional u (r->url); // Repository web interface URL. - if (!u && p->internal ()) - u = ""; // Make URL to reference the current web interface. + auto en (mime_url_encode (n)); - if (u) - s << A - << HREF << *u << "/go/" << mime_url_encode (n) << ~HREF - << n - << ~A; + if (r->url) + s << A << HREF << *r->url << "go/" << en << ~HREF << n << ~A; + else if (p->internal ()) + s << A(HREF=root_ / go / path (en)) << n << ~A; else // Display the dependency as a plain text in no repository URL // available. @@ -471,7 +476,7 @@ namespace brep if (description_.empty ()) return; - string::size_type n (description_.find_first_of (" \t\n", length_)); + auto n (description_.find_first_of (" \t\n", length_)); bool f (n == string::npos); // Description length is below the limit. // Truncate description if length exceed the limit. @@ -525,7 +530,7 @@ namespace brep if (changes_.empty ()) return; - string::size_type n (changes_.find_first_of (" \t\n", length_)); + auto n (changes_.find_first_of (" \t\n", length_)); bool f (n == string::npos); // Changes length is below the limit. // Truncate changes if length exceed the limit. @@ -577,7 +582,7 @@ namespace brep return page == 0 ? url_ : url_ + (url_.find ('?') == string::npos ? "?p=" : "&p=") + - to_string (page); + to_string (page); }); s << DIV(ID="pager"); @@ -596,7 +601,7 @@ namespace brep s << A(HREF=u (p)); if (p == current_page_) - s << ID << "curr" << ~ID; + s << ID("curr"); s << p + 1 << ~A; diff --git a/brep/services.cxx b/brep/services.cxx index eb99f3d..9b7043c 100644 --- a/brep/services.cxx +++ b/brep/services.cxx @@ -17,16 +17,16 @@ static package_search package_search_mod; service AP_MODULE_DECLARE_DATA package_search_srv ( "package-search", package_search_mod, - {"db-host", "db-port", "conf"}); + {"root", "db-host", "db-port", "conf"}); static package_details package_details_mod; service AP_MODULE_DECLARE_DATA package_details_srv ( "package-details", package_details_mod, - {"db-host", "db-port", "conf"}); + {"root", "db-host", "db-port", "conf"}); static package_version_details package_version_details_mod; service AP_MODULE_DECLARE_DATA package_version_details_srv ( "package-version-details", package_version_details_mod, - {"db-host", "db-port", "conf"}); + {"root", "db-host", "db-port", "conf"}); diff --git a/brep/types-parsers b/brep/types-parsers new file mode 100644 index 0000000..6d30544 --- /dev/null +++ b/brep/types-parsers @@ -0,0 +1,31 @@ +// file : brep/types-parsers -*- C++ -*- +// copyright : Copyright (c) 2014-2015 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 + +namespace brep +{ + namespace cli + { + class scanner; + + template + struct parser; + + template <> + struct parser + { + static void + parse (butl::dir_path&, scanner&); + }; + } +} + +#endif // BREP_TYPES_PARSERS diff --git a/brep/types-parsers.cxx b/brep/types-parsers.cxx new file mode 100644 index 0000000..f7c2f11 --- /dev/null +++ b/brep/types-parsers.cxx @@ -0,0 +1,47 @@ +// file : brep/types-parsers.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include + +#include + +using namespace butl; + +namespace brep +{ + namespace cli + { + 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); + + if (x.empty ()) + throw invalid_value (o, v); + } + catch (const invalid_path&) + { + throw invalid_value (o, v); + } + } + + void parser:: + parse (dir_path& x, scanner& s) + { + parse_path (x, s); + } + } +} -- cgit v1.1