From 8e866579cb459c5104c532d5e41d562d45236ea5 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 30 Jun 2015 19:20:16 +0200 Subject: Implement loader --- brep/package | 302 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 240 insertions(+), 62 deletions(-) (limited to 'brep/package') diff --git a/brep/package b/brep/package index 62ad8d6..c0c9fc9 100644 --- a/brep/package +++ b/brep/package @@ -2,30 +2,60 @@ // copyright : Copyright (c) 2014-2015 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#ifndef BPKG_PACKAGE -#define BPKG_PACKAGE +#ifndef BREP_PACKAGE +#define BREP_PACKAGE #include #include #include +#include #include // shared_ptr -#include // pair +#include // size_t +#include // move() #include // uint16 #include #include // database #include -#include + +#include +#include +#include +#include + +namespace brep +{ + // Use an image type to map bpkg::version to the database since there + // is no way to modify individual components directly. + // + #pragma db value + struct _version + { + std::uint16_t epoch; + std::string upstream; + std::uint16_t revision; + std::string canonical_upstream; + }; +} #include +// 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 +// bpkg namespace from which we "borrow" types (and some of them use +// version). +// +#pragma db map type(bpkg::version) as(brep::_version) \ + to(brep::_version{(?).epoch (), \ + (?).upstream (), \ + (?).revision (), \ + (?).canonical_upstream ()}) \ + from(bpkg::version ((?).epoch, std::move ((?).upstream), (?).revision)) + namespace brep { // @@ If namespace, then should probably call it 'repo'. // - // @@ Should probably use optional from libbutl instead of odb::nullable - // for consistency. Create butl profile? - // // @@ Might make sense to put some heavy members (e.g., description, // containers) into a separate section. // @@ -36,38 +66,63 @@ namespace brep // Forward declarations. // - struct package; - struct package_version; + class repository; + class package; + class package_version; using strings = std::vector; - using version = bpkg::version; - #pragma db value(version) definition + template + using optional = butl::optional; + + using path = butl::path; + + #pragma db map type(path) as(std::string) \ + to((?).string ()) from(brep::path (?)) + + using dir_path = butl::dir_path; + + #pragma db map type(dir_path) as(std::string) \ + to((?).string ()) from(brep::dir_path (?)) + + using timestamp = butl::timestamp; - using version_type = brep::version; + #pragma db map type(timestamp) as(std::uint64_t) \ + to(std::chrono::system_clock::to_time_t (?)) \ + from(std::chrono::system_clock::from_time_t (?)) + + using version = bpkg::version; + using repository_location = bpkg::repository_location; #pragma db value struct package_version_id { + std::string repository; std::string package; std::uint16_t epoch; - std::string canonical; + std::string canonical_upstream; // Database mapping. // - #pragma db member(package) points_to(package) + #pragma db member(repository) points_to(repository) //on_delete(cascade) + #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)); + int r (x.repository.compare (y.repository)); + + if (r != 0) + return r < 0; + + r = x.package.compare (y.package); if (r != 0) return r < 0; return x.epoch < y.epoch || - x.epoch == y.epoch && x.canonical < y.canonical; + (x.epoch == y.epoch && x.canonical_upstream < y.canonical_upstream); } using priority = bpkg::priority; @@ -76,7 +131,7 @@ namespace brep using url = bpkg::url; #pragma db value(url) definition - #pragma db member(url::value) virtual(std::string) before access(this) \ + #pragma db member(url::value) virtual(std::string) before access(this) \ column("") using email = bpkg::email; @@ -153,31 +208,110 @@ namespace brep std::size_t first; std::size_t second; - index_pair (std::size_t f = 0, std::size_t s = 0): first (f), second (s) {} + index_pair () = default; + index_pair (std::size_t f, std::size_t s): first (f), second (s) {} bool operator< (const index_pair& v) const { - return first < v.first || first == v.first && second < v.second; + return first < v.first || (first == v.first && second < v.second); } }; #pragma db object pointer(std::shared_ptr) session - struct package + class repository { - // Manifest data. + public: + using path_type = brep::path; + using timestamp_type = brep::timestamp; + using package_versions_type = + std::vector>; + using prerequisite_repositories_type = + std::vector>; + + // Create internal repository. + // + repository (repository_location, + std::string display_name, + dir_path local_path); + + // Create external repository. + // + explicit + repository (repository_location l) + : location (std::move (l)), internal (false) {} + + repository_location location; + std::string display_name; + + // Non empty for internal repositories and external ones with a filesystem + // path location. + // + dir_path local_path; + + // Initialized with timestamp_nonexistent by default. + // + timestamp_type timestamp; + + bool internal; + package_versions_type package_versions; + prerequisite_repositories_type prerequisite_repositories; + + // Database mapping. // + #pragma db value + struct _id_type + { + std::string canonical_name; + std::string location; + }; + + _id_type + _id () const; + + void + _id (_id_type&&); + + #pragma db member(location) transient + + #pragma db member(id) virtual(_id_type) before id(canonical_name) \ + get(_id) set(_id (std::move (?))) column("") + + #pragma db member(package_versions) inverse(id.data.repository) + #pragma db member(prerequisite_repositories) id_column("repository") \ + value_column("prerequisite_repository") value_not_null + + private: + friend class odb::access; + 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 description, + url_type, + optional package_url, + email_type, + optional package_email); + + // Manifest data. + // std::string name; std::string summary; strings tags; - std::string description; + optional description; url_type url; - odb::nullable package_url; + optional package_url; email_type email; - odb::nullable package_email; + optional package_email; std::vector> versions; // Additional data. @@ -187,55 +321,71 @@ namespace brep // #pragma db member(name) id #pragma db member(tags) id_column("package") value_column("tag") - #pragma db member(versions) inverse(id.package) + #pragma db member(versions) inverse(id.data.package) + + private: + friend class odb::access; + package () = default; }; #pragma db object pointer(std::shared_ptr) session - struct package_version + class package_version { - // Manifest data. - // + 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 dependencies_type = brep::dependencies; using requirements_type = brep::requirements; + package_version (odb::lazy_shared_ptr, + odb::lazy_shared_ptr, + version_type, + priority_type, + license_alternatives_type, + std::string changes, + dependencies_type, + requirements_type); + + // Manifest data. + // + odb::lazy_shared_ptr repository; + odb::lazy_shared_ptr package; version_type version; - std::shared_ptr package; priority_type priority; license_alternatives_type license_alternatives; std::string changes; dependencies_type dependencies; requirements_type requirements; - // Additional data. - // - std::string repository; // E.g., "stable", "testing". - // Database mapping. // // id // - package_version_id - id () const + #pragma db value + struct _id_type { - return package_version_id - {package->name, version.epoch, version.canonical}; - } + #pragma db column("") + package_version_id data; + std::string upstream; + std::uint16_t revision; + }; + + _id_type + _id () const; void - id (const package_version_id&, odb::database&); + _id (_id_type&&, odb::database&); #pragma db member(version) transient #pragma db member(package) transient - #pragma db member(id) virtual(package_version_id) before id \ - get(id) set(id ((?), (!))) column("") - #pragma db member(upstream) virtual(std::string) after(id) \ - get(version.upstream) set(version.upstream=(?)) - #pragma db member(revision) virtual(std::uint16_t) after(upstream) \ - get(version.revision) set(version.revision = (?)) + #pragma db member(repository) transient + + #pragma db member(id) virtual(_id_type) before id(data) \ + get(_id) set(_id (std::move (?), (!))) column("") // license // @@ -247,11 +397,11 @@ namespace brep #pragma db member(_license_key::second) column("index") #pragma db member(license_alternatives) id_column("") value_column("") - #pragma db member(licenses) \ - virtual(_licenses_type) \ - after(license_alternatives) \ - get(_get (this.license_alternatives)) \ - set(_set (this.license_alternatives, (?))) \ + #pragma db member(licenses) \ + virtual(_licenses_type) \ + after(license_alternatives) \ + get(_get (this.license_alternatives)) \ + set(_set (this.license_alternatives, (?))) \ id_column("") key_column("") value_column("license") // dependencies @@ -265,11 +415,11 @@ namespace brep #pragma db member(_dependency_key::second) column("index") #pragma db member(dependencies) id_column("") value_column("") - #pragma db member(dependency_alternatives) \ - virtual(_dependency_alternatives_type) \ - after(dependencies) \ - get(_get (this.dependencies)) \ - set(_set (this.dependencies, (?))) \ + #pragma db member(dependency_alternatives) \ + virtual(_dependency_alternatives_type) \ + after(dependencies) \ + get(_get (this.dependencies)) \ + set(_set (this.dependencies, (?))) \ id_column("") key_column("") value_column("dep_") // requirements @@ -283,12 +433,40 @@ namespace brep #pragma db member(_requirement_key::second) column("index") #pragma db member(requirements) id_column("") value_column("") - #pragma db member(requirement_alternatives) \ - virtual(_requirement_alternatives_type) \ - after(requirements) \ - get(_get (this.requirements)) \ - set(_set (this.requirements, (?))) \ + #pragma db member(requirement_alternatives) \ + virtual(_requirement_alternatives_type) \ + after(requirements) \ + get(_get (this.requirements)) \ + set(_set (this.requirements, (?))) \ id_column("") key_column("") value_column("id") + + private: + friend class odb::access; + package_version () = default; + }; + + #pragma db view object(package_version) \ + query((?) + "ORDER BY" + package_version::id.data.epoch + "DESC," + \ + package_version::id.data.canonical_upstream + "DESC," + \ + package_version::id.revision + "DESC 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 (?))) }; } @@ -306,7 +484,7 @@ namespace brep #include #include #include // size_t -#include // pair, declval() +#include // declval() #include #include // remove_reference @@ -355,4 +533,4 @@ namespace odb } } -#endif // BPKG_PACKAGE +#endif // BREP_PACKAGE -- cgit v1.1