aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--brep/package295
-rw-r--r--brep/package-search.cxx17
-rw-r--r--brep/package-version-details.cxx45
-rw-r--r--brep/package-version-search.cxx59
-rw-r--r--brep/package.cxx90
-rw-r--r--brep/page28
-rw-r--r--brep/page.cxx28
-rw-r--r--loader/loader.cxx192
-rw-r--r--tests/loader/driver.cxx244
-rw-r--r--tests/loader/internal/1/math/packages8
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);
}
diff --git a/brep/page b/brep/page
index c7febd8..d14bb41 100644
--- a/brep/page
+++ b/brep/page
@@ -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.