diff options
-rw-r--r-- | brep/buildfile | 7 | ||||
-rw-r--r-- | brep/diagnostics | 28 | ||||
-rw-r--r-- | brep/diagnostics.cxx | 3 | ||||
-rw-r--r-- | brep/module | 29 | ||||
-rw-r--r-- | brep/module.cxx | 13 | ||||
-rw-r--r-- | brep/options-types | 19 | ||||
-rw-r--r-- | brep/options.cli | 53 | ||||
-rw-r--r-- | brep/package | 178 | ||||
-rw-r--r-- | brep/package-details | 7 | ||||
-rw-r--r-- | brep/package-details.cxx | 384 | ||||
-rw-r--r-- | brep/package-search | 7 | ||||
-rw-r--r-- | brep/package-search.cxx | 227 | ||||
-rw-r--r-- | brep/package-version-details | 7 | ||||
-rw-r--r-- | brep/package-version-details.cxx | 477 | ||||
-rw-r--r-- | brep/package.cxx | 8 | ||||
-rw-r--r-- | brep/page | 94 | ||||
-rw-r--r-- | brep/page.cxx | 117 | ||||
-rw-r--r-- | brep/repository-details | 7 | ||||
-rw-r--r-- | brep/repository-details.cxx | 142 | ||||
-rw-r--r-- | brep/repository-root | 31 | ||||
-rw-r--r-- | brep/repository-root.cxx | 119 | ||||
-rw-r--r-- | brep/services.cxx | 7 | ||||
-rw-r--r-- | brep/shared-database | 9 | ||||
-rw-r--r-- | brep/shared-database.cxx | 6 | ||||
-rw-r--r-- | brep/types | 60 | ||||
-rw-r--r-- | brep/types-parsers | 14 | ||||
-rw-r--r-- | brep/types-parsers.cxx | 26 | ||||
-rw-r--r-- | brep/utility | 20 | ||||
-rwxr-xr-x | build.sh | 10 | ||||
-rwxr-xr-x | etc/apachectl | 2 | ||||
-rw-r--r-- | etc/config | 1 | ||||
-rw-r--r-- | etc/httpd.conf | 24 | ||||
-rw-r--r-- | etc/package-details.conf | 4 | ||||
-rw-r--r-- | etc/package-search.conf | 2 | ||||
-rw-r--r-- | etc/package-version-details.conf | 4 | ||||
-rw-r--r-- | loader/loader.cxx | 51 | ||||
-rw-r--r-- | loader/options.cli | 32 | ||||
-rw-r--r-- | tests/loader/1/basics/packages (renamed from tests/loader/external/1/basics/packages) | 0 | ||||
-rw-r--r-- | tests/loader/1/basics/repositories (renamed from tests/loader/external/1/basics/repositories) | 0 | ||||
-rw-r--r-- | tests/loader/1/math/packages (renamed from tests/loader/internal/1/math/packages) | 0 | ||||
-rw-r--r-- | tests/loader/1/math/repositories (renamed from tests/loader/internal/1/math/repositories) | 2 | ||||
-rw-r--r-- | tests/loader/1/misc/packages (renamed from tests/loader/external/1/misc/packages) | 0 | ||||
-rw-r--r-- | tests/loader/1/misc/repositories (renamed from tests/loader/external/1/misc/repositories) | 0 | ||||
-rw-r--r-- | tests/loader/1/stable/packages (renamed from tests/loader/internal/1/stable/packages) | 0 | ||||
-rw-r--r-- | tests/loader/1/stable/repositories (renamed from tests/loader/internal/1/stable/repositories) | 2 | ||||
-rw-r--r-- | tests/loader/1/staging/packages (renamed from tests/loader/external/1/staging/packages) | 0 | ||||
-rw-r--r-- | tests/loader/1/staging/repositories (renamed from tests/loader/external/1/staging/repositories) | 0 | ||||
-rw-r--r-- | tests/loader/1/testing/packages (renamed from tests/loader/external/1/testing/packages) | 0 | ||||
-rw-r--r-- | tests/loader/1/testing/repositories (renamed from tests/loader/external/1/testing/repositories) | 0 | ||||
-rw-r--r-- | tests/loader/driver.cxx | 48 | ||||
-rw-r--r-- | tests/loader/r.conf | 4 | ||||
-rw-r--r-- | www/repository-details.css | 3 |
52 files changed, 1276 insertions, 1012 deletions
diff --git a/brep/buildfile b/brep/buildfile index 464118d..e6d9651 100644 --- a/brep/buildfile +++ b/brep/buildfile @@ -21,9 +21,10 @@ 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 repository-details shared-database page \ - types-parsers} cli.cxx{options} +brep = cxx{diagnostics module services repository-root package-search \ + package-details package-version-details repository-details \ + shared-database page types-parsers} \ + cli.cxx{options} web = ../web/apache/cxx{request service} ../web/cxx{mime-url-encoding} diff --git a/brep/diagnostics b/brep/diagnostics index 6e42e82..d077d6d 100644 --- a/brep/diagnostics +++ b/brep/diagnostics @@ -5,23 +5,24 @@ #ifndef BREP_DIAGNOSTICS #define BREP_DIAGNOSTICS -#include <vector> -#include <cstdint> // uint64_t -#include <utility> // move() +#include <utility> // forward() #include <sstream> #include <functional> +#include <brep/types> +#include <brep/utility> + namespace brep { struct location { location (): line (0), column (0) {} - location (std::string f, std::uint64_t l, std::uint64_t c) - : file (std::move (f)), line (l), column (c) {} + location (string f, uint64_t l, uint64_t c) + : file (move (f)), line (l), column (c) {} - std::string file; - std::uint64_t line; - std::uint64_t column; + string file; + uint64_t line; + uint64_t column; }; enum class severity {error, warning, info, trace}; @@ -31,10 +32,10 @@ namespace brep severity sev; const char* name {nullptr}; // E.g., a function name in tracing. location loc; - std::string msg; + string msg; }; - using diag_data = std::vector<diag_entry>; + using diag_data = vector<diag_entry>; // // @@ -93,15 +94,14 @@ namespace brep @@ libstdc++ doesn't yet have the ostringstream move support. diag_record (diag_record&& r) - : data_ (std::move (r.data_)), os_ (std::move (r.os_)) + : data_ (move (r.data_)), os_ (move (r.os_)) { epilogue_ = r.epilogue_; r.data_.clear (); // Empty. } */ - diag_record (diag_record&& r) - : data_ (std::move (r.data_)) + diag_record (diag_record&& r): data_ (move (r.data_)) { if (!data_.empty ()) os_ << r.os_.str (); @@ -293,7 +293,7 @@ namespace brep } static void - epilogue (diag_data&& d) {throw E (std::move (d));} + epilogue (diag_data&& d) {throw E (move (d));} private: const diag_epilogue epilogue_ {&epilogue}; diff --git a/brep/diagnostics.cxx b/brep/diagnostics.cxx index 0278792..4f8e5d6 100644 --- a/brep/diagnostics.cxx +++ b/brep/diagnostics.cxx @@ -4,9 +4,10 @@ #include <brep/diagnostics> -#include <cassert> #include <exception> +#include <brep/utility> + using namespace std; namespace brep diff --git a/brep/module b/brep/module index 0743598..295744d 100644 --- a/brep/module +++ b/brep/module @@ -5,12 +5,10 @@ #ifndef BREP_MODULE #define BREP_MODULE -#include <string> -#include <utility> // move() -#include <cstdint> - #include <web/module> +#include <brep/types> +#include <brep/utility> #include <brep/options> #include <brep/diagnostics> @@ -40,7 +38,7 @@ namespace brep { diag_data data; - server_error (diag_data&& d): data (std::move (d)) {} + server_error (diag_data&& d): data (move (d)) {} }; // Every module member function that needs to produce any diagnostics @@ -81,11 +79,15 @@ namespace brep // // While uint8 is more than enough, use uint16 for the ease of printing. // - std::uint16_t verb_ {0}; + uint16_t verb_ {0}; template <class F> void level1 (const F& f) const {if (verb_ >= 1) f ();} template <class F> void level2 (const F& f) const {if (verb_ >= 2) f ();} + // Set to true when the module is successfully initialized. + // + bool loaded_ {false}; + // Implementation details. // protected: @@ -117,12 +119,19 @@ namespace brep bool name_; }; - private: + public: + // Can be called normally by the web server or our custom request + // dispatching mechanism. + // virtual void - handle (request&, response&, log&); + handle (request&, response&) = 0; + + bool + loaded () const noexcept {return loaded_;} + private: virtual void - handle (request&, response&) = 0; + handle (request&, response&, log&); virtual void init (const name_values&, log&); @@ -147,7 +156,7 @@ namespace brep // Extract function name from a __PRETTY_FUNCTION__. // Throw std::invalid_argument if fail to parse. // - static std::string + static string func_name (const char* pretty_name); void diff --git a/brep/module.cxx b/brep/module.cxx index 850f593..68177b1 100644 --- a/brep/module.cxx +++ b/brep/module.cxx @@ -7,17 +7,17 @@ #include <httpd.h> #include <http_log.h> -#include <vector> -#include <string> #include <ostream> #include <sstream> -#include <cstring> // strncmp() +#include <cstring> // strchr() #include <stdexcept> #include <functional> // bind() #include <web/module> #include <web/apache/log> +#include <brep/types> +#include <brep/utility> #include <brep/options> using namespace std; @@ -32,6 +32,8 @@ namespace brep void module:: handle (request& rq, response& rs, log& l) { + assert (loaded_); + log_ = &l; try @@ -84,6 +86,8 @@ namespace brep void module:: init (const name_values& options, log& log) { + assert (!loaded_); + log_ = &log; vector<const char*> argv; @@ -119,6 +123,7 @@ namespace brep options::module o (s, unknown_mode::skip, unknown_mode::skip); verb_ = o.verb (); + loaded_ = true; } catch (const server_error& e) { @@ -139,7 +144,7 @@ namespace brep // Custom copy constructor is required to initialize log_writer_ properly. // module:: - module (const module& m): module () {verb_ = m.verb_;} + module (const module& m): module () {verb_ = m.verb_; loaded_ = m.loaded_;} // For function func declared like this: // using B = std::string (*)(int); diff --git a/brep/options-types b/brep/options-types new file mode 100644 index 0000000..01b8d0a --- /dev/null +++ b/brep/options-types @@ -0,0 +1,19 @@ +// file : brep/options-types -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BREP_OPTIONS_TYPES +#define BREP_OPTIONS_TYPES + +namespace brep +{ + // brep types + // + enum class page_form + { + full, + brief + }; +} + +#endif // BREP_OPTIONS_TYPES diff --git a/brep/options.cli b/brep/options.cli index 4126f4a..fa05b56 100644 --- a/brep/options.cli +++ b/brep/options.cli @@ -2,10 +2,8 @@ // copyright : Copyright (c) 2014-2015 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -include <string>; -include <cstdint>; // uint16_t - -include <butl/path>; +include <brep/types>; +include <brep/options-types>; namespace brep { @@ -15,33 +13,33 @@ namespace brep { class module { - std::uint16_t verb = 0; - butl::dir_path root = ""; + uint16_t verb; + dir_path root; }; class db { - std::string db-host = "localhost"; - std::uint16_t db-port = 5432; + string db-host = "localhost"; + uint16_t db-port = 5432; }; class package_search: module, db { - std::uint16_t results-on-page = 10; - std::uint16_t pages-in-pager = 10; + uint16_t results-on-page = 10; + uint16_t pages-in-pager = 5; }; class package_details: module, db { - std::uint16_t results-on-page = 10; - std::uint16_t pages-in-pager = 10; - std::uint16_t description-length = 400; + uint16_t results-on-page = 10; + uint16_t pages-in-pager = 5; + uint16_t description-length = 500; // ~ 80 chars x 6 lines. }; class package_version_details: module, db { - std::uint16_t description-length = 400; - std::uint16_t changes-length = 800; + uint16_t description-length = 500; // ~ 80 chars x 6 lines. + uint16_t changes-length = 5000; // ~ 80 chars x 60 lines. }; class repository_details: module, db @@ -60,36 +58,39 @@ namespace brep { // Display package search result list starting from this page. // - std::uint16_t page | p = 0; + uint16_t page | p; // Package search criteria. // - std::string query | q = ""; + string query | q; }; class package_details { // Display package version search result list starting from this page. // - std::uint16_t page | p = 0; + uint16_t page | p; // Package version search criteria. // - std::string query | q = ""; + string query | q; - // Full page variant. - // - // @@ Shouldn't we use one letter alias for URL as well ? - // I like full. It is descriptive. q= is kind now a convention. + // Page form. // - bool full = false; + page_form form | f = page_form::brief; }; class package_version_details { - // Full page variant. + // Page form. + // + page_form form | f = page_form::brief; + }; + + class repository_details + { + // No parameters so far. // - bool full = false; }; } } diff --git a/brep/package b/brep/package index f56906a..b3d4890 100644 --- a/brep/package +++ b/brep/package @@ -6,25 +6,15 @@ #define BREP_PACKAGE #include <map> -#include <string> -#include <vector> #include <chrono> -#include <memory> // shared_ptr -#include <cassert> -#include <cstddef> // size_t -#include <utility> // move() -#include <cstdint> // uint16 -#include <ostream> +#include <iosfwd> // ostream #include <odb/core.hxx> #include <odb/forward.hxx> // database -#include <odb/lazy-ptr.hxx> #include <odb/nested-container.hxx> -#include <butl/path> -#include <butl/path-io> -#include <butl/optional> -#include <butl/timestamp> +#include <brep/types> +#include <brep/utility> namespace brep { @@ -34,10 +24,10 @@ namespace brep #pragma db value struct _version { - std::uint16_t epoch; - std::string canonical_upstream; - std::uint16_t revision; - std::string upstream; + uint16_t epoch; + string canonical_upstream; + uint16_t revision; + string upstream; }; } @@ -55,9 +45,9 @@ namespace brep (?).upstream}) \ from(bpkg::version ((?).epoch, std::move ((?).upstream), (?).revision)) -#pragma db map type(bpkg::comparison) as(std::string) \ - to(bpkg::to_string (?)) \ - from(bpkg::to_comparison (?)) +#pragma db map type(bpkg::comparison) as(brep::string) \ + to(bpkg::to_string (?)) \ + from(bpkg::to_comparison (?)) namespace brep { @@ -76,33 +66,21 @@ namespace brep class repository; class package; - using strings = std::vector<std::string>; - using butl::optional; - // path // - using butl::path; - - #pragma db map type(path) as(std::string) \ - to((?).string ()) from(brep::path (?)) + #pragma db map type(path) as(string) to((?).string ()) from(brep::path (?)) using optional_path = optional<path>; - using optional_string = optional<std::string>; + using optional_string = optional<string>; #pragma db map type(optional_path) as(brep::optional_string) \ to((?) ? (?)->string () : brep::optional_string ()) \ from((?) ? brep::path (*(?)) : brep::optional_path ()) - using butl::dir_path; - - #pragma db map type(dir_path) as(std::string) \ + #pragma db map type(dir_path) as(string) \ to((?).string ()) from(brep::dir_path (?)) - // timestamp - // - using butl::timestamp; - - #pragma db map type(timestamp) as(std::uint64_t) \ + #pragma db map type(timestamp) as(uint64_t) \ to(std::chrono::system_clock::to_time_t (?)) \ from(std::chrono::system_clock::from_time_t (?)) @@ -113,9 +91,9 @@ namespace brep #pragma db value struct canonical_version { - std::uint16_t epoch; - std::string canonical_upstream; - std::uint16_t revision; + uint16_t epoch; + string canonical_upstream; + uint16_t revision; bool empty () const noexcept @@ -133,12 +111,12 @@ namespace brep #pragma db value transient struct upstream_version: version { - #pragma db member(upstream_) virtual(std::string) \ + #pragma db member(upstream_) virtual(string) \ get(this.upstream) \ set(this = brep::version (0, std::move (?), 0)) upstream_version () = default; - upstream_version (version v): version (std::move (v)) {} + upstream_version (version v): version (move (v)) {} upstream_version& operator= (version v) {version& b (*this); b = v; return *this;} @@ -162,21 +140,19 @@ namespace brep using bpkg::url; #pragma db value(url) definition - #pragma db member(url::value) virtual(std::string) before access(this) \ - column("") + #pragma db member(url::value) virtual(string) before access(this) column("") // email // using bpkg::email; #pragma db value(email) definition - #pragma db member(email::value) virtual(std::string) before access(this) \ - column("") + #pragma db member(email::value) virtual(string) before access(this) column("") // licenses // using bpkg::licenses; - using license_alternatives = std::vector<licenses>; + using license_alternatives = vector<licenses>; #pragma db value(licenses) definition @@ -192,12 +168,12 @@ namespace brep #pragma db value struct package_id { - std::string name; + string name; canonical_version version; package_id () = default; - package_id (std::string n, const brep::version& v) - : name (std::move (n)), + package_id (string n, const brep::version& v) + : name (move (n)), version {v.epoch, v.canonical_upstream, v.revision} { } @@ -249,12 +225,12 @@ namespace brep { using package_type = brep::package; - odb::lazy_shared_ptr<package_type> package; + lazy_shared_ptr<package_type> package; optional<dependency_constraint> constraint; // Prerequisite package name. // - std::string + string name () const; // Database mapping. @@ -266,25 +242,25 @@ namespace brep operator<< (std::ostream&, const dependency&); #pragma db value - class dependency_alternatives: public std::vector<dependency> + class dependency_alternatives: public vector<dependency> { public: bool conditional; - std::string comment; + string comment; dependency_alternatives () = default; explicit - dependency_alternatives (bool d, std::string c) - : conditional (d), comment (std::move (c)) {} + dependency_alternatives (bool d, string c) + : conditional (d), comment (move (c)) {} }; - using dependencies = std::vector<dependency_alternatives>; + using dependencies = vector<dependency_alternatives>; // requirements // using bpkg::requirement_alternatives; - using requirements = std::vector<requirement_alternatives>; + using requirements = vector<requirement_alternatives>; #pragma db value(requirement_alternatives) definition @@ -292,35 +268,41 @@ namespace brep // using bpkg::repository_location; - #pragma db map type(repository_location) as(std::string) \ + #pragma db map type(repository_location) as(string) \ to((?).string ()) from(brep::repository_location (?)) - #pragma db object pointer(std::shared_ptr) session + #pragma db object pointer(shared_ptr) session class repository { public: // Create internal repository. // repository (repository_location, - std::string display_name, - dir_path local_path); + string display_name, + dir_path local_path, + uint16_t priority); // Create external repository. // explicit repository (repository_location); - std::string name; // Object id (canonical name). + string name; // Object id (canonical name). repository_location location; - std::string display_name; + string display_name; + + // The order in the internal repositories configuration file, starting from + // 1. 0 for external repositories. + // + uint16_t priority; - optional<std::string> url; + optional<string> url; - // Set only for internal repositories. + // Present only for internal repositories. // - optional<std::string> email; - optional<std::string> summary; - optional<std::string> description; + optional<string> email; + optional<string> summary; + optional<string> description; // Non empty for internal repositories and external ones with a filesystem // path location. @@ -336,8 +318,8 @@ namespace brep timestamp repositories_timestamp; bool internal; - std::vector<odb::lazy_weak_ptr<repository>> complements; - std::vector<odb::lazy_weak_ptr<repository>> prerequisites; + vector<lazy_weak_ptr<repository>> complements; + vector<lazy_weak_ptr<repository>> prerequisites; // Database mapping. // @@ -372,13 +354,13 @@ namespace brep #pragma db value type("tsvector") struct weighted_text { - std::string a; - std::string b; - std::string c; - std::string d; + string a; + string b; + string c; + string d; }; - #pragma db object pointer(std::shared_ptr) session + #pragma db object pointer(shared_ptr) session class package { public: @@ -393,14 +375,14 @@ namespace brep // Create internal package object. // - package (std::string name, + package (string name, version_type, priority_type, - std::string summary, + string summary, license_alternatives_type, strings tags, - optional<std::string> description, - std::string changes, + optional<string> description, + string changes, url_type, optional<url_type> package_url, email_type, @@ -408,7 +390,7 @@ namespace brep dependencies_type, requirements_type, optional<path> location, - std::shared_ptr<repository_type>); + shared_ptr<repository_type>); // Create external package object. // @@ -417,7 +399,7 @@ namespace brep // The only package information required to compose such a link is the // package name, version, and repository location. // - package (std::string name, version_type, std::shared_ptr<repository_type>); + package (string name, version_type, shared_ptr<repository_type>); bool internal () const noexcept {return internal_repository != nullptr;} @@ -427,24 +409,24 @@ namespace brep package_id id; upstream_version version; priority_type priority; - std::string summary; + string summary; license_alternatives_type license_alternatives; strings tags; - optional<std::string> description; - std::string changes; + optional<string> description; + string changes; url_type url; optional<url_type> package_url; email_type email; optional<email_type> package_email; dependencies_type dependencies; requirements_type requirements; - odb::lazy_shared_ptr<repository_type> internal_repository; + lazy_shared_ptr<repository_type> internal_repository; - // Path to the package file. Set only for internal packages. + // Path to the package file. Present only for internal packages. // optional<path> location; - std::vector<odb::lazy_shared_ptr<repository_type>> other_repositories; + vector<lazy_shared_ptr<repository_type>> other_repositories; // Database mapping. // @@ -454,7 +436,7 @@ namespace brep // license // using _license_key = odb::nested_key<licenses>; - using _licenses_type = std::map<_license_key, std::string>; + using _licenses_type = std::map<_license_key, string>; #pragma db value(_license_key) #pragma db member(_license_key::outer) column("alternative_index") @@ -494,18 +476,18 @@ namespace brep // using _requirement_key = odb::nested_key<requirement_alternatives>; using _requirement_alternatives_type = - std::map<_requirement_key, std::string>; + std::map<_requirement_key, string>; #pragma db value(_requirement_key) #pragma db member(_requirement_key::outer) column("requirement_index") #pragma db member(_requirement_key::inner) column("index") #pragma db member(requirements) id_column("") value_column("") - #pragma db member(requirement_alternatives) \ - virtual(_requirement_alternatives_type) \ - after(requirements) \ - get(odb::nested_get (this.requirements)) \ - set(odb::nested_set (this.requirements, move (?))) \ + #pragma db member(requirement_alternatives) \ + virtual(_requirement_alternatives_type) \ + after(requirements) \ + get(odb::nested_get (this.requirements)) \ + set(odb::nested_set (this.requirements, std::move (?))) \ id_column("") key_column("") value_column("id") // other_repositories @@ -550,9 +532,9 @@ namespace brep query("/*CALL*/ SELECT count(*) FROM search_latest_packages(?)") struct latest_package_count { - std::size_t result; + size_t result; - operator std::size_t () const {return result;} + operator size_t () const {return result;} }; #pragma db view query("/*CALL*/ SELECT * FROM search_packages(?)") @@ -565,9 +547,9 @@ namespace brep #pragma db view query("/*CALL*/ SELECT count(*) FROM search_packages(?)") struct package_count { - std::size_t result; + size_t result; - operator std::size_t () const {return result;} + operator size_t () const {return result;} }; #pragma db view query("/*CALL*/ SELECT * FROM latest_package(?)") diff --git a/brep/package-details b/brep/package-details index 471dcee..214a0fe 100644 --- a/brep/package-details +++ b/brep/package-details @@ -5,10 +5,9 @@ #ifndef BREP_PACKAGE_DETAILS #define BREP_PACKAGE_DETAILS -#include <memory> // shared_ptr - #include <odb/forward.hxx> // database +#include <brep/types> #include <brep/module> #include <brep/options> @@ -24,8 +23,8 @@ namespace brep init (cli::scanner&); private: - std::shared_ptr<options::package_details> options_; - std::shared_ptr<odb::core::database> db_; + shared_ptr<options::package_details> options_; + shared_ptr<odb::core::database> db_; }; } diff --git a/brep/package-details.cxx b/brep/package-details.cxx index 8be6108..4b99feb 100644 --- a/brep/package-details.cxx +++ b/brep/package-details.cxx @@ -4,11 +4,6 @@ #include <brep/package-details> -#include <string> -#include <memory> // make_shared(), shared_ptr -#include <cstddef> // size_t -#include <cassert> - #include <xml/serializer> #include <odb/session.hxx> @@ -20,222 +15,225 @@ #include <web/mime-url-encoding> #include <brep/page> +#include <brep/types> +#include <brep/utility> #include <brep/options> #include <brep/package> #include <brep/package-odb> #include <brep/shared-database> -using namespace std; using namespace odb::core; +using namespace brep::cli; -namespace brep +void brep::package_details:: +init (scanner& s) { - using namespace cli; + MODULE_DIAG; - void package_details:: - init (scanner& s) - { - MODULE_DIAG; + options_ = make_shared<options::package_details> ( + s, unknown_mode::fail, unknown_mode::fail); - options_ = make_shared<options::package_details> ( - s, unknown_mode::fail, unknown_mode::fail); + db_ = shared_database (options_->db_host (), options_->db_port ()); +} - db_ = shared_database (options_->db_host (), options_->db_port ()); - } +template <typename T> +static inline query<T> +search_params (const brep::string& n, const brep::string& q) +{ + using query = query<T>; + + return "(" + + (q.empty () + ? query ("NULL") + : "plainto_tsquery (" + query::_val (q) + ")") + + "," + + query::_val (n) + + ")"; +} - template <typename T> - static inline query<T> - search_params (const string& n, const string& q) - { - using query = query<T>; - - return "(" + - (q.empty () - ? query ("NULL") - : "plainto_tsquery (" + query::_val (q) + ")") + - "," + - query::_val (n) + - ")"; - } +void brep::package_details:: +handle (request& rq, response& rs) +{ + using namespace web; + using namespace web::xhtml; - void package_details:: - handle (request& rq, response& rs) - { - using namespace web; - using namespace web::xhtml; + MODULE_DIAG; - MODULE_DIAG; + // The module options object is not changed after being created once per + // server process. + // + static const size_t res_page (options_->results_on_page ()); + static const dir_path& root ( + options_->root ().empty () + ? dir_path ("/") + : options_->root ()); - // 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 ().empty () - ? dir_path ("/") - : options_->root ()); + const string& name (*rq.path ().rbegin ()); + const string ename (mime_url_encode (name)); - const string& name (*rq.path ().rbegin ()); - const string en (mime_url_encode (name)); + params::package_details params; + bool full; - params::package_details pr; + try + { + param_scanner s (rq.parameters ()); + params = params::package_details ( + s, unknown_mode::fail, unknown_mode::fail); - try - { - param_scanner s (rq.parameters ()); - pr = params::package_details (s, unknown_mode::fail, unknown_mode::fail); - } - catch (const unknown_argument& e) - { - throw invalid_request (400, e.what ()); - } - - const string& sq (pr.query ()); // Search query. - size_t pg (pr.page ()); - bool f (pr.full ()); - - auto url ( - [&en](bool f = false, - const string& q = "", - size_t p = 0, - const string& a = "") -> string - { - string s ("?"); - string u (en); - - if (f) { u += "?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); - const string& title (sq.empty () ? name : name + " " + sq); - static const path sp ("package-details.css"); - - s << HTML - << HEAD - << TITLE << title << ~TITLE - << CSS_LINKS (sp, rt) - << ~HEAD - << BODY - << DIV_HEADER (rt) - << DIV(ID="content"); - - if (f) - s << CLASS("full"); - - s << DIV(ID="heading") - << H1 << A(HREF=url ()) << name << ~A << ~H1 - << A(HREF=url (!f, sq, pg)) << (f ? "[brief]" : "[full]") << ~A - << ~DIV; - - session sn; - transaction t (db_->begin ()); - - shared_ptr<package> p; + 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 { - latest_package lp; - if (!db_->query_one<latest_package> ( - query<latest_package>( - "(" + query<latest_package>::_val (name) + ")"), lp)) - { - throw invalid_request (404, "Package '" + name + "' not found"); - } + 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) + << ~HEAD + << BODY + << DIV_HEADER (root) + << 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<package> pkg; + { + latest_package lp; + if (!db_->query_one<latest_package> ( + query<latest_package>( + "(" + query<latest_package>::_val (name) + ")"), lp)) + throw invalid_request (404, "Package '" + name + "' not found"); - p = db_->load<package> (lp.id); - } + pkg = db_->load<package> (lp.id); + } - const auto& ll (p->license_alternatives); + const auto& licenses (pkg->license_alternatives); - if (pg == 0) - { - // Display package details on the first page only. - // - 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, 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, rt) - << ~TBODY - << ~TABLE; - } - - auto pc ( - db_->query_value<package_count> ( - search_params<package_count> (name, sq))); - - auto r ( - db_->query<package_search_rank> ( - search_params<package_search_rank> (name, sq) + - "ORDER BY rank DESC, version_epoch DESC, " - "version_canonical_upstream DESC, version_revision DESC" + - "OFFSET" + to_string (pg * rp) + - "LIMIT" + to_string (rp))); - - s << FORM_SEARCH (sq) - << DIV_COUNTER (pc, "Version", "Versions"); - - // Enclose the subsequent tables to be able to use nth-child CSS selector. + if (page == 0) + { + // Display package details on the first page only. // - s << DIV; - for (const auto& pr: r) - { - shared_ptr<package> p (db_->load<package> (pr.id)); + 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_->description_length (), + 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; + } - s << TABLE(CLASS="proplist version") - << TBODY - << TR_VERSION (name, p->version.string (), rt) + auto pkg_count ( + db_->query_value<package_count> ( + search_params<package_count> (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<package_search_rank> ( + search_params<package_search_rank> (name, squery) + + "ORDER BY rank DESC, version_epoch DESC, " + "version_canonical_upstream DESC, version_revision DESC" + + "OFFSET" + to_string (page * res_page) + + "LIMIT" + to_string (res_page))) + { + shared_ptr<package> p (db_->load<package> (pr.id)); - // @@ Shouldn't we skip low priority row ? Don't think so, why? - // - << TR_PRIORITY (p->priority); + s << TABLE(CLASS="proplist version") + << TBODY + << TR_VERSION (name, p->version.string (), root) - // Comparing objects of the license_alternatives class as being of the - // vector<vector<string>> class, so comments are not considered. + // @@ Shouldn't we skip low priority row ? Don't think so, why? // - if (p->license_alternatives != ll) - s << TR_LICENSE (p->license_alternatives); + << TR_PRIORITY (p->priority); - assert (p->internal ()); + // Comparing objects of the license_alternatives class as being of the + // vector<vector<string>> class, so comments are not considered. + // + if (p->license_alternatives != licenses) + s << TR_LICENSE (p->license_alternatives); - // @@ 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. - // - // @@ 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 differes - // 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 (), rt) - << TR_DEPENDS (p->dependencies, rt) - << TR_REQUIRES (p->requirements) - << ~TBODY - << ~TABLE; - } - s << ~DIV; - - t.commit (); - - static const size_t pp (options_->pages_in_pager ()); - - s << DIV_PAGER (pg, pc, rp, pp, url (f, sq)) - << ~DIV - << ~BODY - << ~HTML; + 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_->pages_in_pager (), + url (full, squery)) + << ~DIV + << ~BODY + << ~HTML; } diff --git a/brep/package-search b/brep/package-search index 156ed68..a5c441e 100644 --- a/brep/package-search +++ b/brep/package-search @@ -5,10 +5,9 @@ #ifndef BREP_PACKAGE_SEARCH #define BREP_PACKAGE_SEARCH -#include <memory> // shared_ptr - #include <odb/forward.hxx> // database +#include <brep/types> #include <brep/module> #include <brep/options> @@ -24,8 +23,8 @@ namespace brep init (cli::scanner&); private: - std::shared_ptr<options::package_search> options_; - std::shared_ptr<odb::core::database> db_; + shared_ptr<options::package_search> options_; + shared_ptr<odb::core::database> db_; }; } diff --git a/brep/package-search.cxx b/brep/package-search.cxx index 6a349b0..f2f922c 100644 --- a/brep/package-search.cxx +++ b/brep/package-search.cxx @@ -4,10 +4,6 @@ #include <brep/package-search> -#include <string> -#include <memory> // make_shared(), shared_ptr -#include <cstddef> // size_t - #include <xml/serializer> #include <odb/session.hxx> @@ -19,134 +15,131 @@ #include <web/mime-url-encoding> #include <brep/page> +#include <brep/types> +#include <brep/utility> #include <brep/options> #include <brep/package> #include <brep/package-odb> #include <brep/shared-database> -using namespace std; using namespace odb::core; +using namespace brep::cli; -namespace brep +void brep::package_search:: +init (scanner& s) { - using namespace cli; + MODULE_DIAG; - void package_search:: - init (scanner& s) - { - MODULE_DIAG; + options_ = make_shared<options::package_search> ( + s, unknown_mode::fail, unknown_mode::fail); - options_ = make_shared<options::package_search> ( - s, unknown_mode::fail, unknown_mode::fail); + db_ = shared_database (options_->db_host (), options_->db_port ()); +} - db_ = shared_database (options_->db_host (), options_->db_port ()); - } +template <typename T> +static inline query<T> +search_param (const brep::string& q) +{ + using query = query<T>; + return "(" + + (q.empty () + ? query ("NULL") + : "plainto_tsquery (" + query::_val (q) + ")") + + ")"; +} + +void brep::package_search:: +handle (request& rq, response& rs) +{ + using namespace web::xhtml; - template <typename T> - static inline query<T> - search_param (const string& q) + MODULE_DIAG; + + // The module options object is not changed after being created once per + // server process. + // + static const size_t res_page (options_->results_on_page ()); + static const dir_path& root ( + options_->root ().empty () + ? dir_path ("/") + : options_->root ()); + + params::package_search params; + + try { - using query = query<T>; - return "(" + - (q.empty () - ? query ("NULL") - : "plainto_tsquery (" + query::_val (q) + ")") + - ")"; + param_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 ()); } - void package_search:: - handle (request& rq, response& rs) + 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.empty (); + + s << ~TITLE + << CSS_LINKS (path ("package-search.css"), root) + << ~HEAD + << BODY + << DIV_HEADER (root) + << DIV(ID="content"); + + session sn; + transaction t (db_->begin ()); + + auto pkg_count ( + db_->query_value<latest_package_count> ( + search_param<latest_package_count> (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<latest_package_search_rank> ( + search_param<latest_package_search_rank> (squery) + + "ORDER BY rank DESC, name" + + "OFFSET" + to_string (page * res_page) + + "LIMIT" + to_string (res_page))) { - using namespace web::xhtml; - - 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 ().empty () - ? dir_path ("/") - : options_->root ()); - - params::package_search pr; - - try - { - param_scanner s (rq.parameters ()); - pr = params::package_search (s, unknown_mode::fail, unknown_mode::fail); - } - catch (const unknown_argument& e) - { - throw invalid_request (400, e.what ()); - } - - const string& sq (pr.query ()); // Search query. - string qp (sq.empty () ? "" : "q=" + web::mime_url_encode (sq)); - size_t pg (pr.page ()); - - xml::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 (sp, rt) - << ~HEAD - << BODY - << DIV_HEADER (rt) - << DIV(ID="content"); - - session sn; - transaction t (db_->begin ()); - - auto pc ( - db_->query_value<latest_package_count> ( - search_param<latest_package_count> (sq))); - - auto r ( - db_->query<latest_package_search_rank> ( - search_param<latest_package_search_rank> (sq) + - "ORDER BY rank DESC, name" + - "OFFSET" + to_string (pg * rp) + - "LIMIT" + to_string (rp))); - - s << FORM_SEARCH (sq) - << DIV_COUNTER (pc, "Package", "Packages"); - - // Enclose the subsequent tables to be able to use nth-child CSS selector. - // - s << DIV; - for (const auto& pr: r) - { - shared_ptr<package> p (db_->load<package> (pr.id)); - - s << TABLE(CLASS="proplist package") - << TBODY - << TR_NAME (p->id.name, qp, rt) - << TR_SUMMARY (p->summary) - << TR_LICENSE (p->license_alternatives) - << TR_TAGS (p->tags, rt) - << TR_DEPENDS (p->dependencies, rt) - << TR_REQUIRES (p->requirements) - << ~TBODY - << ~TABLE; - } - s << ~DIV; - - t.commit (); - - 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, pp, u) - << ~DIV - << ~BODY - << ~HTML; + shared_ptr<package> p (db_->load<package> (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_->pages_in_pager (), + root.string () + squery_param) + << ~DIV + << ~BODY + << ~HTML; } diff --git a/brep/package-version-details b/brep/package-version-details index 7917de3..36b7420 100644 --- a/brep/package-version-details +++ b/brep/package-version-details @@ -5,10 +5,9 @@ #ifndef BREP_PACKAGE_VERSION_DETAILS #define BREP_PACKAGE_VERSION_DETAILS -#include <memory> // shared_ptr - #include <odb/forward.hxx> // database +#include <brep/types> #include <brep/module> #include <brep/options> @@ -24,8 +23,8 @@ namespace brep init (cli::scanner&); private: - std::shared_ptr<options::package_version_details> options_; - std::shared_ptr<odb::core::database> db_; + shared_ptr<options::package_version_details> options_; + shared_ptr<odb::core::database> db_; }; } diff --git a/brep/package-version-details.cxx b/brep/package-version-details.cxx index a1fe017..a0ad7d4 100644 --- a/brep/package-version-details.cxx +++ b/brep/package-version-details.cxx @@ -4,9 +4,6 @@ #include <brep/package-version-details> -#include <string> -#include <memory> // shared_ptr, make_shared() -#include <cassert> #include <stdexcept> // invalid_argument #include <xml/serializer> @@ -20,6 +17,8 @@ #include <web/mime-url-encoding> #include <brep/page> +#include <brep/types> +#include <brep/utility> #include <brep/options> #include <brep/package> #include <brep/package-odb> @@ -27,297 +26,285 @@ using namespace std; using namespace odb::core; +using namespace brep::cli; -namespace brep +void brep::package_version_details:: +init (scanner& s) { - using namespace cli; + MODULE_DIAG; - void package_version_details:: - init (scanner& s) - { - MODULE_DIAG; - - options_ = make_shared<options::package_version_details> ( - s, unknown_mode::fail, unknown_mode::fail); - - db_ = shared_database (options_->db_host (), options_->db_port ()); - } + options_ = make_shared<options::package_version_details> ( + s, unknown_mode::fail, unknown_mode::fail); - void package_version_details:: - handle (request& rq, response& rs) - { - using namespace web; - using namespace web::xhtml; + db_ = shared_database (options_->db_host (), options_->db_port ()); +} - MODULE_DIAG; +void brep::package_version_details:: +handle (request& rq, response& rs) +{ + using namespace web; + using namespace web::xhtml; - // The module options object is not changed after being created once per - // server process. - // - static const dir_path& rt ( - options_->root ().empty () - ? dir_path ("/") - : options_->root ()); + MODULE_DIAG; - auto i (rq.path ().rbegin ()); - version v; + // The module options object is not changed after being created once per + // server process. + // + static const dir_path& root ( + options_->root ().empty () + ? dir_path ("/") + : options_->root ()); - try - { - v = version (*i++); - } - catch (const invalid_argument& ) - { - throw invalid_request (400, "invalid package version format"); - } + auto i (rq.path ().rbegin ()); + version ver; - const string& vs (v.string ()); + try + { + ver = version (*i++); + } + catch (const invalid_argument& ) + { + throw invalid_request (400, "invalid package version format"); + } - assert (i != rq.path ().rend ()); - const string& n (*i); // Package name. - const string name (n + " " + vs); + const string& sver (ver.string ()); - params::package_version_details pr; + assert (i != rq.path ().rend ()); + const string& name (*i); - try - { - param_scanner s (rq.parameters ()); - pr = params::package_version_details ( - s, unknown_mode::fail, unknown_mode::fail); - } - catch (const unknown_argument& e) - { - throw invalid_request (400, e.what ()); - } + params::package_version_details params; + bool full; - bool f (pr.full ()); + try + { + param_scanner s (rq.parameters ()); + params = params::package_version_details ( + s, unknown_mode::fail, unknown_mode::fail); - auto url ([&vs](bool f = false, const string& a = "") -> string - { - string u (vs); - - if (f) { u += "?full"; } - if (!a.empty ()) { u += '#' + a; } - return u; - }); - - xml::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 (sp, rt) - << ~HEAD - << BODY - << DIV_HEADER (rt) - << DIV(ID="content"); - - if (f) - s << CLASS("full"); - - s << DIV(ID="heading") - << H1 - << A(HREF=rt / go / path (mime_url_encode (n))) << n << ~A - << "/" - << A(HREF=url ()) << vs << ~A - << ~H1 - << A(HREF=url (!f)) << (f ? "[brief]" : "[full]") << ~A - << ~DIV; - - bool not_found (false); - shared_ptr<package> p; - - session sn; - transaction t (db_->begin ()); - - try - { - p = db_->load<package> (package_id (n, v)); + full = params.form () == page_form::full; + } + catch (const unknown_argument& e) + { + throw invalid_request (400, e.what ()); + } - // If the requested package turned up to be an "external" one just - // respond that no "internal" package is present. - // - not_found = !p->internal (); - } - catch (const object_not_persistent& ) + auto url ( + [&sver](bool f = false, const string& a = "") -> string { - not_found = true; - } - - if (not_found) - throw invalid_request (404, "Package '" + name + "' not found"); - - 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, dl, url (!f, "description"))); + 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) + << 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<package> pkg; + + session sn; + transaction t (db_->begin ()); + + try + { + pkg = db_->load<package> (package_id (name, ver)); - // Link to download from the internal repository. + // If the requested package turned up to be an "external" one just + // respond that no "internal" package is present. // - assert (p->location); - const string du (p->internal_repository.load ()->location.string () + "/" + - p->location->string ()); + not_found = !pkg->internal (); + } + catch (const object_not_persistent& ) + { + not_found = true; + } - s << TABLE(CLASS="proplist", ID="version") - << TBODY + if (not_found) + throw invalid_request (404, "Package '" + title + "' not found"); - // Repeat version here since it can be cut out in the header. - // - << TR_VERSION (p->version.string ()) + s << H2 << pkg->summary << ~H2; - << TR_PRIORITY (p->priority) - << TR_LICENSES (p->license_alternatives) - << TR_LOCATION (p->internal_repository.object_id (), rt) - << TR_DOWNLOAD (du) - << ~TBODY - << ~TABLE + static const string id ("description"); + if (const auto& d = pkg->description) + s << (full + ? P_DESCRIPTION (*d, id) + : P_DESCRIPTION (*d, options_->description_length (), + url (!full, id))); - << TABLE(CLASS="proplist", ID="package") - << TBODY - << TR_URL (p->url) - << TR_EMAIL (p->email); + assert (pkg->location); - if (p->package_url && *p->package_url != p->url) - s << TR_URL (*p->package_url, "pkg-url"); + s << TABLE(CLASS="proplist", ID="version") + << TBODY - if (p->package_email && *p->package_email != p->email) - s << TR_EMAIL (*p->package_email, "pkg-email"); + // 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 ()) + << ~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; - s << TR_TAGS (p->tags, rt) - << ~TBODY - << ~TABLE; + for (const auto& da: ds) + { + s << TR(CLASS="depends") + << TH; - const auto& ds (p->dependencies); + if (da.conditional) + s << "?"; - if (!ds.empty ()) - { - s << H3 << "Depends" << ~H3 - << TABLE(CLASS="proplist", ID="depends") - << TBODY; + s << ~TH + << TD + << SPAN(CLASS="value"); - for (const auto& da: ds) + for (const auto& d: da) { - s << TR(CLASS="depends") - << TH; + if (&d != &da[0]) + s << " | "; - if (da.conditional) - s << "?"; + shared_ptr<package> p (d.package.load ()); + assert (p->internal () || !p->other_repositories.empty ()); - s << ~TH - << TD - << SPAN(CLASS="value"); + shared_ptr<repository> r ( + p->internal () + ? p->internal_repository.load () + : p->other_repositories[0].load ()); - for (const auto& d: da) + const auto& dcon (d.constraint); + const string& dname (p->id.name); + string ename (mime_url_encode (dname)); + + if (r->url) { - if (&d != &da[0]) - s << " | "; - - shared_ptr<package> p (d.package.load ()); - assert (p->internal () || !p->other_repositories.empty ()); - - shared_ptr<repository> r ( - p->internal () - ? p->internal_repository.load () - : p->other_repositories[0].load ()); - - const auto& dc (d.constraint); - const string& dn (p->id.name); - string en (mime_url_encode (dn)); - - if (r->url) - { - string u (*r->url + "go/" + en); - s << A(HREF=u) << dn << ~A; - - if (dc) - s << ' ' - << A - << 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 if no repository URL - // available. - // - s << d; + 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; - s << ~SPAN - << SPAN_COMMENT (da.comment) - << ~TD - << ~TR; + 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 << ~TBODY - << ~TABLE; + s << ~SPAN + << SPAN_COMMENT (da.comment) + << ~TD + << ~TR; } - t.commit (); + s << ~TBODY + << ~TABLE; + } - const auto& rm (p->requirements); + t.commit (); - if (!rm.empty ()) - { - s << H3 << "Requires" << ~H3 - << TABLE(CLASS="proplist", ID="requires") - << TBODY; + 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; + for (const auto& ra: rm) + { + s << TR(CLASS="requires") + << TH; - if (ra.conditional) - s << "?"; + if (ra.conditional) + s << "?"; - s << ~TH - << TD - << SPAN(CLASS="value"); + s << ~TH + << TD + << SPAN(CLASS="value"); - for (const auto& r: ra) - { - if (&r != &ra[0]) - s << " | "; - - s << r; - } + for (const auto& r: ra) + { + if (&r != &ra[0]) + s << " | "; - s << ~SPAN - << SPAN_COMMENT (ra.comment) - << ~TD - << ~TR; + s << r; } - s << ~TBODY - << ~TABLE; + s << ~SPAN + << SPAN_COMMENT (ra.comment) + << ~TD + << ~TR; } - 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, cl, url (!f, "changes"))); - - s << ~DIV - << ~BODY - << ~HTML; + s << ~TBODY + << ~TABLE; } + + const auto& ch (pkg->changes); + if (!ch.empty ()) + s << H3 << "Changes" << ~H3 + << (full + ? PRE_CHANGES (ch) + : PRE_CHANGES (ch, options_->description_length (), + url (!full, "changes"))); + + s << ~DIV + << ~BODY + << ~HTML; } diff --git a/brep/package.cxx b/brep/package.cxx index d99819c..ecaa369 100644 --- a/brep/package.cxx +++ b/brep/package.cxx @@ -4,12 +4,12 @@ #include <brep/package> -#include <utility> // move() -#include <cassert> #include <ostream> #include <odb/database.hxx> +#include <brep/types> +#include <brep/utility> #include <brep/package-odb> using namespace std; @@ -131,10 +131,11 @@ namespace brep // repository // repository:: - repository (repository_location l, string d, dir_path p) + repository (repository_location l, string d, dir_path p, uint16_t r) : name (l.canonical_name ()), location (move (l)), display_name (move (d)), + priority (r), local_path (move (p)), internal (true) { @@ -144,6 +145,7 @@ namespace brep repository (repository_location l) : name (l.canonical_name ()), location (move (l)), + priority (0), internal (false) { } @@ -5,11 +5,9 @@ #ifndef BREP_PAGE #define BREP_PAGE -#include <string> -#include <cstddef> // size_t - #include <xml/forward> +#include <brep/types> #include <brep/package> namespace brep @@ -51,13 +49,13 @@ namespace brep class FORM_SEARCH { public: - FORM_SEARCH (const std::string& q): query_ (q) {} + FORM_SEARCH (const string& q): query_ (q) {} void operator() (xml::serializer& s) const; private: - const std::string& query_; + const string& query_; }; // Generates counter element. @@ -69,14 +67,14 @@ namespace brep class DIV_COUNTER { public: - DIV_COUNTER (std::size_t c, const char* s, const char* p) + DIV_COUNTER (size_t c, const char* s, const char* p) : count_ (c), singular_ (s), plural_ (p) {} void operator() (xml::serializer& s) const; private: - std::size_t count_; + size_t count_; const char* singular_; const char* plural_; }; @@ -86,15 +84,15 @@ namespace brep class TR_NAME { public: - TR_NAME (const std::string& n, const std::string& q, const dir_path& r) + TR_NAME (const string& n, const string& q, const dir_path& r) : name_ (n), query_param_ (q), root_ (r) {} void operator() (xml::serializer& s) const; private: - const std::string& name_; - const std::string& query_param_; + const string& name_; + const string& query_param_; const dir_path& root_; }; @@ -105,22 +103,20 @@ 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, - const dir_path& r) + 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 std::string& v) + TR_VERSION (const string& v) : package_ (nullptr), version_ (v), root_ (nullptr) {} void operator() (xml::serializer& s) const; private: - const std::string* package_; - const std::string& version_; + const string* package_; + const string& version_; const dir_path* root_; }; @@ -129,13 +125,13 @@ namespace brep class TR_SUMMARY { public: - TR_SUMMARY (const std::string& s): summary_ (s) {} + TR_SUMMARY (const string& s): summary_ (s) {} void operator() (xml::serializer& s) const; private: - const std::string& summary_; + const string& summary_; }; // Generates package license alternatives element. @@ -262,14 +258,14 @@ namespace brep class TR_LOCATION { public: - TR_LOCATION (const std::string& n, const dir_path& r) + TR_LOCATION (const string& n, const dir_path& r) : name_ (n), root_ (r) {} void operator() (xml::serializer& s) const; private: - const std::string& name_; + const string& name_; const dir_path& root_; }; @@ -278,13 +274,13 @@ namespace brep class TR_DOWNLOAD { public: - TR_DOWNLOAD (const std::string& u): url_ (u) {} + TR_DOWNLOAD (const string& u): url_ (u) {} void operator() (xml::serializer& s) const; private: - const std::string& url_; + const string& url_; }; // Generates comment element. @@ -292,13 +288,13 @@ namespace brep class SPAN_COMMENT { public: - SPAN_COMMENT (const std::string& c): comment_ (c) {} + SPAN_COMMENT (const string& c): comment_ (c) {} void operator() (xml::serializer& s) const; private: - const std::string& comment_; + const string& comment_; }; // Generates package description element. @@ -308,22 +304,22 @@ namespace brep public: // Genereate full description. // - P_DESCRIPTION (const std::string& d, bool u = true) - : description_ (d), length_ (d.size ()), url_ (nullptr), unique_ (u) {} + P_DESCRIPTION (const string& d, const string& id = "") + : description_ (d), length_ (d.size ()), url_ (nullptr), id_ (id) {} // Genereate brief description. // - P_DESCRIPTION (const std::string& d, size_t l, const std::string& u) - : description_ (d), length_ (l), url_ (&u), unique_ (false) {} + P_DESCRIPTION (const string& d, size_t l, const string& u) + : description_ (d), length_ (l), url_ (&u) {} void operator() (xml::serializer& s) const; private: - const std::string& description_; - std::size_t length_; - const std::string* url_; // Full page url. - bool unique_; + const string& description_; + size_t length_; + const string* url_; // Full page url. + string id_; }; // Generates package description element. @@ -333,21 +329,21 @@ namespace brep public: // Genereate full changes info. // - PRE_CHANGES (const std::string& c) + PRE_CHANGES (const string& c) : changes_ (c), length_ (c.size ()), url_ (nullptr) {} // Genereate brief changes info. // - PRE_CHANGES (const std::string& c, size_t l, const std::string& u) + PRE_CHANGES (const string& c, size_t l, const string& u) : changes_ (c), length_ (l), url_ (&u) {} void operator() (xml::serializer& s) const; private: - const std::string& changes_; - std::size_t length_; - const std::string* url_; // Full page url. + const string& changes_; + size_t length_; + const string* url_; // Full page url. }; // Generates paging element. @@ -355,28 +351,28 @@ namespace brep class DIV_PAGER { public: - DIV_PAGER (std::size_t current_page, - std::size_t item_count, - std::size_t item_per_page, - std::size_t page_number_count, - const std::string& url); + 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& s) const; private: - std::size_t current_page_; - std::size_t item_count_; - std::size_t item_per_page_; - std::size_t page_number_count_; - const std::string& url_; + 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. // - std::string - id_attribute (const std::string& v); + string + html_id (const string&); } #endif // BREP_PAGE diff --git a/brep/page.cxx b/brep/page.cxx index 5b650a3..780d759 100644 --- a/brep/page.cxx +++ b/brep/page.cxx @@ -6,10 +6,6 @@ #include <set> #include <ios> // hex, uppercase, right -#include <string> -#include <memory> // shared_ptr -#include <cstddef> // size_t -#include <cassert> #include <sstream> #include <iomanip> // setw(), setfill() #include <algorithm> // min() @@ -19,6 +15,8 @@ #include <web/xhtml> #include <web/mime-url-encoding> +#include <brep/types> +#include <brep/utility> #include <brep/package> #include <brep/package-odb> @@ -29,18 +27,16 @@ using namespace web::xhtml; namespace brep { - static const path go ("go"); - static const path about ("about"); - // CSS_LINKS // void CSS_LINKS:: operator() (serializer& s) const { - static const path c ("common.css"); + static const path css ("@"); - s << *LINK(REL="stylesheet", TYPE="text/css", HREF=root_ / c) - << *LINK(REL="stylesheet", TYPE="text/css", HREF=root_ / path_); + s << *LINK(REL="stylesheet", TYPE="text/css", + HREF=root_ / css / path ("common.css")) + << *LINK(REL="stylesheet", TYPE="text/css", HREF=root_ / css / path_); } // DIV_HEADER @@ -51,7 +47,7 @@ namespace brep s << DIV(ID="header") << DIV(ID="header-menu") << A(HREF=root_) << "packages" << ~A - << A(HREF=root_ / about) << "about" << ~A + << A(HREF=root_.string () + "?about") << "about" << ~A << ~DIV << ~DIV; } @@ -105,14 +101,12 @@ namespace brep << SPAN(CLASS="value") << A << HREF - << root_ / go / path (mime_url_encode (name_)); - // Propagate search criteria to the package details page. - // - if (!query_param_.empty ()) - s << "?" << query_param_; + // Propagate search criteria to the package details page. + // + << root_ / path (mime_url_encode (name_)) << query_param_ - s << ~HREF + << ~HREF << name_ << ~A << ~SPAN @@ -133,8 +127,9 @@ namespace brep else { assert (root_ != nullptr); - path p (mime_url_encode (*package_)); - s << A(HREF=*root_ / go / p / path (version_)) << version_ << ~A; + s << A(HREF=*root_ / path (mime_url_encode (*package_)) / path (version_)) + << version_ + << ~A; } s << ~SPAN @@ -234,8 +229,7 @@ namespace brep if (&t != &tags_[0]) s << " "; - s << A - << HREF << root_ << "?q=" << mime_url_encode (t) << ~HREF + s << A << HREF << root_ << "?q=" << mime_url_encode (t) << ~HREF << t << ~A; } @@ -270,25 +264,25 @@ namespace brep // Suppress package name duplicates. // - set<string> ds; + set<string> names; for (const auto& da: d) - ds.emplace (da.name ()); + names.emplace (da.name ()); - bool m (ds.size () > 1); + bool mult (names.size () > 1); - if (m) + if (mult) s << "("; - bool f (true); // First dependency alternative. + bool first (true); for (const auto& da: d) { string n (da.name ()); - if (ds.find (n) != ds.end ()) + if (names.find (n) != names.end ()) { - ds.erase (n); + names.erase (n); - if (f) - f = false; + if (first) + first = false; else s << " | "; @@ -303,9 +297,9 @@ namespace brep auto en (mime_url_encode (n)); if (r->url) - s << A << HREF << *r->url << "go/" << en << ~HREF << n << ~A; + s << A(HREF=*r->url + en) << n << ~A; else if (p->internal ()) - s << A(HREF=root_ / go / path (en)) << n << ~A; + s << A(HREF=root_ / path (en)) << n << ~A; else // Display the dependency as a plain text if no repository URL // available. @@ -314,7 +308,7 @@ namespace brep } } - if (m) + if (mult) s << ")"; } @@ -365,9 +359,9 @@ namespace brep } else { - bool m (r.size () > 1); + bool mult (r.size () > 1); - if (m) + if (mult) s << "("; for (const auto& ra: r) @@ -378,7 +372,7 @@ namespace brep s << ra; } - if (m) + if (mult) s << ")"; } } @@ -411,7 +405,7 @@ namespace brep << TH << label_ << ~TH << TD << SPAN(CLASS="value") - << A << HREF << "mailto:" << email_ << ~HREF << email_ << ~A + << A(HREF="mailto:" + email_) << email_ << ~A << ~SPAN << SPAN_COMMENT (email_.comment) << ~TD @@ -446,7 +440,7 @@ namespace brep << SPAN(CLASS="value") << A << HREF - << root_ / about << "#" << mime_url_encode (id_attribute (name_)) + << root_ << "?about#" << mime_url_encode (html_id (name_)) << ~HREF << name_ << ~A @@ -475,7 +469,7 @@ namespace brep { if (size_t l = comment_.size ()) s << SPAN(CLASS="comment") - << (comment_[l - 1] == '.' ? string (comment_, 0, l - 1) : comment_) + << (comment_.back () == '.' ? string (comment_, 0, l - 1) : comment_) << ~SPAN; } @@ -488,19 +482,19 @@ namespace brep return; auto n (description_.find_first_of (" \t\n", length_)); - bool f (n == string::npos); // Description length is below the limit. + bool full (n == string::npos); // Description length is below the limit. // Truncate description if length exceed the limit. // - const string& d (f ? description_ : string (description_, 0, n)); + 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 (unique_) - s << ID("description"); + if (!id_.empty ()) + s << ID(id_); bool nl (false); // The previous character is '\n'. for (const auto& c: d) @@ -527,7 +521,7 @@ namespace brep } } - if (!f) + if (!full) { assert (url_ != nullptr); s << "... " << A(HREF=*url_) << "More" << ~A; @@ -545,14 +539,14 @@ namespace brep return; auto n (changes_.find_first_of (" \t\n", length_)); - bool f (n == string::npos); // Changes length is below the limit. + bool full (n == string::npos); // Changes length is below the limit. // Truncate changes if length exceed the limit. // - const string& c (f ? changes_ : string (changes_, 0, n)); + const string& c (full ? changes_ : string (changes_, 0, n)); s << PRE(ID="changes") << c; - if (!f) + if (!full) { assert (url_ != nullptr); s << "... " << A(HREF=*url_) << "More" << ~A; @@ -583,14 +577,14 @@ namespace brep if (item_count_ == 0 || item_per_page_ == 0) return; - size_t pc (item_count_ / item_per_page_); // Page count. + size_t pcount (item_count_ / item_per_page_); // Page count. if (item_count_ % item_per_page_) - ++pc; + ++pcount; - if (pc > 1) + if (pcount > 1) { - auto u ( + auto url ( [this](size_t page) -> string { return page == 0 @@ -602,17 +596,17 @@ namespace brep s << DIV(ID="pager"); if (current_page_ > 0) - s << A(ID="prev", HREF=u (current_page_ - 1)) << "Prev" << ~A; + s << A(ID="prev", HREF=url (current_page_ - 1)) << "Prev" << ~A; if (page_number_count_) { size_t offset (page_number_count_ / 2); - size_t fp (current_page_ > offset ? current_page_ - offset : 0); - size_t tp (min (fp + page_number_count_, pc)); + size_t from (current_page_ > offset ? current_page_ - offset : 0); + size_t to (min (from + page_number_count_, pcount)); - for (size_t p (fp); p < tp; ++p) + for (size_t p (from); p < to; ++p) { - s << A(HREF=u (p)); + s << A(HREF=url (p)); if (p == current_page_) s << ID("curr"); @@ -622,8 +616,8 @@ namespace brep } } - if (current_page_ < pc - 1) - s << A(ID="next", HREF=u (current_page_ + 1)) << "Next" << ~A; + if (current_page_ < pcount - 1) + s << A(ID="next", HREF=url (current_page_ + 1)) << "Next" << ~A; s << ~DIV; } @@ -634,7 +628,7 @@ namespace brep // http://www.w3.org/TR/html5/dom.html#the-id-attribute. // string - id_attribute (const string& v) + html_id (const string& v) { ostringstream o; o << hex << uppercase << right << setfill ('0'); @@ -654,9 +648,8 @@ namespace brep case '\f': case '~': { - // Intentionally use '~' as an escape character to leave it unescaped - // being a part of URL. For example - // http://cppget.org/about#cppget.org%2Fmath~20lab + // We use '~' as an escape character because it doesn't require + // escaping in URLs. // o << "~" << setw (2) << static_cast<unsigned short> (c); break; diff --git a/brep/repository-details b/brep/repository-details index a3008dc..fb41e32 100644 --- a/brep/repository-details +++ b/brep/repository-details @@ -5,10 +5,9 @@ #ifndef BREP_REPOSITORY_DETAILS #define BREP_REPOSITORY_DETAILS -#include <memory> // shared_ptr - #include <odb/forward.hxx> // database +#include <brep/types> #include <brep/module> #include <brep/options> @@ -24,8 +23,8 @@ namespace brep init (cli::scanner&); private: - std::shared_ptr<options::repository_details> options_; - std::shared_ptr<odb::core::database> db_; + shared_ptr<options::repository_details> options_; + shared_ptr<odb::core::database> db_; }; } diff --git a/brep/repository-details.cxx b/brep/repository-details.cxx index 86a6099..eb2885c 100644 --- a/brep/repository-details.cxx +++ b/brep/repository-details.cxx @@ -4,9 +4,6 @@ #include <brep/repository-details> -#include <string> -#include <memory> // make_shared() - #include <xml/serializer> #include <odb/database.hxx> @@ -17,85 +14,96 @@ #include <web/mime-url-encoding> #include <brep/page> +#include <brep/types> +#include <brep/utility> #include <brep/options> #include <brep/package> #include <brep/package-odb> #include <brep/shared-database> -using namespace std; using namespace odb::core; +using namespace brep::cli; -namespace brep +void brep::repository_details:: +init (scanner& s) { - using namespace cli; + MODULE_DIAG; - void repository_details:: - init (scanner& s) - { - MODULE_DIAG; + options_ = make_shared<options::repository_details> ( + s, unknown_mode::fail, unknown_mode::fail); - options_ = make_shared<options::repository_details> ( - s, unknown_mode::fail, unknown_mode::fail); + db_ = shared_database (options_->db_host (), options_->db_port ()); +} - db_ = shared_database (options_->db_host (), options_->db_port ()); - } +void brep::repository_details:: +handle (request& rq, response& rs) +{ + using namespace web::xhtml; - void repository_details:: - handle (request&, response& rs) + MODULE_DIAG; + + // The module options object is not changed after being created once per + // server process. + // + static const dir_path& root ( + options_->root ().empty () + ? dir_path ("/") + : options_->root ()); + + // Make sure no parameters passed. + // + try { - using namespace web::xhtml; + param_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 ()); + } - MODULE_DIAG; + static const string title ("About"); + xml::serializer s (rs.content (), title); - // The module options object is not changed after being created once per - // server process. + s << HTML + << HEAD + << TITLE << title << ~TITLE + << CSS_LINKS (path ("repository-details.css"), root) + << ~HEAD + << BODY + << DIV_HEADER (root) + << DIV(ID="content"); + + transaction t (db_->begin ()); + + using query = query<repository>; + + for (const auto& r: + db_->query<repository> ( + 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. // - static const dir_path& rt ( - options_->root ().empty () - ? dir_path ("/") - : options_->root ()); - - xml::serializer s (rs.content (), "About"); - const string& title (s.output_name ()); - static const path sp ("repository-details.css"); - - s << HTML - << HEAD - << TITLE << title << ~TITLE - << CSS_LINKS (sp, rt) - << ~HEAD - << BODY - << DIV_HEADER (rt) - << DIV(ID="content"); - - transaction t (db_->begin ()); - - using query = query<repository>; - auto rp (db_->query<repository> (query::internal + "ORDER BY name")); - - for (const auto& r: rp) - { - string id (id_attribute (r.name)); - s << H1(ID=id) - << A(HREF="#" + web::mime_url_encode (id)) << r.name << ~A - << ~H1; - - if (r.summary) - s << H2 << *r.summary << ~H2; - - if (r.description) - s << P_DESCRIPTION (*r.description, false); - - if (r.email) - s << P - << A << HREF << "mailto:" << *r.email << ~HREF << *r.email << ~A - << ~P; - } - - t.commit (); - - s << ~DIV - << ~BODY - << ~HTML; + 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) + s << P << A(HREF="mailto:" + *r.email) << *r.email << ~A << ~P; } + + t.commit (); + + s << ~DIV + << ~BODY + << ~HTML; } diff --git a/brep/repository-root b/brep/repository-root new file mode 100644 index 0000000..e5fba78 --- /dev/null +++ b/brep/repository-root @@ -0,0 +1,31 @@ +// file : brep/repository-root -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BREP_REPOSITORY_ROOT +#define BREP_REPOSITORY_ROOT + +#include <brep/module> + +namespace brep +{ + class package_search; + class repository_details; + + class repository_root: public module + { + public: + repository_root (package_search& ps, repository_details& rd) + : package_search_ (ps), repository_details_ (rd) {} + + private: + virtual void + handle (request&, response&); + + private: + package_search& package_search_; + repository_details& repository_details_; + }; +} + +#endif // BREP_REPOSITORY_ROOT diff --git a/brep/repository-root.cxx b/brep/repository-root.cxx new file mode 100644 index 0000000..180d61f --- /dev/null +++ b/brep/repository-root.cxx @@ -0,0 +1,119 @@ +// file : brep/repository-root.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include <brep/repository-root> + +#include <map> +#include <functional> + +#include <web/module> + +#include <brep/types> +#include <brep/utility> +#include <brep/package-search> +#include <brep/repository-details> + +using namespace std; + +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 () {return request_.content ();} + + private: + request& request_; + const name_values& parameters_; + }; + + // repository_root + // + void repository_root:: + handle (request& rq, response& rs) + { + MODULE_DIAG; + + // Dispatch request handling to the appropriate module depending on the + // function name passed as a first HTTP request parameter. The parameter + // should have no value specified. If no function name is passed, + // the default handler is selected. Example: cppget.org/?about + // + + string func; + name_values params (rq.parameters ()); + + // Obtain the function name. + // + if (!params.empty () && !params.front ().value) + { + func = move (params.front ().name); + + // Cleanup not to confuse the selected handler with the unknown parameter. + // + params.erase (params.begin ()); + } + + // To handle the request a new module instance is created as a copy of + // the corresponsing exemplar. + // + using module_ptr = unique_ptr<module>; + + // Function name to module factory map. + // + const map<string, function<module_ptr()>> + handlers ({ + { + "about", + [this]() -> module_ptr + {return module_ptr (new repository_details (repository_details_));} + }, + { + string (), // The default handler. + [this]() -> module_ptr + {return module_ptr (new package_search (package_search_));} + }}); + + // Find proper handler. + // + auto i (handlers.find (func)); + if (i == handlers.end ()) + throw invalid_request (400, "unknown function"); + + module_ptr m (i->second ()); + if (m->loaded ()) + { + // Delegate request handling. + // + // @@ An exception thrown by the handler will be attributed to the + // repository-root service while being logged. Could intercept + // exception handling to fix that, but let's not complicate the + // code for the time being. + // + // + request_proxy rqp (rq, params); + m->handle (rqp, rs); + } + else + // The module is not loaded, presumably being disabled in the web server + // configuration file. + // + throw invalid_request (404, "handler not available"); + } +} diff --git a/brep/services.cxx b/brep/services.cxx index e41d3f3..b214a09 100644 --- a/brep/services.cxx +++ b/brep/services.cxx @@ -8,6 +8,7 @@ #include <brep/package-search> #include <brep/package-details> +#include <brep/repository-root> #include <brep/repository-details> #include <brep/package-version-details> @@ -37,3 +38,9 @@ service AP_MODULE_DECLARE_DATA repository_details_srv ( "repository-details", repository_details_mod, {"root", "db-host", "db-port", "conf"}); + +static repository_root repository_root_mod ( + package_search_mod, repository_details_mod); +service AP_MODULE_DECLARE_DATA repository_root_srv ( + "repository-root", + repository_root_mod); diff --git a/brep/shared-database b/brep/shared-database index 36fa0a2..4d8186d 100644 --- a/brep/shared-database +++ b/brep/shared-database @@ -5,11 +5,10 @@ #ifndef BREP_SHARED_DATABASE #define BREP_SHARED_DATABASE -#include <string> -#include <memory> // shared_ptr - #include <odb/forward.hxx> // database +#include <brep/types> + namespace brep { // Returns pointer to the shared database instance, creating one on the @@ -17,8 +16,8 @@ namespace brep // to ones of the existing database instance throwing runtime_error // otherwise. Is not thread-safe. // - std::shared_ptr<odb::core::database> - shared_database (const std::string& host, unsigned int port); + shared_ptr<odb::core::database> + shared_database (const string& host, unsigned int port); } #endif // BREP_SHARED_DATABASE diff --git a/brep/shared-database.cxx b/brep/shared-database.cxx index fc17659..c1d128f 100644 --- a/brep/shared-database.cxx +++ b/brep/shared-database.cxx @@ -4,12 +4,12 @@ #include <brep/shared-database> -#include <memory> // weak_ptr, shared_ptr, make_shared() #include <stdexcept> // runtime_error #include <odb/pgsql/database.hxx> -using namespace std; +#include <brep/types> +#include <brep/utility> namespace brep { @@ -27,7 +27,7 @@ namespace brep if (shared_ptr<database> d = db.lock ()) { if (h != d->host () || p != d->port ()) - throw runtime_error ("shared database host/port mismatch"); + throw std::runtime_error ("shared database host/port mismatch"); return d; } diff --git a/brep/types b/brep/types new file mode 100644 index 0000000..d3b7b2d --- /dev/null +++ b/brep/types @@ -0,0 +1,60 @@ +// file : brep/types -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BREP_TYPES +#define BREP_TYPES + +#include <vector> +#include <string> +#include <memory> // unique_ptr, weak_ptr, shared_ptr +#include <cstddef> // size_t +#include <cstdint> // uint{8,16,32,64}_t + +#include <odb/lazy-ptr.hxx> + +#include <butl/path> +#include <butl/path-io> +#include <butl/optional> +#include <butl/timestamp> + +namespace brep +{ + // Commonly-used types + // + using std::uint8_t; + using std::uint16_t; + using std::uint32_t; + using std::uint64_t; + using std::size_t; + using std::vector; + using std::string; + + using strings = vector<string>; + + using butl::optional; + using butl::nullopt; + + // Smart pointers + // + using std::unique_ptr; + + using std::shared_ptr; + using std::weak_ptr; + + using odb::lazy_shared_ptr; + using odb::lazy_weak_ptr; + + // <butl/path> + // + using butl::path; + using butl::dir_path; + using butl::invalid_path; + + // <butl/timestamp> + // + using butl::timestamp; + using butl::timestamp_nonexistent; +} + +#endif // BREP_TYPES diff --git a/brep/types-parsers b/brep/types-parsers index 6d30544..dfe86a6 100644 --- a/brep/types-parsers +++ b/brep/types-parsers @@ -8,7 +8,8 @@ #ifndef BREP_TYPES_PARSERS #define BREP_TYPES_PARSERS -#include <butl/path> +#include <brep/types> +#include <brep/options-types> namespace brep { @@ -20,10 +21,17 @@ namespace brep struct parser; template <> - struct parser<butl::dir_path> + struct parser<dir_path> { static void - parse (butl::dir_path&, scanner&); + parse (dir_path&, scanner&); + }; + + template <> + struct parser<page_form> + { + static void + parse (page_form&, scanner&); }; } } diff --git a/brep/types-parsers.cxx b/brep/types-parsers.cxx index 6236000..f7f1c1b 100644 --- a/brep/types-parsers.cxx +++ b/brep/types-parsers.cxx @@ -4,16 +4,17 @@ #include <brep/types-parsers> -#include <butl/path> - +#include <brep/types> #include <brep/options> -using namespace butl; +using namespace std; namespace brep { namespace cli { + // Parse path. + // template <typename T> static void parse_path (T& x, scanner& s) @@ -40,5 +41,24 @@ namespace brep { parse_path (x, s); } + + // Parse page_form. + // + void parser<page_form>:: + 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); + } } } diff --git a/brep/utility b/brep/utility new file mode 100644 index 0000000..d978e2b --- /dev/null +++ b/brep/utility @@ -0,0 +1,20 @@ +// file : brep/utility -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BREP_UTILITY +#define BREP_UTILITY + +#include <string> // to_string() +#include <memory> // make_shared() +#include <cassert> +#include <utility> // move() + +namespace brep +{ + using std::move; + using std::make_shared; + using std::to_string; +}; + +#endif // BREP_UTILITY @@ -34,12 +34,12 @@ cli --include-with-brackets --include-prefix brep --hxx-suffix "" \ echo "g++ libbrep-apache.so" s="package-search.cxx package-details.cxx package-version-details.cxx \ -repository-details.cxx module.cxx diagnostics.cxx page.cxx services.cxx \ -options.cxx shared-database.cxx \ +repository-details.cxx repository-root.cxx module.cxx page.cxx services.cxx \ +options.cxx shared-database.cxx diagnostics.cxx \ ../web/apache/request.cxx ../web/apache/service.cxx \ ../web/mime-url-encoding.cxx" -g++ -shared $DEBUG -std=c++11 -I. -I/usr/include/apr-1 -I/usr/include/httpd \ +g++ -shared $DEBUG -std=c++11 -I/usr/include/apr-1 -I/usr/include/httpd \ -I.. -I../../libbpkg -I../../libbutl -L. -L../../libbpkg/bpkg \ -fPIC -o libbrep-apache.so $s -lbrep -lbpkg -lodb-pgsql -lodb -lstudxml @@ -53,7 +53,7 @@ echo "g++ brep-loader" s="loader.cxx options.cxx" -g++ $DEBUG -std=c++11 -I. -I.. -I../../libbpkg \ +g++ $DEBUG -std=c++11 -I.. -I../../libbpkg \ -I../../libbutl -L../brep -L../../libbpkg/bpkg -L../../libbutl/butl \ -o brep-loader $s -lbrep -lbpkg -lbutl -lodb-pgsql -lodb @@ -63,7 +63,7 @@ echo "g++ tests/loader" s="driver.cxx" -g++ $DEBUG -std=c++11 -I. -I../.. -I../../../libbpkg \ +g++ $DEBUG -std=c++11 -I../.. -I../../../libbpkg \ -I../../../libbutl -L../../brep -L../../../libbpkg/bpkg \ -L../../../libbutl/butl \ -o driver $s -lbrep -lbpkg -lbutl -lodb-pgsql -lodb diff --git a/etc/apachectl b/etc/apachectl index 895d580..4c67c1f 100755 --- a/etc/apachectl +++ b/etc/apachectl @@ -37,6 +37,7 @@ export AP_MODULE_DIR export AP_WWW_DIR export AP_CONFIG_DIR export AP_WORKSPACE_DIR +export AP_REPOSITORY_DIR if test -n "$AP_LIB_DIRS"; then export LD_LIBRARY_PATH=$AP_LIB_DIRS:$LD_LIBRARY_PATH @@ -44,6 +45,7 @@ fi mkdir -p "$AP_WORKSPACE_DIR" mkdir -p "$AP_LOG_DIR" +mkdir -p "$AP_REPOSITORY_DIR" # the path to your httpd binary, including options if necessary @@ -29,6 +29,7 @@ AP_WWW_DIR="$PROJECT_DIR/www" AP_CONFIG_DIR="$CONFIG_DIR" AP_LOG_DIR="$WORKSPACE_DIR/log/httpd" AP_WORKSPACE_DIR="$WORKSPACE_DIR/run/httpd" +AP_REPOSITORY_DIR="$WORKSPACE_DIR/www" # brep-loader settings (used in loader) # diff --git a/etc/httpd.conf b/etc/httpd.conf index 2570a5b..96a8b74 100644 --- a/etc/httpd.conf +++ b/etc/httpd.conf @@ -40,6 +40,8 @@ LoadModule expires_module /usr/lib64/httpd/modules/mod_expires.so LoadModule dir_module /usr/lib64/httpd/modules/mod_dir.so LoadModule alias_module /usr/lib64/httpd/modules/mod_alias.so +LoadModule repository_root_srv ${AP_MODULE_DIR}/libbrep-apache.so + LoadModule package_search_srv ${AP_MODULE_DIR}/libbrep-apache.so <IfModule package_search_srv> @@ -77,22 +79,32 @@ LoadModule repository_details_srv ${AP_MODULE_DIR}/libbrep-apache.so </IfModule> <LocationMatch ^${AP_ROOT}/?$> - SetHandler package-search + SetHandler repository-root </LocationMatch> -<LocationMatch ^${AP_ROOT}/go/[^/]+$> +<LocationMatch ^${AP_ROOT}/[^/]+$> SetHandler package-details </LocationMatch> -<LocationMatch ^${AP_ROOT}/go/[^/]+/[^/]+$> +<LocationMatch ^${AP_ROOT}/[^/]+/[^/]+$> SetHandler package-version-details </LocationMatch> -<LocationMatch ^${AP_ROOT}/about$> - SetHandler repository-details +# Disable package-version-details and package-details handlers on static files +# and repository content locations. +# Location examples: /@, /@/common.css, /1, /1/math/stable. +# +<LocationMatch ^${AP_ROOT}/(@|\d+)(/.*)?$> + SetHandler None </LocationMatch> -AliasMatch ^${AP_ROOT}/(.+) ${AP_WWW_DIR}/$1 +# Static files locations. +# +AliasMatch ^${AP_ROOT}/@/(.+) ${AP_WWW_DIR}/$1 + +# Repository files locations. +# +AliasMatch ^${AP_ROOT}/(\d+)/(.+) ${AP_REPOSITORY_DIR}/$1/$2 ExtendedStatus On diff --git a/etc/package-details.conf b/etc/package-details.conf index 49b3dce..66a7c17 100644 --- a/etc/package-details.conf +++ b/etc/package-details.conf @@ -8,8 +8,8 @@ verb 1 # brep::package_details options # -# @@ Set to 10 +# @@ Set to 10. results-on-page 2 pages-in-pager 5 -# @@ Set to 500 (~ 80 chars x 6 lines) +# @@ Set to 500 (~ 80 chars x 6 lines). description-length 100 diff --git a/etc/package-search.conf b/etc/package-search.conf index 80562b2..4c1484f 100644 --- a/etc/package-search.conf +++ b/etc/package-search.conf @@ -8,6 +8,6 @@ verb 1 # brep::package_search options # -# @@ Set to 10 +# @@ Set to 10. results-on-page 2 pages-in-pager 5 diff --git a/etc/package-version-details.conf b/etc/package-version-details.conf index 84fd75d..865e162 100644 --- a/etc/package-version-details.conf +++ b/etc/package-version-details.conf @@ -8,7 +8,7 @@ verb 1 # brep::package_version_details options # -# @@ Set to 500 (~ 80 chars x 6 lines) +# @@ Set to 500 (~ 80 chars x 6 lines). description-length 100 -# @@ Set to 5000 (~ 80 chars x 60 lines) +# @@ Set to 5000 (~ 80 chars x 60 lines). changes-length 100 diff --git a/loader/loader.cxx b/loader/loader.cxx index e9f5566..402194c 100644 --- a/loader/loader.cxx +++ b/loader/loader.cxx @@ -2,13 +2,7 @@ // copyright : Copyright (c) 2014-2015 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#include <vector> -#include <memory> // shared_ptr, make_shared() -#include <string> -#include <utility> // move() -#include <cstdint> // uint64_t #include <sstream> -#include <cassert> #include <fstream> #include <iostream> #include <stdexcept> // runtime_error, invalid_argument @@ -23,11 +17,12 @@ #include <odb/pgsql/connection.hxx> #include <odb/pgsql/transaction.hxx> -#include <butl/timestamp> // timestamp_nonexistent #include <butl/filesystem> #include <bpkg/manifest-parser> // manifest_parsing +#include <brep/types> +#include <brep/utility> #include <brep/package> #include <brep/package-odb> @@ -225,11 +220,10 @@ changed (const internal_repositories& repos, database& db) // Check if there is an internal repository not being listed in the // configuration file. // - auto rs ( - db.query<repository> ( - query::internal && !query::name.in_range (names.begin (), names.end ()))); - - return !rs.empty (); + return + !db.query<repository> ( + query::internal && !query::name.in_range (names.begin (), names.end ())). + empty (); } static timestamp @@ -249,8 +243,6 @@ manifest_stream (const path& p, ifstream& f) static void load_packages (const shared_ptr<repository>& rp, database& db) { - using brep::optional; // Ambiguity with butl::optional. - // packages_timestamp other than timestamp_nonexistent signals the // repository packages are already loaded. // @@ -430,6 +422,9 @@ load_repositories (const shared_ptr<repository>& rp, database& db) // Can, basically, repository be available on the web but have no web // interface associated ? // + // Yes, there can be no web interface. So we should just not form + // links to packages from such repos. + // if (rp->url) { // Normalize web interface url adding trailing '/' if not present. @@ -607,10 +602,8 @@ resolve_dependencies (package& p, database& db) } } - auto r ( - db.query<package> (q + order_by_version_desc (query::id.version))); - - for (const auto& pp: r) + for (const auto& pp: + db.query<package> (q + order_by_version_desc (query::id.version))) { if (find (p.internal_repository, pp)) { @@ -784,12 +777,14 @@ main (int argc, char* argv[]) // On the first pass over the internal repositories we load their // packages. // + uint16_t priority (1); for (const auto& ir: irs) { shared_ptr<repository> r ( make_shared<repository> (ir.location, move (ir.display_name), - move (ir.local_path))); + move (ir.local_path), + priority++)); load_packages (r, db); } @@ -811,20 +806,16 @@ main (int argc, char* argv[]) // Resolve internal packages dependencies. // - { - auto r (db.query<package> (query::internal_repository.is_not_null ())); - for (auto& p: r) - resolve_dependencies (p, db); - } + for (auto& p: + db.query<package> (query::internal_repository.is_not_null ())) + resolve_dependencies (p, db); // Ensure there is no package dependency cycles. // - { - package_ids chain; - auto r (db.query<package> (query::internal_repository.is_not_null ())); - for (const auto& p: r) - detect_dependency_cycle (p.id, chain, db); - } + package_ids chain; + for (const auto& p: + db.query<package> (query::internal_repository.is_not_null ())) + detect_dependency_cycle (p.id, chain, db); } t.commit (); diff --git a/loader/options.cli b/loader/options.cli index 9e96585..7045a22 100644 --- a/loader/options.cli +++ b/loader/options.cli @@ -2,23 +2,25 @@ // copyright : Copyright (c) 2014-2015 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -include <string>; -include <cstdint>; +include <brep/types>; -class options +namespace brep { - bool --help {"Print usage information and exit."}; - bool --version {"Print version and exit."}; - - std::string --db-host = "localhost" + class options { - "<host>", - "Connect database server using specified host or socket directory." - }; + bool --help {"Print usage information and exit."}; + bool --version {"Print version and exit."}; - std::uint16_t --db-port = 5432 - { - "<port>", - "Connect database server using specified port." + string --db-host = "localhost" + { + "<host>", + "Connect database server using specified host or socket directory." + }; + + uint16_t --db-port = 5432 + { + "<port>", + "Connect database server using specified port." + }; }; -}; +} diff --git a/tests/loader/external/1/basics/packages b/tests/loader/1/basics/packages index 86c20c1..86c20c1 100644 --- a/tests/loader/external/1/basics/packages +++ b/tests/loader/1/basics/packages diff --git a/tests/loader/external/1/basics/repositories b/tests/loader/1/basics/repositories index 57a1c7a..57a1c7a 100644 --- a/tests/loader/external/1/basics/repositories +++ b/tests/loader/1/basics/repositories diff --git a/tests/loader/internal/1/math/packages b/tests/loader/1/math/packages index 4d34c13..4d34c13 100644 --- a/tests/loader/internal/1/math/packages +++ b/tests/loader/1/math/packages diff --git a/tests/loader/internal/1/math/repositories b/tests/loader/1/math/repositories index c2df027..20aa30d 100644 --- a/tests/loader/internal/1/math/repositories +++ b/tests/loader/1/math/repositories @@ -1,7 +1,7 @@ : 1 # Foreign repository manifest. # -location: ../../../external/1/misc +location: ../misc : # Local repository manifest (this repository). # diff --git a/tests/loader/external/1/misc/packages b/tests/loader/1/misc/packages index e47208d..e47208d 100644 --- a/tests/loader/external/1/misc/packages +++ b/tests/loader/1/misc/packages diff --git a/tests/loader/external/1/misc/repositories b/tests/loader/1/misc/repositories index 1a41290..1a41290 100644 --- a/tests/loader/external/1/misc/repositories +++ b/tests/loader/1/misc/repositories diff --git a/tests/loader/internal/1/stable/packages b/tests/loader/1/stable/packages index 756a562..756a562 100644 --- a/tests/loader/internal/1/stable/packages +++ b/tests/loader/1/stable/packages diff --git a/tests/loader/internal/1/stable/repositories b/tests/loader/1/stable/repositories index c06f731..b692ebe 100644 --- a/tests/loader/internal/1/stable/repositories +++ b/tests/loader/1/stable/repositories @@ -1,7 +1,7 @@ : 1 # Foreign repository manifest. # -location: ../../../external/1/misc +location: ../misc : # Adjacent repository manifest. # diff --git a/tests/loader/external/1/staging/packages b/tests/loader/1/staging/packages index e7b22b0..e7b22b0 100644 --- a/tests/loader/external/1/staging/packages +++ b/tests/loader/1/staging/packages diff --git a/tests/loader/external/1/staging/repositories b/tests/loader/1/staging/repositories index 8443ab8..8443ab8 100644 --- a/tests/loader/external/1/staging/repositories +++ b/tests/loader/1/staging/repositories diff --git a/tests/loader/external/1/testing/packages b/tests/loader/1/testing/packages index bdebece..bdebece 100644 --- a/tests/loader/external/1/testing/packages +++ b/tests/loader/1/testing/packages diff --git a/tests/loader/external/1/testing/repositories b/tests/loader/1/testing/repositories index a218d5c..a218d5c 100644 --- a/tests/loader/external/1/testing/repositories +++ b/tests/loader/1/testing/repositories diff --git a/tests/loader/driver.cxx b/tests/loader/driver.cxx index 0d361ab..94a0b86 100644 --- a/tests/loader/driver.cxx +++ b/tests/loader/driver.cxx @@ -2,10 +2,6 @@ // copyright : Copyright (c) 2014-2015 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#include <vector> -#include <memory> // shared_ptr -#include <string> -#include <cassert> #include <iostream> #include <exception> #include <algorithm> // sort(), find() @@ -16,9 +12,10 @@ #include <odb/pgsql/database.hxx> #include <butl/process> -#include <butl/timestamp> // timestamp_nonexistent #include <butl/filesystem> +#include <brep/types> +#include <brep/utility> #include <brep/package> #include <brep/package-odb> @@ -59,8 +56,6 @@ check_external (const package& p) int main (int argc, char* argv[]) { - using brep::optional; // Ambiguity with butl::optional. - if (argc != 7) { cerr << "usage: " << argv[0] @@ -83,7 +78,7 @@ main (int argc, char* argv[]) // Update packages file timestamp to enforce loader to update // persistent state. // - path p (cp.directory () / path ("internal/1/stable/packages")); + path p (cp.directory () / path ("1/stable/packages")); char const* args[] = {"touch", p.string ().c_str (), nullptr}; assert (process (args).wait ()); @@ -115,8 +110,9 @@ main (int argc, char* argv[]) // assert (sr->location.canonical_name () == "cppget.org/stable"); assert (sr->location.string () == - "http://pkg.cppget.org/internal/1/stable"); + "http://pkg.cppget.org/1/stable"); assert (sr->display_name == "stable"); + assert (sr->priority == 1); assert (!sr->url); assert (sr->email && *sr->email == "repoman@cppget.org"); assert (sr->summary && @@ -125,7 +121,7 @@ main (int argc, char* argv[]) "This is the awesome C++ package repository full of exciting " "stuff."); - dir_path srp (cp.directory () / dir_path ("internal/1/stable")); + dir_path srp (cp.directory () / dir_path ("1/stable")); assert (sr->local_path == srp.normalize ()); assert (sr->packages_timestamp == srt); @@ -220,7 +216,7 @@ main (int argc, char* argv[]) assert (fpv2->dependencies[1][0] == dep ( "libexp", - brep::optional<dependency_constraint> ( + optional<dependency_constraint> ( dependency_constraint{comparison::eq, version ("1+1.2")}))); assert (fpv2->requirements.empty ()); @@ -250,7 +246,7 @@ main (int argc, char* argv[]) assert (fpv3->dependencies[0][0] == dep ( "libmisc", - brep::optional<dependency_constraint> ( + optional<dependency_constraint> ( dependency_constraint{comparison::ge, version ("2.0.0")}))); // libfoo-1.2.4 @@ -279,15 +275,16 @@ main (int argc, char* argv[]) assert (fpv4->dependencies[0][0] == dep ( "libmisc", - brep::optional<dependency_constraint> ( + optional<dependency_constraint> ( dependency_constraint{comparison::ge, version ("2.0.0")}))); // Verify 'math' repository. // assert (mr->location.canonical_name () == "cppget.org/math"); assert (mr->location.string () == - "http://pkg.cppget.org/internal/1/math"); + "http://pkg.cppget.org/1/math"); assert (mr->display_name == "math"); + assert (mr->priority == 2); assert (!mr->url); assert (mr->email && *mr->email == "repoman@cppget.org"); assert (mr->summary && *mr->summary == "Math C++ package repository"); @@ -295,7 +292,7 @@ main (int argc, char* argv[]) "This is the awesome C++ package repository full of remarkable " "algorithms and\nAPIs."); - dir_path mrp (cp.directory () / dir_path ("internal/1/math")); + dir_path mrp (cp.directory () / dir_path ("1/math")); assert (mr->local_path == mrp.normalize ()); assert (mr->packages_timestamp == @@ -413,13 +410,13 @@ main (int argc, char* argv[]) assert (fpv5->dependencies[0][0] == dep ( "libmisc", - brep::optional<dependency_constraint> ( + optional<dependency_constraint> ( dependency_constraint{comparison::lt, version ("1.1")}))); assert (fpv5->dependencies[0][1] == dep ( "libmisc", - brep::optional<dependency_constraint> ( + optional<dependency_constraint> ( dependency_constraint{comparison::gt, version ("2.3.0")}))); assert (fpv5->dependencies[1].size () == 1); @@ -427,7 +424,7 @@ main (int argc, char* argv[]) assert (fpv5->dependencies[1][0] == dep ("libexp", - brep::optional<dependency_constraint> ( + optional<dependency_constraint> ( dependency_constraint{comparison::ge, version ("1.0")}))); assert (fpv5->dependencies[2].size () == 2); @@ -488,14 +485,15 @@ main (int argc, char* argv[]) // assert (cr->location.canonical_name () == "cppget.org/misc"); assert (cr->location.string () == - "http://pkg.cppget.org/external/1/misc"); + "http://pkg.cppget.org/1/misc"); assert (cr->display_name.empty ()); + assert (cr->priority == 0); assert (cr->url && *cr->url == "http://misc.cppget.org/"); assert (!cr->email); assert (!cr->summary); assert (!cr->description); - dir_path crp (cp.directory () / dir_path ("external/1/misc")); + dir_path crp (cp.directory () / dir_path ("1/misc")); assert (cr->local_path == crp.normalize ()); assert (cr->packages_timestamp == @@ -546,14 +544,15 @@ main (int argc, char* argv[]) // assert (tr->location.canonical_name () == "cppget.org/testing"); assert (tr->location.string () == - "http://pkg.cppget.org/external/1/testing"); + "http://pkg.cppget.org/1/testing"); assert (tr->display_name.empty ()); + assert (tr->priority == 0); assert (tr->url && *tr->url == "http://test.cppget.org/hello/"); assert (!tr->email); assert (!tr->summary); assert (!tr->description); - dir_path trp (cp.directory () / dir_path ("external/1/testing")); + dir_path trp (cp.directory () / dir_path ("1/testing")); assert (tr->local_path == trp.normalize ()); assert (tr->packages_timestamp == @@ -582,14 +581,15 @@ main (int argc, char* argv[]) // assert (gr->location.canonical_name () == "cppget.org/staging"); assert (gr->location.string () == - "http://pkg.cppget.org/external/1/staging"); + "http://pkg.cppget.org/1/staging"); assert (gr->display_name.empty ()); + assert (gr->priority == 0); assert (gr->url && *gr->url == "http://stage.cppget.org/"); assert (!gr->email); assert (!gr->summary); assert (!gr->description); - dir_path grp (cp.directory () / dir_path ("external/1/staging")); + dir_path grp (cp.directory () / dir_path ("1/staging")); assert (gr->local_path == grp.normalize ()); assert (gr->packages_timestamp == diff --git a/tests/loader/r.conf b/tests/loader/r.conf index fea477a..8da4b77 100644 --- a/tests/loader/r.conf +++ b/tests/loader/r.conf @@ -1,2 +1,2 @@ -http://pkg.cppget.org/internal/1/stable stable internal/1/stable -http://pkg.cppget.org/internal/1/math math internal/1/math +http://pkg.cppget.org/1/stable stable 1/stable +http://pkg.cppget.org/1/math math 1/math diff --git a/www/repository-details.css b/www/repository-details.css index 1f1a845..29d62f6 100644 --- a/www/repository-details.css +++ b/www/repository-details.css @@ -5,12 +5,13 @@ h1 font-size: 2.074em; line-height: 1.4em; - margin: .6em 0 .6em 0; + margin: 1.6em 0 .4em 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +h1:first-child {margin-top: .6em;} /* Since it is a link to itself, it will always be visited. */ h1 a:visited {color: #006fbf;} |