From d1fae6b26e0820dee76e396c540bb1de90038917 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 22 Sep 2015 12:31:42 +0200 Subject: Implement package version detals page --- brep/package-version-details.cxx | 222 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 210 insertions(+), 12 deletions(-) (limited to 'brep/package-version-details.cxx') 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 #include -#include // make_shared() +#include // shared_ptr, make_shared() #include #include // invalid_argument @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include #include @@ -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 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 (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 (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; } -- cgit v1.1