aboutsummaryrefslogtreecommitdiff
path: root/brep
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-11-05 17:41:16 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-11-11 17:52:19 +0200
commitaacff79e854d6d4eb22540339bc88c3efab353a2 (patch)
tree042ac3a493dcf0ddd72f19c572159a1cea4aa5f4 /brep
parente70163685afe5cae1ebe055a53ce353ae9cbe590 (diff)
Implement package dependency resolution
Diffstat (limited to 'brep')
-rw-r--r--brep/package124
-rw-r--r--brep/package-details.cxx24
-rw-r--r--brep/package-search.cxx17
-rw-r--r--brep/package-version-details.cxx35
-rw-r--r--brep/package.cxx10
-rw-r--r--brep/page.cxx27
6 files changed, 168 insertions, 69 deletions
diff --git a/brep/package b/brep/package
index 719a906..ef73542 100644
--- a/brep/package
+++ b/brep/package
@@ -10,6 +10,7 @@
#include <vector>
#include <chrono>
#include <memory> // shared_ptr
+#include <cassert>
#include <cstddef> // size_t
#include <utility> // move()
#include <cstdint> // uint16
@@ -75,13 +76,11 @@ namespace brep
class package;
using strings = std::vector<std::string>;
-
- template <typename T>
- using optional = butl::optional<T>;
+ using butl::optional;
// path
//
- using path = butl::path;
+ using butl::path;
#pragma db map type(path) as(std::string) \
to((?).string ()) from(brep::path (?))
@@ -93,14 +92,14 @@ namespace brep
to((?) ? (?)->string () : brep::optional_string ()) \
from((?) ? brep::path (*(?)) : brep::optional_path ())
- using dir_path = butl::dir_path;
+ using butl::dir_path;
#pragma db map type(dir_path) as(std::string) \
to((?).string ()) from(brep::dir_path (?))
// timestamp
//
- using timestamp = butl::timestamp;
+ using butl::timestamp;
#pragma db map type(timestamp) as(std::uint64_t) \
to(std::chrono::system_clock::to_time_t (?)) \
@@ -108,7 +107,7 @@ namespace brep
// version
//
- using version = bpkg::version;
+ using bpkg::version;
#pragma db value
struct canonical_version
@@ -116,6 +115,18 @@ namespace brep
std::uint16_t epoch;
std::string canonical_upstream;
std::uint16_t revision;
+
+ bool
+ empty () const noexcept
+ {
+ // No sense to test epoch and revision for 0 as a valid canonical_version
+ // object can not have them different from 0 if canonical_upstream is
+ // empty. The predicate semantics is equal to the one of the
+ // bpkg::version class.
+ //
+ assert (!canonical_upstream.empty () || (epoch == 0 && revision == 0));
+ return canonical_upstream.empty ();
+ }
};
#pragma db value transient
@@ -140,14 +151,14 @@ namespace brep
// priority
//
- using priority = bpkg::priority;
+ using bpkg::priority;
#pragma db value(priority) definition
#pragma db member(priority::value) column("")
// url
//
- using url = bpkg::url;
+ using bpkg::url;
#pragma db value(url) definition
#pragma db member(url::value) virtual(std::string) before access(this) \
@@ -155,7 +166,7 @@ namespace brep
// email
//
- using email = bpkg::email;
+ using bpkg::email;
#pragma db value(email) definition
#pragma db member(email::value) virtual(std::string) before access(this) \
@@ -163,17 +174,33 @@ namespace brep
// licenses
//
- using licenses = bpkg::licenses;
+ using bpkg::licenses;
using license_alternatives = std::vector<licenses>;
#pragma db value(licenses) definition
// dependencies
//
- using comparison = bpkg::comparison;
- using dependency_constraint = bpkg::dependency_constraint;
+ using bpkg::comparison;
+ using bpkg::dependency_constraint;
#pragma db value(dependency_constraint) definition
+ #pragma db member(dependency_constraint::operation) column("")
+ #pragma db member(dependency_constraint::version) column("")
+
+ #pragma db value
+ struct package_id
+ {
+ std::string name;
+ canonical_version version;
+
+ package_id () = default;
+ package_id (std::string n, const brep::version& v)
+ : name (std::move (n)),
+ version {v.epoch, v.canonical_upstream, v.revision}
+ {
+ }
+ };
// Notes:
//
@@ -215,24 +242,51 @@ namespace brep
// * No need to complicate persisted object model with repository
// relations otherwise required just for dependency resolution.
//
- using dependency = bpkg::dependency;
- using dependency_alternatives = bpkg::dependency_alternatives;
- using dependencies = std::vector<dependency_alternatives>;
- #pragma db value(dependency) definition
- #pragma db member(dependency::constraint) column("")
- #pragma db value(dependency_alternatives) definition
+ #pragma db value
+ struct dependency
+ {
+ using package_type = brep::package;
+
+ odb::lazy_shared_ptr<package_type> package;
+ optional<dependency_constraint> constraint;
+
+ // Prerequisite package name.
+ //
+ std::string
+ name () const;
+
+ // Database mapping.
+ //
+ #pragma db member(package) column("") not_null
+ };
+
+ #pragma db value
+ class dependency_alternatives: public std::vector<dependency>
+ {
+ public:
+ bool conditional;
+ std::string comment;
+
+ dependency_alternatives () = default;
+
+ explicit
+ dependency_alternatives (bool d, std::string c)
+ : conditional (d), comment (std::move (c)) {}
+ };
+
+ using dependencies = std::vector<dependency_alternatives>;
// requirements
//
- using requirement_alternatives = bpkg::requirement_alternatives;
+ using bpkg::requirement_alternatives;
using requirements = std::vector<requirement_alternatives>;
#pragma db value(requirement_alternatives) definition
// repository_location
//
- using repository_location = bpkg::repository_location;
+ using bpkg::repository_location;
#pragma db map type(repository_location) as(std::string) \
to((?).string ()) from(brep::repository_location (?))
@@ -270,6 +324,8 @@ namespace brep
timestamp repositories_timestamp;
bool internal;
+ std::vector<odb::lazy_weak_ptr<repository>> complements;
+ std::vector<odb::lazy_weak_ptr<repository>> prerequisites;
// Database mapping.
//
@@ -279,25 +335,17 @@ namespace brep
set(this.location = std::move (?); \
assert (this.name == this.location.canonical_name ()))
+ #pragma db member(complements) id_column("repository") \
+ value_column("complement") value_not_null
+
+ #pragma db member(prerequisites) id_column("repository") \
+ value_column("prerequisite") value_not_null
+
private:
friend class odb::access;
repository () = default;
};
- #pragma db value
- struct package_id
- {
- std::string name;
- canonical_version version;
-
- package_id () = default;
- package_id (std::string n, const brep::version& v)
- : name (std::move (n)),
- version {v.epoch, v.canonical_upstream, v.revision}
- {
- }
- };
-
// The 'to' expression calls the PostgreSQL to_tsvector(weighted_text)
// function overload (package-extra.sql). Since we are only interested
// in "write-only" members of this type, make the 'from' expression
@@ -382,7 +430,7 @@ namespace brep
//
optional<path> location;
- std::vector<odb::lazy_shared_ptr<repository_type>> external_repositories;
+ std::vector<odb::lazy_shared_ptr<repository_type>> other_repositories;
// Database mapping.
//
@@ -446,9 +494,9 @@ namespace brep
set(odb::nested_set (this.requirements, move (?))) \
id_column("") key_column("") value_column("id")
- // external_repositories
+ // other_repositories
//
- #pragma db member(external_repositories) \
+ #pragma db member(other_repositories) \
id_column("") value_column("repository") value_not_null
// search_index
diff --git a/brep/package-details.cxx b/brep/package-details.cxx
index f814ef8..0424d5b 100644
--- a/brep/package-details.cxx
+++ b/brep/package-details.cxx
@@ -10,6 +10,7 @@
#include <xml/serializer>
+#include <odb/session.hxx>
#include <odb/database.hxx>
#include <odb/transaction.hxx>
@@ -119,6 +120,7 @@ namespace brep
<< A(HREF=url (!f, sq, pg)) << (f ? "[brief]" : "[full]") << ~A
<< ~DIV;
+ session sn;
transaction t (db_->begin ());
shared_ptr<package> p;
@@ -172,13 +174,12 @@ namespace brep
"OFFSET" + to_string (pg * rp) +
"LIMIT" + to_string (rp)));
- s << FORM_SEARCH (sq.c_str ())
- << DIV_COUNTER (pc, "Version", "Versions")
-
- // Enclose the subsequent tables to be able to use nth-child CSS selector.
- //
- << DIV;
+ s << FORM_SEARCH (sq)
+ << DIV_COUNTER (pc, "Version", "Versions");
+ // Enclose the subsequent tables to be able to use nth-child CSS selector.
+ //
+ s << DIV;
for (const auto& pr: r)
{
shared_ptr<package> p (db_->load<package> (pr.id));
@@ -187,7 +188,7 @@ namespace brep
<< TBODY
<< TR_VERSION (name, p->version.string ())
- // @@ Shouldn't we skip low priority row ?
+ // @@ Shouldn't we skip low priority row ? Don't think so, why?
//
<< TR_PRIORITY (p->priority);
@@ -200,24 +201,27 @@ namespace brep
assert (p->internal_repository != nullptr);
// @@ Shouldn't we make package location to be a link to the proper
- // place of the About page, describing corresponding repository ?
+ // place of the About page, describing corresponding repository?
+ // Yes, I think that's sounds reasonable, once we have about.
//
// @@ In most cases package location will be the same for all versions
// of the same package. Shouldn't we put package location to the
// package summary part and display it here only if it differes
// from the one in the summary ?
//
+ // Hm, I am not so sure about this. Consider: stable/testing/unstable.
+ //
s << TR_LOCATION (p->internal_repository.object_id ())
<< TR_DEPENDS (p->dependencies)
<< TR_REQUIRES (p->requirements)
<< ~TBODY
<< ~TABLE;
}
+ s << ~DIV;
t.commit ();
- s << ~DIV
- << DIV_PAGER (pg, pc, rp, options_->pages_in_pager (), url (f, sq))
+ s << DIV_PAGER (pg, pc, rp, options_->pages_in_pager (), url (f, sq))
<< ~DIV
<< ~BODY
<< ~HTML;
diff --git a/brep/package-search.cxx b/brep/package-search.cxx
index 64e43f1..47f53e9 100644
--- a/brep/package-search.cxx
+++ b/brep/package-search.cxx
@@ -10,6 +10,7 @@
#include <xml/serializer>
+#include <odb/session.hxx>
#include <odb/database.hxx>
#include <odb/transaction.hxx>
@@ -92,6 +93,7 @@ namespace brep
<< DIV_HEADER ()
<< DIV(ID="content");
+ session sn;
transaction t (db_->begin ());
auto pc (
@@ -105,13 +107,12 @@ namespace brep
"OFFSET" + to_string (pg * rp) +
"LIMIT" + to_string (rp)));
- s << FORM_SEARCH (sq.c_str ())
- << DIV_COUNTER (pc, "Package", "Packages")
-
- // Enclose the subsequent tables to be able to use nth-child CSS selector.
- //
- << DIV;
+ s << FORM_SEARCH (sq)
+ << DIV_COUNTER (pc, "Package", "Packages");
+ // Enclose the subsequent tables to be able to use nth-child CSS selector.
+ //
+ s << DIV;
for (const auto& pr: r)
{
shared_ptr<package> p (db_->load<package> (pr.id));
@@ -127,13 +128,13 @@ namespace brep
<< ~TBODY
<< ~TABLE;
}
+ s << ~DIV;
t.commit ();
string url (qp.empty () ? "/" : ("/?" + qp));
- s << ~DIV
- << DIV_PAGER (pg, pc, rp, options_->pages_in_pager (), url)
+ s << DIV_PAGER (pg, pc, rp, options_->pages_in_pager (), url)
<< ~DIV
<< ~BODY
<< ~HTML;
diff --git a/brep/package-version-details.cxx b/brep/package-version-details.cxx
index 71559b9..a4fa95a 100644
--- a/brep/package-version-details.cxx
+++ b/brep/package-version-details.cxx
@@ -11,6 +11,7 @@
#include <xml/serializer>
+#include <odb/session.hxx>
#include <odb/database.hxx>
#include <odb/transaction.hxx>
@@ -63,7 +64,7 @@ namespace brep
}
assert (i != rq.path ().rend ());
- const string& n (*i);
+ const string& n (*i); // Package name.
params::package_version_details pr;
@@ -120,6 +121,7 @@ namespace brep
bool not_found (false);
shared_ptr<package> p;
+ session sn;
transaction t (db_->begin ());
try
@@ -153,8 +155,6 @@ namespace brep
const string du (p->internal_repository.load ()->location.string () +
"/" + p->location->string ());
- t.commit ();
-
s << TABLE(CLASS="proplist", ID="version")
<< TBODY
@@ -209,7 +209,32 @@ namespace brep
if (&d != &da[0])
s << " | ";
- s << d; // @@ Should it be a link ?
+ shared_ptr<package> p (d.package.load ());
+ string en (mime_url_encode (p->id.name));
+
+ if (p->internal_repository != nullptr)
+ s << A << HREF << "/go/" << en << ~HREF << p->id.name << ~A;
+ else
+ // @@ Refer to package repository URL when supported in repository
+ // manifest.
+ //
+ s << p->id.name;
+
+ if (d.constraint)
+ {
+ s << ' ';
+
+ if (p->internal_repository != nullptr)
+ s << A
+ << HREF << "/go/" << en << "/" << p->version.string () << ~HREF
+ << *d.constraint
+ << ~A;
+ else
+ // @@ Refer to package repository URL when supported in
+ // repository manifest.
+ //
+ s << *d.constraint;
+ }
}
s << ~SPAN
@@ -222,6 +247,8 @@ namespace brep
<< ~TABLE;
}
+ t.commit ();
+
const auto& rt (p->requirements);
if (!rt.empty ())
diff --git a/brep/package.cxx b/brep/package.cxx
index 9b7d24a..3c65ed8 100644
--- a/brep/package.cxx
+++ b/brep/package.cxx
@@ -16,6 +16,14 @@ using namespace odb::core;
namespace brep
{
+ // dependency
+ //
+ string dependency::
+ name () const
+ {
+ return package.object_id ().name;
+ }
+
// package
//
package::
@@ -63,7 +71,7 @@ namespace brep
version (move (vr))
{
assert (!rp->internal);
- external_repositories.emplace_back (move (rp));
+ other_repositories.emplace_back (move (rp));
}
weighted_text package::
diff --git a/brep/page.cxx b/brep/page.cxx
index a23ce17..deee055 100644
--- a/brep/page.cxx
+++ b/brep/page.cxx
@@ -6,6 +6,7 @@
#include <set>
#include <string>
+#include <memory> // shared_ptr
#include <cassert>
#include <utility> // move()
#include <algorithm> // min()
@@ -16,6 +17,7 @@
#include <web/mime-url-encoding>
#include <brep/package>
+#include <brep/package-odb>
using namespace std;
using namespace xml;
@@ -51,7 +53,7 @@ namespace brep
void FORM_SEARCH::
operator() (serializer& s) const
{
- // The 'action' attribute is optional in HTML5. While the standard don't
+ // The 'action' attribute is optional in HTML5. While the standard doesn't
// specify browser behavior explicitly for the case the attribute is
// ommited, the only reasonable behavior is to default it to the current
// document URL.
@@ -260,26 +262,35 @@ namespace brep
//
set<string> ds;
for (const auto& da: d)
- ds.emplace (da.name);
+ ds.emplace (da.name ());
bool m (ds.size () > 1);
if (m)
s << "(";
- bool first (true);
+ bool f (true); // First dependency alternative.
for (const auto& da: d)
{
- if (ds.find (da.name) != ds.end ())
+ string n (da.name ());
+ if (ds.find (n) != ds.end ())
{
- ds.erase (da.name);
+ ds.erase (n);
- if (first)
- first = false;
+ if (f)
+ f = false;
else
s << " | ";
- s << da.name; // @@ Make it a link.
+ shared_ptr<package> p (da.package.load ());
+
+ if (p->internal_repository != nullptr)
+ s << A << HREF << "/go/" << mime_url_encode (n) << ~HREF << n << ~A;
+ else
+ // @@ Refer to package repository URL when supported in repository
+ // manifest.
+ //
+ s << n;
}
}