diff options
-rw-r--r-- | brep/package | 295 | ||||
-rw-r--r-- | brep/package-search.cxx | 17 | ||||
-rw-r--r-- | brep/package-version-details.cxx | 45 | ||||
-rw-r--r-- | brep/package-version-search.cxx | 59 | ||||
-rw-r--r-- | brep/package.cxx | 90 | ||||
-rw-r--r-- | brep/page | 28 | ||||
-rw-r--r-- | brep/page.cxx | 28 | ||||
-rw-r--r-- | loader/loader.cxx | 192 | ||||
-rw-r--r-- | tests/loader/driver.cxx | 244 | ||||
-rw-r--r-- | tests/loader/internal/1/math/packages | 8 |
10 files changed, 496 insertions, 510 deletions
diff --git a/brep/package b/brep/package index 6cd87e9..252c22f 100644 --- a/brep/package +++ b/brep/package @@ -40,10 +40,10 @@ namespace brep #include <bpkg/manifest> -// We have to keep this mapping at the global scope instead of inside -// the brep namespace because it needs to be also effective in the +// We have to keep these mappings at the global scope instead of inside +// the brep namespace because they need to be also effective in the // bpkg namespace from which we "borrow" types (and some of them use -// version). +// version and comparison). // #pragma db map type(bpkg::version) as(brep::_version) \ to(brep::_version{(?).epoch, \ @@ -68,34 +68,9 @@ namespace brep // to TEXT as a comma-separated list. // - // Version comparison operators. - // - template <typename T1, typename T2> - inline auto - operator< (const T1& x, const T2& y) -> decltype (x.epoch < y.epoch) - { - return x.epoch < y.epoch || - (x.epoch == y.epoch && - x.canonical_upstream < y.canonical_upstream) || - (x.epoch == y.epoch && - x.canonical_upstream == y.canonical_upstream && - x.revision < y.revision); - } - - template <typename T> - inline auto - order_by_version_desc (const T& x) -> decltype (x.epoch == 0) - { - return "ORDER BY" - + x.epoch + "DESC," - + x.canonical_upstream + "DESC," - + x.revision + "DESC"; - } - // Forward declarations. // class repository; - class package; class package_version; using strings = std::vector<std::string>; @@ -146,20 +121,8 @@ namespace brep // Database mapping. // - #pragma db member(package) points_to(package) //on_delete(cascade) }; - inline bool - operator< (const package_version_id& x, const package_version_id& y) - { - int r (x.package.compare (y.package)); - - if (r != 0) - return r < 0; - - return x.version < y.version; - } - using priority = bpkg::priority; #pragma db value(priority) definition #pragma db member(priority::value) column("") @@ -216,6 +179,17 @@ namespace brep // tricky. Can stick to just a package name until get some clarity on // "foreign" package resolution. // + // 4. As we get rid of the package class the dependency resolution come to + // finding the best matching package version object. The question is + // if to resolve dependencies on the loading phase or in the WEB interface + // when required. The arguments in favour of doing that during loading + // phase are: + // * WEB interface get offloaded from a possibly expensive queries + // which otherwise have to be executed multiple times for the same + // dependency no matter the result would be the same. + // * No need to complicate persisted object model with repository + // relations otherwise required just for dependency resolution. + // using dependency = bpkg::dependency; #pragma db value(dependency) definition #pragma db member(dependency::condition) column("") @@ -313,77 +287,68 @@ namespace brep repository () = default; }; - #pragma db object pointer(std::shared_ptr) session - class package - { - public: - using url_type = brep::url; - using email_type = brep::email; - - package (std::string name, - std::string summary, - strings tags, - optional<std::string> description, - url_type, - optional<url_type> package_url, - email_type, - optional<email_type> package_email); - - // Manifest data. - // - std::string name; - std::string summary; - strings tags; - optional<std::string> description; - url_type url; - optional<url_type> package_url; - email_type email; - optional<email_type> package_email; - std::vector<odb::lazy_weak_ptr<package_version>> versions; - - // Additional data. - // - - // Database mapping. - // - #pragma db member(name) id - #pragma db member(tags) id_column("package") value_column("tag") - #pragma db member(versions) inverse(id.data.package) value_not_null - - private: - friend class odb::access; - package () = default; - }; - + // @@ While it's very tempting to rename package_version to package wouldn't + // it be confusing having package denoting both specific package version + // and package as a collection of versions. + // #pragma db object pointer(std::shared_ptr) session class package_version { public: using repository_type = brep::repository; - using package_type = brep::package; using version_type = brep::version; using priority_type = brep::priority; using license_alternatives_type = brep::license_alternatives; + using url_type = brep::url; + using email_type = brep::email; using dependencies_type = brep::dependencies; using requirements_type = brep::requirements; - package_version (odb::lazy_shared_ptr<package_type>, + // Create internal package version object. + // + package_version (std::string name, version_type, priority_type, + std::string summary, license_alternatives_type, + strings tags, + optional<std::string> description, std::string changes, + url_type, + optional<url_type> package_url, + email_type, + optional<email_type> package_email, dependencies_type, requirements_type, optional<path> location, std::shared_ptr<repository_type>); + // Create external package version object. + // + // External repository packages can appear on the WEB interface only on + // the package version details page in dependency list in the form of a + // link to the corresponding WEB page. The only package information + // required to compose such a link is the package name, version, and + // repository location. + // + package_version (std::string name, + version_type, + std::shared_ptr<repository_type>); + // Manifest data. // - odb::lazy_shared_ptr<package_type> package; + std::string name; version_type version; priority_type priority; + std::string summary; license_alternatives_type license_alternatives; + strings tags; + optional<std::string> description; std::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; @@ -405,6 +370,8 @@ namespace brep { #pragma db column("") package_version_id data; + + #pragma db column("version_upstream") std::string upstream; }; @@ -414,8 +381,8 @@ namespace brep void _id (_id_type&&, odb::database&); + #pragma db member(name) transient #pragma db member(version) transient - #pragma db member(package) transient #pragma db member(id) virtual(_id_type) before id(data) \ get(_id) set(_id (std::move (?), (!))) column("") @@ -437,6 +404,10 @@ namespace brep set(_set (this.license_alternatives, (?))) \ id_column("") key_column("") value_column("license") + // tags + // + #pragma db member(tags) id_column("") value_column("tag") + // dependencies // using _dependency_key = index_pair<dependency_alternatives>; @@ -481,65 +452,141 @@ namespace brep package_version () = default; }; - #pragma db view object(package_version) \ - query((?) + order_by_version_desc (package_version::id.data.version) + \ - "LIMIT 1") - struct max_package_version - { - using version_type = brep::version; - version_type version; - - void - _id (package_version::_id_type&&); - - // Database mapping. - // - #pragma db member(version) transient - - // Can't specify column expression using aggregate max function for a - // data member of a composite value type. - // - #pragma db member(id) virtual(package_version::_id_type) \ - get() set(_id (std::move (?))) - }; - // Find the latest version of an internal package. // - #pragma db view object(package_version = version) \ - object(package_version = v: \ - version::id.data.package == v::id.data.package && \ - version::id.data.version < v::id.data.version) \ - object(package inner: version::id.data.package == package::name && \ - version::internal_repository.is_not_null () && \ - v::id.data.package.is_null ()) + #pragma db view object(package_version) \ + object(package_version = v: \ + package_version::id.data.package == v::id.data.package && \ + package_version::id.data.version < v::id.data.version) \ + query((package_version::internal_repository.is_not_null () && \ + v::id.data.package.is_null ()) + "AND" + (?)) struct latest_internal_package_version { - using package_type = brep::package; - std::shared_ptr<package_type> package; - std::shared_ptr<package_version> version; + using package_version_type = brep::package_version; + std::shared_ptr<package_version_type> package_version; + + operator const std::shared_ptr<package_version_type>& () const + {return package_version;} + + explicit operator package_version_type& () const + {return *package_version;} }; - #pragma db view object(package) \ - object(package_version: package_version::id.data.package == \ - package::name) \ + #pragma db view object(package_version) \ query(package_version::internal_repository.is_not_null () && (?)) struct internal_package_count { - #pragma db column("count(DISTINCT" + package::name + ")") - std::size_t count; + #pragma db column("count(DISTINCT" + \ + package_version::id.data.package+ ")") + + std::size_t result; + + operator std::size_t () const {return result;} }; #pragma db view object(package_version) struct package_version_count { #pragma db column("count(*)") - std::size_t count; + std::size_t result; + + operator std::size_t () const {return result;} }; + + // Version comparison operators. + // + // They allow comparing objects that have epoch, canonical_upstream, + // and revision data members. + // + template <typename T1, typename T2> + inline auto + operator== (const T1& x, const T2& y) -> decltype (x.epoch == y.epoch) + { + return x.epoch == y.epoch && + x.canonical_upstream == y.canonical_upstream && + x.revision == y.revision; + } + + template <typename T1, typename T2> + inline auto + operator!= (const T1& x, const T2& y) -> decltype (x.epoch != y.epoch) + { + return x.epoch != y.epoch || + x.canonical_upstream != y.canonical_upstream || + x.revision != y.revision; + } + + template <typename T1, typename T2> + inline auto + operator< (const T1& x, const T2& y) -> decltype (x.epoch < y.epoch) + { + return x.epoch < y.epoch || + (x.epoch == y.epoch && x.canonical_upstream < y.canonical_upstream) || + (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && + x.revision < y.revision); + } + + template <typename T1, typename T2> + inline auto + operator<= (const T1& x, const T2& y) -> decltype (x.epoch <= y.epoch) + { + return x.epoch < y.epoch || + (x.epoch == y.epoch && x.canonical_upstream < y.canonical_upstream) || + (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && + x.revision <= y.revision); + } + + template <typename T1, typename T2> + inline auto + operator> (const T1& x, const T2& y) -> decltype (x.epoch > y.epoch) + { + return x.epoch > y.epoch || + (x.epoch == y.epoch && x.canonical_upstream > y.canonical_upstream) || + (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && + x.revision > y.revision); + } + + template <typename T1, typename T2> + inline auto + operator>= (const T1& x, const T2& y) -> decltype (x.epoch >= y.epoch) + { + return x.epoch > y.epoch || + (x.epoch == y.epoch && x.canonical_upstream > y.canonical_upstream) || + (x.epoch == y.epoch && x.canonical_upstream == y.canonical_upstream && + x.revision >= y.revision); + } + + template <typename T> + inline auto + order_by_version_desc (const T& x) -> //decltype ("ORDER BY" + x.epoch) + decltype (x.epoch == 0) + { + return "ORDER BY" + + x.epoch + "DESC," + + x.canonical_upstream + "DESC," + + x.revision + "DESC"; + } + + inline bool + operator< (const package_version_id& x, const package_version_id& y) + { + int r (x.package.compare (y.package)); + + if (r != 0) + return r < 0; + + return x.version < y.version; + } } namespace odb { + using ::brep::operator==; + using ::brep::operator!=; using ::brep::operator<; + using ::brep::operator<=; + using ::brep::operator>; + using ::brep::operator>=; using ::brep::order_by_version_desc; } diff --git a/brep/package-search.cxx b/brep/package-search.cxx index 9b3fb2c..cc15e02 100644 --- a/brep/package-search.cxx +++ b/brep/package-search.cxx @@ -91,7 +91,7 @@ namespace brep // @@ Query will include search criteria if specified. // - size_t pc (db_->query_value<internal_package_count> ().count); + size_t pc (db_->query_value<internal_package_count> ()); s << DIV(ID="packages") << "Packages (" << pc << ")" << ~DIV; @@ -100,20 +100,19 @@ namespace brep using query = query<latest_internal_package_version>; auto r ( - db_->query<latest_internal_package_version> ( - "ORDER BY" + query::package::name + + db_->query<latest_internal_package_version> (query (true) + + "ORDER BY" + query::package_version::id.data.package + "OFFSET" + to_string (pr.page () * rop) + "LIMIT" + to_string (rop))); for (const auto& ip: r) { - const package& p = *ip.package; - const package_version& v = *ip.version; + const package_version& v (ip); s << DIV(CLASS="package") << DIV(CLASS="name") << A - << HREF << "/go/" << mime_url_encode (p.name); + << HREF << "/go/" << mime_url_encode (v.name); // Propagate search criteria to the package version search url. // @@ -121,11 +120,11 @@ namespace brep s << "?" << q; s << ~HREF - << p.name + << v.name << ~A << ~DIV - << DIV(CLASS="summary") << p.summary << ~DIV - << DIV_TAGS (p.tags) + << DIV(CLASS="summary") << v.summary << ~DIV + << DIV_TAGS (v.tags) << DIV_LICENSES (v.license_alternatives) << DIV(CLASS="dependencies") << "Dependencies: " << v.dependencies.size () diff --git a/brep/package-version-details.cxx b/brep/package-version-details.cxx index 0d08a45..0ad86d7 100644 --- a/brep/package-version-details.cxx +++ b/brep/package-version-details.cxx @@ -90,13 +90,16 @@ namespace brep << CSS_STYLE << ident << A_STYLE () << ident << "#name {font-size: xx-large; font-weight: bold;}" << ident - << ".url {margin: 0.3em 0 0;}" << ident - << ".priority, #licenses, #dependencies, #requirements, " + << ".url, .email {font-size: medium;}" << ident + << ".comment {font-size: small;}" << ident + << "#summary {font-size: x-large; margin: 0.2em 0 0;}" << ident + << "#description {margin: 0.5em 0 0;}" << ident + << ".tags {margin: 0.3em 0 0;}" << ident + << "#package, .priority, #licenses, #dependencies, #requirements, " "#locations, #changes {" << ident << " font-size: x-large;" << ident << " margin: 0.5em 0 0;" << ident << "}" << ident - << ".comment {font-size: medium;}" << ident << "ul {margin: 0; padding: 0 0 0 1em;}" << ident << "li {font-size: large; margin: 0.1em 0 0;}" << ident << ".conditional {font-weight: bold;}" << ident @@ -112,7 +115,7 @@ namespace brep bool not_found (false); shared_ptr<package_version> pv; - transaction t (db_->begin ()); //@@ Not committed, other places? + transaction t (db_->begin ()); try { @@ -133,12 +136,20 @@ namespace brep throw invalid_request (404, "Package '" + name + "' not found"); assert (pv->location); - const string url (pv->internal_repository.load ()->location.string () + - "/" + pv->location->string ()); + const string u (pv->internal_repository.load ()->location.string () + + "/" + pv->location->string ()); + + s << DIV(CLASS="url") << A << HREF << u << ~HREF << u << ~A << ~DIV + << DIV(ID="summary") << pv->summary << ~DIV + << DIV_URL (pv->url) + << DIV_EMAIL (pv->email); + + if (pv->description) + s << DIV(ID="description") << *pv->description << ~DIV; const priority& pt (pv->priority); - s << DIV(CLASS="url") << A << HREF << url << ~HREF << url << ~A << ~DIV + s << DIV_TAGS (pv->tags) << DIV_PRIORITY (pt); if (!pt.comment.empty ()) @@ -249,6 +260,22 @@ namespace brep << ~DIV; } + if (pv->package_url || pv->package_email) + { + s << DIV(ID="package") + << "Package:" + << UL; + + if (pv->package_url) + s << LI << DIV_URL (*pv->package_url) << ~LI; + + if (pv->package_email) + s << LI << DIV_EMAIL (*pv->package_email) << ~LI; + + s << ~UL + << ~DIV; + } + const auto& er (pv->external_repositories); if (!er.empty ()) @@ -267,7 +294,9 @@ namespace brep u += ":" + to_string (l.port ()); u += "/go/" + mime_url_encode (p) + "/" + vs; - s << LI << A << HREF << u << ~HREF << u << ~A << ~LI; + s << LI + << DIV(CLASS="url") << A << HREF << u << ~HREF << u << ~A << ~DIV + << ~LI; } s << ~UL diff --git a/brep/package-version-search.cxx b/brep/package-version-search.cxx index 2774a16..7b7ed63 100644 --- a/brep/package-version-search.cxx +++ b/brep/package-version-search.cxx @@ -75,7 +75,8 @@ namespace brep << DIV_PAGER_STYLE () << ident << "#name {font-size: xx-large; font-weight: bold;}" << ident << "#summary {font-size: x-large; margin: 0.2em 0 0;}" << ident - << ".url {margin: 0.3em 0 0;}" << ident + << ".url, .email {font-size: medium;}" << ident + << ".comment {font-size: small;}" << ident << "#description {margin: 0.5em 0 0;}" << ident << ".tags {margin: 0.3em 0 0;}" << ident << "#versions {font-size: x-large; margin: 0.5em 0 0;}" << ident @@ -87,32 +88,32 @@ namespace brep << BODY << DIV(ID="name") << name << ~DIV; - shared_ptr<package> p; size_t rop (options_->results_on_page ()); transaction t (db_->begin ()); - try - { - p = db_->load<package> (name); - } - catch (const object_not_persistent& ) + shared_ptr<package_version> pv; { - throw invalid_request (404, "Package '" + name + "' not found"); + using query = query<latest_internal_package_version>; + + latest_internal_package_version v; + if (!db_->query_one<latest_internal_package_version> ( + query::package_version::id.data.package == name, v)) + { + throw invalid_request (404, "Package '" + name + "' not found"); + } + + pv = v; } - s << DIV(ID="summary") << p->summary << ~DIV - << DIV(CLASS="url") - << A << HREF << p->url << ~HREF << p->url << ~A - << ~DIV - << DIV(CLASS="email") - << A << HREF << "mailto:" << p->email << ~HREF << p->email << ~A - << ~DIV; + s << DIV(ID="summary") << pv->summary << ~DIV + << DIV_URL (pv->url) + << DIV_EMAIL (pv->email); - if (p->description) - s << DIV(ID="description") << *p->description << ~DIV; + if (pv->description) + s << DIV(ID="description") << *pv->description << ~DIV; - s << DIV_TAGS (p->tags); + s << DIV_TAGS (pv->tags); size_t pvc; { @@ -122,23 +123,21 @@ namespace brep // pvc = db_->query_value<package_version_count> ( query::id.data.package == name && - query::internal_repository.is_not_null ()).count; + query::internal_repository.is_not_null ()); } s << DIV(ID="versions") << "Versions (" << pvc << ")" << ~DIV; - if (p->package_url) - s << DIV(CLASS="url") - << A << HREF << *p->package_url << ~HREF << *p->package_url << ~A - << ~DIV; + // @@ Need to find some better place for package url and email or drop them + // from this page totally. + // +/* + if (pv->package_url) + s << DIV_URL (*pv->package_url); - if (p->package_email) - s << DIV(CLASS="email") - << A - << HREF << "mailto:" << *p->package_email << ~HREF - << *p->package_email - << ~A - << ~DIV; + if (pv->package_email) + s << DIV_EMAIL (*pv->package_email); +*/ // @@ Use appropriate view when clarify which package version info to be // displayed and search index structure get implemented. Query will also diff --git a/brep/package.cxx b/brep/package.cxx index 46953f4..3cf4063 100644 --- a/brep/package.cxx +++ b/brep/package.cxx @@ -16,70 +16,54 @@ using namespace odb::core; namespace brep { - // Utility functions - // - static inline bool - alpha (char c) - { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); - } - - static inline bool - digit (char c) - { - return c >= '0' && c <= '9'; - } - - // package - // - package:: - package (string n, - string s, - strings t, - optional<string> d, - url_type u, - optional<url_type> pu, - email_type e, - optional<email_type> pe) - : name (move (n)), - summary (move (s)), - tags (move (t)), - description (move (d)), - url (move (u)), - package_url (move (pu)), - email (move (e)), - package_email (move (pe)) - { - } - // package_version // package_version:: - package_version (lazy_shared_ptr<package_type> pk, + package_version (string nm, version_type vr, priority_type pr, + string sm, license_alternatives_type la, + strings tg, + optional<string> ds, string ch, + url_type ur, + optional<url_type> pu, + email_type em, + optional<email_type> pe, dependencies_type dp, requirements_type rq, optional<path> lc, shared_ptr<repository_type> rp) - : package (move (pk)), + : name (move (nm)), version (move (vr)), priority (move (pr)), + summary (move (sm)), license_alternatives (move (la)), + tags (move (tg)), + description (move (ds)), changes (move (ch)), + url (move (ur)), + package_url (move (pu)), + email (move (em)), + package_email (move (pe)), dependencies (move (dp)), requirements (move (rq)), + internal_repository (move (rp)), location (move (lc)) { - //@@ Can't be sure we are in transaction. Instead, make caller - // pass shared_ptr. - // - if (rp->internal) - internal_repository = move (rp); - else - external_repositories.emplace_back (move (rp)); + assert (internal_repository->internal); + } + + package_version:: + package_version (string nm, + version_type vr, + shared_ptr<repository_type> rp) + : name (move (nm)), + version (move (vr)) + { + assert (!rp->internal); + external_repositories.emplace_back (move (rp)); } package_version::_id_type package_version:: @@ -87,7 +71,7 @@ namespace brep { return _id_type { { - package.object_id (), + name, version.epoch, version.canonical_upstream, version.revision @@ -96,20 +80,10 @@ namespace brep } void package_version:: - _id (_id_type&& v, database& db) - { - const auto& dv (v.data.version); - package = lazy_shared_ptr<package_type> (db, v.data.package); - version = version_type (dv.epoch, move (v.upstream), dv.revision); - assert (version.canonical_upstream == dv.canonical_upstream); - } - - // max_package_version - // - void max_package_version:: - _id (package_version::_id_type&& v) + _id (_id_type&& v, database&) { const auto& dv (v.data.version); + name = move (v.data.package); version = version_type (dv.epoch, move (v.upstream), dv.revision); assert (version.canonical_upstream == dv.canonical_upstream); } @@ -55,6 +55,34 @@ namespace brep operator() (xml::serializer& s) const; }; + // Generates url element. + // + class DIV_URL + { + public: + DIV_URL (const url& u): url_ (u) {} + + void + operator() (xml::serializer& s) const; + + private: + const url& url_; + }; + + // Generates email element. + // + class DIV_EMAIL + { + public: + DIV_EMAIL (const email& e): email_ (e) {} + + void + operator() (xml::serializer& s) const; + + private: + const email& email_; + }; + // Generates package tags element. // class DIV_TAGS diff --git a/brep/page.cxx b/brep/page.cxx index 552be3c..b59cd4b 100644 --- a/brep/page.cxx +++ b/brep/page.cxx @@ -147,6 +147,34 @@ namespace brep s << ~DIV; } + // DIV_URL + // + void DIV_URL:: + operator() (serializer& s) const + { + s << DIV(CLASS="url") + << A << HREF << url_ << ~HREF << url_ << ~A; + + if (!url_.comment.empty ()) + s << DIV(CLASS="comment") << url_.comment << ~DIV; + + s << ~DIV; + } + + // DIV_EMAIL + // + void DIV_EMAIL:: + operator() (serializer& s) const + { + s << DIV(CLASS="email") + << A << HREF << "mailto:" << email_ << ~HREF << email_ << ~A; + + if (!email_.comment.empty ()) + s << DIV(CLASS="comment") << email_.comment << ~DIV; + + s << ~DIV; + } + // DIV_TAGS // void DIV_TAGS:: diff --git a/loader/loader.cxx b/loader/loader.cxx index a901d14..9ddd7c2 100644 --- a/loader/loader.cxx +++ b/loader/loader.cxx @@ -273,140 +273,15 @@ load_packages (const shared_ptr<repository>& rp, database& db) pkm = package_manifests (mp); } - // Let's establish the terminology which will be used in comments appearing - // in the body of this function. - // * Will call a package manifest internal if corresponding 'packages' file - // is located in the internal repository, otherwise call a package manifest - // external. - // * Will call a package version internal if it is described by internal - // package manifest, otherwise call a package version external. - // * Will call a package internal if there is an internal package version, - // otherwise call it external. - // - - // @@ External packages and external package versions are not used by the - // current implementation in any way. The reason to keep them is to see - // if we decide to link dependency information displayed on package - // version details page to best matching package or package version - // details pages. But even if we decide to keep mentioned objects for - // that purpose the ammount of information we store about them can be - // reduces significantly. Seems all we need to keep is in which - // repository they are located. - // - for (auto& pm: pkm) { - // The code below ensures that the package object get updated with a - // package manifest info of the highest version. We should also make - // sure that for the internal package only internal package manifests - // are considered for this purpose. - // - - max_package_version mv; - - // If there are no package_version objects meeting query condition, - // then query_one() will leave mv unchanged, in which case the version - // member remains empty. The empty version value is less than any non-empty - // one, so version comparisons below evaluate to true and the package - // object gets persisted. - // - // Get maximum internal version of the package. - // - using query = query<max_package_version>; - db.query_one<max_package_version> ( - query::id.data.package == pm.name && - query::internal_repository.is_not_null (), - mv); - - bool update (false); - - if (mv.version.empty ()) - { - // The package is external or not persisted yet. - // - - // Get maximum external version of the package. - // - db.query_one<max_package_version> ( - query::id.data.package == pm.name, mv); - - if (rp->internal) - { - // Since internal repositories get loaded first, the package - // can't be external. - // - assert (mv.version.empty ()); - - // Persist not yet persisted internal package. - // - update = true; - } - else - // Update the external package with the external package manifest info - // of a higher version. Version of non-persisted package is empty and - // therefore less then any package manifest version, so the package - // will be persisted. - // - update = mv.version < pm.version; - } - else - { - // The package is internal. - // - - if (rp->internal) - // Update the internal package with the internal package manifest info - // of a higher version. - // - update = mv.version < pm.version; - else - { - // Should not update internal package with an external package - // manifest info. - // - } - } - - if (update) - { - // Create the package object. - // - optional<string> desc; - - // Don't add description for external repository packages. - // - if (rp->internal && pm.description) - { - if (pm.description->file) - { - // @@ Pull description from the file when package manager API - // is ready. - } - else - desc = move (*pm.description); - } - - package p (pm.name, - move (pm.summary), - move (pm.tags), - move (desc), - move (pm.url), - move (pm.package_url), - move (pm.email), - move (pm.package_email)); - - if (mv.version.empty ()) - db.persist (p); - else - db.update (p); - } - shared_ptr<package_version> pv ( db.find<package_version> ( package_version_id { pm.name, - { pm.version.epoch, + { + pm.version.epoch, pm.version.canonical_upstream, pm.version.revision } @@ -414,22 +289,23 @@ load_packages (const shared_ptr<repository>& rp, database& db) if (pv == nullptr) { - // Create package version object. - // - dependencies dep; - requirements req; - optional<path> loc; - string chn; - - // Don't add dependencies, requirements and changes for external - // repository packages. - // if (rp->internal) { - dep = move (pm.dependencies); - req = move (pm.requirements); - loc = move (pm.location); + // Create internal package version object. + // + optional<string> dsc; + if (pm.description) + { + if (pm.description->file) + { + // @@ Pull description from the file when package manager API + // is ready. + } + else + dsc = move (*pm.description); + } + string chn; for (auto& c: pm.changes) { if (c.file) @@ -445,17 +321,32 @@ load_packages (const shared_ptr<repository>& rp, database& db) chn += "\n" + c; } } - } - package_version pv (lazy_shared_ptr<package> (db, pm.name), - move (pm.version), - pm.priority ? move (*pm.priority) : priority (), - move (pm.license_alternatives), - move (chn), - move (dep), - move (req), - move (loc), - rp); + pv = make_shared<package_version>( + move (pm.name), + move (pm.version), + pm.priority ? move (*pm.priority) : priority (), + move (pm.summary), + move (pm.license_alternatives), + move (pm.tags), + move (dsc), + move (chn), + move (pm.url), + move (pm.package_url), + move (pm.email), + move (pm.package_email), + move (pm.dependencies), + move (pm.requirements), + move (pm.location), + rp); + } + else + // Create external package version object. + // + pv = make_shared<package_version>( + move (pm.name), + move (pm.version), + rp); db.persist (pv); } @@ -675,7 +566,6 @@ main (int argc, char* argv[]) // Rebuild repositories persistent state from scratch. // db.erase_query<package_version> (); - db.erase_query<package> (); db.erase_query<repository> (); // On the first pass over the internal repositories we load their diff --git a/tests/loader/driver.cxx b/tests/loader/driver.cxx index 104255a..7a78e39 100644 --- a/tests/loader/driver.cxx +++ b/tests/loader/driver.cxx @@ -42,8 +42,7 @@ check_location (shared_ptr<package_version>& pv) return !pv->location; else return pv->location && *pv->location == - path (pv->package.load ()->name + "-" + pv->version.string () + - ".tar.gz"); + path (pv->name + "-" + pv->version.string () + ".tar.gz"); } int @@ -91,7 +90,6 @@ main (int argc, char* argv[]) transaction t (db.begin ()); assert (db.query<repository> ().size () == 3); - assert (db.query<package> ().size () == 4); assert (db.query<package_version> ().size () == 9); shared_ptr<repository> sr (db.load<repository> ("cppget.org/stable")); @@ -113,19 +111,6 @@ main (int argc, char* argv[]) file_mtime (dir_path (sr->local_path) / path ("repositories"))); assert (sr->internal); - using lv_t = lazy_weak_ptr<package_version>; - auto vc ([](const lv_t& a, const lv_t& b){ - auto v1 (a.load ()); - auto v2 (b.load ()); - - int r (v1->package.object_id ().compare (v2->package.object_id ())); - - if (r) - return r < 0; - - return v1->version < v2->version; - }); - version fv1 ("1.0"); shared_ptr<package_version> fpv1 ( db.load<package_version> ( @@ -166,33 +151,26 @@ main (int argc, char* argv[]) {xv.epoch, xv.canonical_upstream, xv.revision}})); assert (check_location (xpv)); - // Verify libstudxml package. + // Verify libstudxml package version. // - shared_ptr<package> px (db.load<package> ("libstudxml")); - assert (px->name == "libstudxml"); - assert (px->summary == "Modern C++ XML API"); - assert (px->tags == strings ({"c++", "xml", "parser", "serializer", + assert (xpv->name == "libstudxml"); + assert (xpv->version == version ("1.0.0-1")); + assert (xpv->summary == "Modern C++ XML API"); + assert (xpv->tags == strings ({"c++", "xml", "parser", "serializer", "pull", "streaming", "modern"})); - assert (!px->description); - assert (px->url == "http://www.codesynthesis.com/projects/libstudxml/"); - assert (!px->package_url); - assert (px->email == email ("studxml-users@codesynthesis.com", - "Public mailing list, posts by non-members " - "are allowed but moderated.")); - assert (px->package_email && - *px->package_email == email ("boris@codesynthesis.com", - "Direct email to the author.")); - - auto& xpvs (px->versions); - assert (xpvs.size () == 1); - assert (xpvs[0].load () == xpv); + assert (!xpv->description); + assert (xpv->url == "http://www.codesynthesis.com/projects/libstudxml/"); + assert (!xpv->package_url); + assert (xpv->email == + email ("studxml-users@codesynthesis.com", + "Public mailing list, posts by non-members " + "are allowed but moderated.")); + assert (xpv->package_email && + *xpv->package_email == email ("boris@codesynthesis.com", + "Direct email to the author.")); - // Verify libstudxml package version. - // assert (xpv->internal_repository.load () == sr); assert (xpv->external_repositories.empty ()); - assert (xpv->package.load () == px); - assert (xpv->version == version ("1.0.0-1")); assert (xpv->priority == priority::low); assert (xpv->changes.empty ()); @@ -215,37 +193,21 @@ main (int argc, char* argv[]) assert (xpv->requirements.empty ()); - // Verify libfoo package. - // - shared_ptr<package> pf (db.load<package> ("libfoo")); - assert (pf->name == "libfoo"); - assert (pf->summary == "The Foo Math Library"); - assert (pf->tags == strings ({"c++", "foo", "math"})); - assert (*pf->description == - "A modern C++ library with easy to use linear algebra and " - "optimization tools. There are over 100 functions in total with " - "an extensive test suite. The API is similar to MATLAB."); - assert (pf->url == "http://www.example.com/foo/"); - assert (pf->package_url && - *pf->package_url == "http://www.example.com/foo/pack"); - assert (pf->email == "foo-users@example.com"); - assert (pf->package_email && *pf->package_email == "pack@example.com"); - - auto& fpv (pf->versions); - assert (fpv.size () == 6); - sort (fpv.begin (), fpv.end (), vc); - assert (fpv[1].load () == fpv1); - assert (fpv[2].load () == fpv2); - assert (fpv[3].load () == fpv3); - assert (fpv[4].load () == fpv4); - // Verify libfoo package versions. // + assert (fpv1->name == "libfoo"); + assert (fpv1->version == version ("1.0")); + assert (fpv1->summary == "The Foo Library"); + assert (fpv1->tags.empty ()); + assert (!fpv1->description); + assert (fpv1->url == "http://www.example.com/foo/"); + assert (!fpv1->package_url); + assert (fpv1->email == "foo-users@example.com"); + assert (!fpv1->package_email); + assert (fpv1->internal_repository.load () == sr); assert (fpv1->external_repositories.size () == 1); assert (fpv1->external_repositories[0].load () == cr); - assert (fpv1->package.load () == pf); - assert (fpv1->version == version ("1.0")); assert (fpv1->priority == priority::low); assert (fpv1->changes.empty ()); @@ -256,10 +218,18 @@ main (int argc, char* argv[]) assert (fpv1->dependencies.empty ()); assert (fpv1->requirements.empty ()); + assert (fpv2->name == "libfoo"); + assert (fpv2->version == version ("1.2.2")); + assert (fpv2->summary == "The Foo library"); + assert (fpv2->tags == strings ({"c++", "foo"})); + assert (!fpv2->description); + assert (fpv2->url == "http://www.example.com/foo/"); + assert (!fpv2->package_url); + assert (fpv2->email == "foo-users@example.com"); + assert (!fpv2->package_email); + assert (fpv2->internal_repository.load () == sr); assert (fpv2->external_repositories.empty ()); - assert (fpv2->package.load () == pf); - assert (fpv2->version == version ("1.2.2")); assert (fpv2->priority == priority::low); assert (fpv2->changes.empty ()); @@ -285,10 +255,18 @@ main (int argc, char* argv[]) assert (fpv2->requirements.empty ()); + assert (fpv3->name == "libfoo"); + assert (fpv3->version == version ("1.2.3-4")); + assert (fpv3->summary == "The Foo library"); + assert (fpv3->tags == strings ({"c++", "foo"})); + assert (!fpv3->description); + assert (fpv3->url == "http://www.example.com/foo/"); + assert (!fpv3->package_url); + assert (fpv3->email == "foo-users@example.com"); + assert (!fpv3->package_email); + assert (fpv3->internal_repository.load () == sr); assert (fpv3->external_repositories.empty ()); - assert (fpv3->package.load () == pf); - assert (fpv3->version == version ("1.2.3-4")); assert (fpv3->priority == priority::low); assert (fpv3->changes.empty ()); @@ -305,10 +283,18 @@ main (int argc, char* argv[]) brep::optional<dependency_condition> ( dependency_condition{comparison::ge, version ("2.0.0")})})); + assert (fpv4->name == "libfoo"); + assert (fpv4->version == version ("1.2.4")); + assert (fpv4->summary == "The Foo Library"); + assert (fpv4->tags == strings ({"c++", "foo"})); + assert (*fpv4->description == "Very good foo library."); + assert (fpv4->url == "http://www.example.com/foo/"); + assert (!fpv4->package_url); + assert (fpv4->email == "foo-users@example.com"); + assert (!fpv4->package_email); + assert (fpv4->internal_repository.load () == sr); assert (fpv4->external_repositories.empty ()); - assert (fpv4->package.load () == pf); - assert (fpv4->version == version ("1.2.4")); assert (fpv4->priority == priority::low); assert (fpv4->changes == "some changes 1\nsome changes 2"); @@ -356,17 +342,29 @@ main (int argc, char* argv[]) package_version_id { "libfoo", {fv5.epoch, fv5.canonical_upstream, fv5.revision}})); - assert (fpv[5].load () == fpv5); assert (check_location (fpv5)); // Verify libfoo package versions. // + assert (fpv5->name == "libfoo"); + assert (fpv5->version == version ("1.2.4-1")); + assert (fpv5->summary == "The Foo Math Library"); + assert (fpv5->tags == strings ({"c++", "foo", "math"})); + assert (*fpv5->description == + "A modern C++ library with easy to use linear algebra and " + "optimization tools. There are over 100 functions in total with " + "an extensive test suite. The API is similar to MATLAB."); + assert (fpv5->url == "http://www.example.com/foo/"); + assert (fpv5->package_url && + *fpv5->package_url == "http://www.example.com/foo/pack"); + assert (fpv5->email == "foo-users@example.com"); + assert (fpv5->package_email && + *fpv5->package_email == "pack@example.com"); + assert (fpv5->internal_repository.load () == mr); assert (fpv5->external_repositories.size () == 1); assert (fpv5->external_repositories[0].load () == cr); - assert (fpv5->package.load () == pf); - assert (fpv5->version == version ("1.2.4-1")); assert (fpv5->priority == priority::high); assert (fpv5->priority.comment == "Due to critical bug fix."); @@ -433,28 +431,20 @@ main (int argc, char* argv[]) assert (fpvr5[3].comment == "libc++ standard library if using Clang on Mac OS X."); - // Verify libexp package. - // - shared_ptr<package> pe (db.load<package> ("libexp")); - assert (pe->name == "libexp"); - assert (pe->summary == "The exponent"); - assert (pe->tags == strings ({"c++", "exponent"})); - assert (!pe->description); - assert (pe->url == "http://www.exp.com"); - assert (!pe->package_url); - assert (pe->email == email ("users@exp.com")); - assert (!pe->package_email); - - auto& epvs (pe->versions); - assert (epvs.size () == 1); - assert (epvs[0].load () == epv); - // Verify libexp package version. // + assert (epv->name == "libexp"); + assert (epv->version == version ("1+1.2")); + assert (epv->summary == "The exponent"); + assert (epv->tags == strings ({"c++", "exponent"})); + assert (!epv->description); + assert (epv->url == "http://www.exp.com"); + assert (!epv->package_url); + assert (epv->email == email ("users@exp.com")); + assert (!epv->package_email); + assert (epv->internal_repository.load () == mr); assert (epv->external_repositories.empty ()); - assert (epv->package.load () == pe); - assert (epv->version == version ("1+1.2")); assert (epv->priority == priority (priority::low)); assert (epv->changes.empty ()); @@ -501,71 +491,73 @@ main (int argc, char* argv[]) {fv0.epoch, fv0.canonical_upstream, fv0.revision}})); assert (check_location (fpv0)); - // Verify libbar package. - // - shared_ptr<package> pb (db.load<package> ("libbar")); - assert (pb->name == "libbar"); - assert (pb->summary == "The Bar library"); - assert (pb->tags == strings ({"c++", "bar"})); - assert (!pb->description); - assert (pb->url == "http://www.example.com/bar/"); - assert (!pb->package_url); - assert (pb->email == email ("bar-users@example.com")); - assert (!pb->package_email); - - auto& bpvs (pb->versions); - assert (bpvs.size () == 1); - assert (bpvs[0].load () == bpv); - // Verify libbar package version. // + assert (bpv->name == "libbar"); + assert (bpv->version == version ("2.3.5")); + assert (bpv->summary.empty ()); + assert (bpv->tags.empty ()); + assert (!bpv->description); + assert (bpv->url.empty ()); + assert (!bpv->package_url); + assert (bpv->email.empty ()); + assert (!bpv->package_email); + assert (bpv->internal_repository == nullptr); assert (bpv->external_repositories.size () == 1); assert (bpv->external_repositories[0].load () == cr); - assert (bpv->package.load () == pb); - assert (bpv->version == version ("2.3.5")); - assert (bpv->priority == priority (priority::security, - "Very important to install.")); + assert (bpv->priority == priority ()); assert (bpv->changes.empty ()); - assert (bpv->license_alternatives.size () == 1); - assert (bpv->license_alternatives[0].size () == 1); - assert (bpv->license_alternatives[0][0] == "GPLv2"); - + assert (bpv->license_alternatives.empty ()); assert (bpv->dependencies.empty ()); assert (bpv->requirements.empty ()); // Verify libfoo package versions. // + assert (fpv0->name == "libfoo"); + assert (fpv0->version == version ("0.1")); + assert (fpv0->summary.empty ()); + assert (fpv0->tags.empty ()); + assert (!fpv0->description); + assert (fpv0->url.empty ()); + assert (!fpv0->package_url); + assert (fpv0->email.empty ()); + assert (!fpv0->package_email); + assert (fpv0->internal_repository.load () == nullptr); assert (fpv0->external_repositories.size () == 1); assert (fpv0->external_repositories[0].load () == cr); - assert (fpv0->package.load () == pf); - assert (fpv0->version == version ("0.1")); assert (fpv0->priority == priority::low); assert (fpv0->changes.empty ()); - assert (fpv0->license_alternatives.size () == 1); - assert (fpv0->license_alternatives[0].size () == 1); - assert (fpv0->license_alternatives[0][0] == "MIT"); + assert (fpv0->license_alternatives.empty ()); assert (fpv0->dependencies.empty ()); assert (fpv0->requirements.empty ()); - // Update package summary, update package persistent state, rerun loader - // and ensure the model were not rebuilt. + // Change package version summary, update the object persistent + // state, rerun loader and ensure the model were not rebuilt. // - pb->summary = "test"; - db.update (pb); + bpv->summary = "test"; + db.update (bpv); t.commit (); } assert (process (ld_args).wait ()); - transaction t (db.begin ()); - assert (db.load<package> ("libbar")->summary == "test"); + + version bv ("2.3.5"); + shared_ptr<package_version> bpv ( + db.load<package_version> ( + package_version_id { + "libbar", + {bv.epoch, bv.canonical_upstream, bv.revision}})); + + assert (bpv->summary == "test"); + t.commit (); } // Fully qualified to avoid ambiguity with odb exception. diff --git a/tests/loader/internal/1/math/packages b/tests/loader/internal/1/math/packages index ac6c675..3e041a7 100644 --- a/tests/loader/internal/1/math/packages +++ b/tests/loader/internal/1/math/packages @@ -19,10 +19,10 @@ license: LGPLv2, MIT; If using with GNU TLS. license: BSD; If using with OpenSSL. priority: high; Due to critical bug fix. tags: c++, foo, math -url: http://www.example.com/foo/ -email: foo-users@example.com -package-url: http://www.example.com/foo/pack -package-email: pack@example.com +url: http://www.example.com/foo/; Project home page. +email: foo-users@example.com; Public mailing list. +package-url: http://www.example.com/foo/pack; Package details. +package-email: pack@example.com; Current packager. depends: libmisc < 1.1 | libmisc > 2.3.0; Crashes in range [1.1, 2.3.0]. depends: ? libstudxml; Newer - better. requires: linux | windows | macosx; Symbian is coming. |