aboutsummaryrefslogtreecommitdiff
path: root/brep/package-version-details.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-09-22 12:31:42 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-09-24 11:49:02 +0200
commitd1fae6b26e0820dee76e396c540bb1de90038917 (patch)
treee6a145e0901b6eeb118a03c6a616a763de79e42e /brep/package-version-details.cxx
parent675e973bf8e0e24593552f596eb3d81e57e19c94 (diff)
Implement package version detals page
Diffstat (limited to 'brep/package-version-details.cxx')
-rw-r--r--brep/package-version-details.cxx222
1 files changed, 210 insertions, 12 deletions
diff --git a/brep/package-version-details.cxx b/brep/package-version-details.cxx
index 0faecd2..162e783 100644
--- a/brep/package-version-details.cxx
+++ b/brep/package-version-details.cxx
@@ -5,7 +5,7 @@
#include <brep/package-version-details>
#include <string>
-#include <memory> // make_shared()
+#include <memory> // shared_ptr, make_shared()
#include <cassert>
#include <stdexcept> // invalid_argument
@@ -18,6 +18,8 @@
#include <web/module>
#include <web/mime-url-encoding>
+#include <brep/page>
+#include <brep/options>
#include <brep/package>
#include <brep/package-odb>
#include <brep/shared-database>
@@ -48,12 +50,12 @@ namespace brep
MODULE_DIAG;
- path::reverse_iterator i (rq.path ().rbegin ());
- version ver;
+ auto i (rq.path ().rbegin ());
+ version v;
try
{
- ver = version (*i++);
+ v = version (*i++);
}
catch (const invalid_argument& )
{
@@ -61,7 +63,7 @@ namespace brep
}
assert (i != rq.path ().rend ());
- const string& package (*i);
+ const string& p (*i);
params::package_version_details pr;
@@ -77,7 +79,8 @@ namespace brep
}
const char* ident ("\n ");
- const string name (package + "-" + ver.string ());
+ const string& vs (v.string ());
+ const string name (p + " " + vs);
const string title ("Package Version " + name);
serializer s (rs.content (), title);
@@ -85,17 +88,212 @@ namespace brep
<< HEAD
<< TITLE << title << ~TITLE
<< CSS_STYLE << ident
- << "a {text-decoration: none;}" << ident
- << "a:hover {text-decoration: underline;}" << ident
- << ".name {font-size: xx-large; font-weight: bold;}"
+ << A_STYLE () << ident
+ << "#name {font-size: xx-large; font-weight: bold;}" << ident
+ << ".url {margin: 0.3em 0 0;}" << ident
+ << ".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
+ << "pre {font-size: medium; margin: 0.1em 0 0 1em;}"
<< ~CSS_STYLE
<< ~HEAD
- << BODY;
+ << BODY
+ << DIV(ID="name")
+ << A << HREF << "/go/" << mime_url_encode (p) << ~HREF << p << ~A
+ << " " << vs
+ << ~DIV;
- s << DIV(CLASS="name")
- << name
+ bool not_found (false);
+ shared_ptr<package_version> pv;
+
+ transaction t (db_->begin ()); //@@ Not committed, other places?
+
+ try
+ {
+ package_version_id id {
+ p, v.epoch (), v.canonical_upstream (), v.revision ()};
+
+ pv = db_->load<package_version> (id);
+
+ // If the requested package version turned up to be an "external" one
+ // just respond that no "internal" package version is present.
+ //
+ not_found = pv->internal_repository == nullptr;
+ }
+ catch (const object_not_persistent& )
+ {
+ not_found = true;
+ }
+
+ if (not_found)
+ throw invalid_request (404, "Package '" + name + "' not found");
+
+ assert (pv->location);
+ const string url (pv->internal_repository.load ()->location.string () +
+ "/" + pv->location->string ());
+
+ const priority& pt (pv->priority);
+
+ s << DIV(CLASS="url") << A << HREF << url << ~HREF << url << ~A << ~DIV
+ << DIV_PRIORITY (pt);
+
+ if (!pt.comment.empty ())
+ s << DIV(CLASS="comment") << pt.comment << ~DIV;
+
+ const auto& ls (pv->license_alternatives);
+
+ s << DIV(ID="licenses")
+ << "Licenses:"
+ << UL;
+
+ for (const auto& la: ls)
+ {
+ s << LI;
+
+ for (const auto& l: la)
+ {
+ if (&l != &la[0])
+ s << " & ";
+
+ s << l;
+ }
+
+ if (!la.comment.empty ())
+ s << DIV(CLASS="comment") << la.comment << ~DIV;
+
+ s << ~LI;
+ }
+
+ s << ~UL
<< ~DIV;
+ const auto& ds (pv->dependencies);
+
+ if (!ds.empty ())
+ {
+ s << DIV(ID="dependencies")
+ << "Dependencies:"
+ << UL;
+
+ for (const auto& da: ds)
+ {
+ s << LI;
+
+ if (da.conditional)
+ s << SPAN(CLASS="conditional") << "? " << ~SPAN;
+
+ for (const auto& d: da)
+ {
+ if (&d != &da[0])
+ s << " | ";
+
+ // @@ Should it be a link to package version search page on the
+ // corresponding repository site ?
+ //
+ s << d.package;
+
+ if (d.version)
+ {
+ static const strings operations ({"==", "<", ">", "<=", ">="});
+ size_t op (static_cast<size_t> (d.version->operation));
+ assert (op < operations.size ());
+
+ // @@ Should it be a link to the best matching package version
+ // details page on the corresponding repository site ?
+ //
+ s << " " << operations[op] << " " << d.version->value.string ();
+ }
+ }
+
+ if (!da.comment.empty ())
+ s << DIV(CLASS="comment") << da.comment << ~DIV;
+
+ s << ~LI;
+ }
+
+ s << ~UL
+ << ~DIV;
+ }
+
+ const auto& rm (pv->requirements);
+
+ if (!rm.empty ())
+ {
+ s << DIV(ID="requirements")
+ << "Requirements:"
+ << UL;
+
+ for (const auto& ra: rm)
+ {
+ s << LI;
+
+ if (ra.conditional)
+ s << SPAN(CLASS="conditional") << "? " << ~SPAN;
+
+ if (ra.empty ())
+ // If there is no requirement alternatives specified, then
+ // print the comment instead.
+ //
+ s << ra.comment;
+ else
+ {
+ for (const auto& r: ra)
+ {
+ if (&r != &ra[0])
+ s << " | ";
+
+ s << r;
+ }
+
+ if (!ra.comment.empty ())
+ s << DIV(CLASS="comment") << ra.comment << ~DIV;
+ }
+
+ s << ~LI;
+ }
+
+ s << ~UL
+ << ~DIV;
+ }
+
+ const auto& er (pv->external_repositories);
+
+ if (!er.empty ())
+ {
+ s << DIV(ID="locations")
+ << "Alternative Locations:"
+ << UL;
+
+ for (const auto& r: er)
+ {
+ repository_location l (move (r.load ()->location));
+ assert (l.remote ());
+
+ string u ("http://" + l.host ());
+ if (l.port () != 0)
+ u += ":" + to_string (l.port ());
+
+ u += "/go/" + mime_url_encode (p) + "/" + vs;
+ s << LI << A << HREF << u << ~HREF << u << ~A << ~LI;
+ }
+
+ s << ~UL
+ << ~DIV;
+ }
+
+ t.commit ();
+
+ const string& ch (pv->changes);
+
+ if (!ch.empty ())
+ s << DIV(ID="changes") << "Changes:" << PRE << ch << ~PRE << ~DIV;
+
s << ~BODY
<< ~HTML;
}