aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-09-08 17:46:57 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-09-08 21:00:05 +0300
commitd63e34a7e8612dc69ae25f3d3903ba04cc808bf7 (patch)
treea70540d6d7ec2b9ce72eae52d83ff35bcf150c1c
parent70c1cdfd8f34472761fe5ec97f0713990c1b4f5b (diff)
Add support for root global and tenant views
-rw-r--r--mod/mod-package-details.cxx2
-rw-r--r--mod/mod-packages.cxx (renamed from mod/mod-package-search.cxx)44
-rw-r--r--mod/mod-packages.hxx (renamed from mod/mod-package-search.hxx)18
-rw-r--r--mod/mod-repository-root.cxx112
-rw-r--r--mod/mod-repository-root.hxx4
-rw-r--r--mod/options.cli25
-rw-r--r--mod/page.cxx25
-rw-r--r--mod/page.hxx13
8 files changed, 157 insertions, 86 deletions
diff --git a/mod/mod-package-details.cxx b/mod/mod-package-details.cxx
index 6ec0b0f..a36d4c0 100644
--- a/mod/mod-package-details.cxx
+++ b/mod/mod-package-details.cxx
@@ -215,7 +215,7 @@ handle (request& rq, response& rs)
package_db_->query_value<package_count> (
search_params<package_count> (squery, tenant, name)));
- s << FORM_SEARCH (squery)
+ s << FORM_SEARCH (squery, "q")
<< DIV_COUNTER (pkg_count, "Version", "Versions");
// Enclose the subsequent tables to be able to use nth-child CSS selector.
diff --git a/mod/mod-package-search.cxx b/mod/mod-packages.cxx
index 347abf1..1157378 100644
--- a/mod/mod-package-search.cxx
+++ b/mod/mod-packages.cxx
@@ -1,8 +1,8 @@
-// file : mod/mod-package-search.cxx -*- C++ -*-
+// file : mod/mod-packages.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
-#include <mod/mod-package-search.hxx>
+#include <mod/mod-packages.hxx>
#include <libstudxml/serializer.hxx>
@@ -28,19 +28,19 @@ using namespace brep::cli;
// need to deep copy nullptr's), it is a good idea to keep the placeholder
// ready for less trivial cases.
//
-brep::package_search::
-package_search (const package_search& r)
+brep::packages::
+packages (const packages& r)
: database_module (r),
options_ (r.initialized_ ? r.options_ : nullptr)
{
}
-void brep::package_search::
+void brep::packages::
init (scanner& s)
{
HANDLER_DIAG;
- options_ = make_shared<options::package_search> (
+ options_ = make_shared<options::packages> (
s, unknown_mode::fail, unknown_mode::fail);
database_module::init (*options_, options_->package_db_retry ());
@@ -79,7 +79,7 @@ search_param (const brep::string& q, const brep::string& t)
")";
}
-bool brep::package_search::
+bool brep::packages::
handle (request& rq, response& rs)
{
using namespace web::xhtml;
@@ -90,13 +90,12 @@ handle (request& rq, response& rs)
const dir_path& root (options_->root ());
const string& title (options_->search_title ());
- params::package_search params;
+ params::packages params;
try
{
name_value_scanner s (rq.parameters (8 * 1024));
- params = params::package_search (
- s, unknown_mode::fail, unknown_mode::fail);
+ params = params::packages (s, unknown_mode::fail, unknown_mode::fail);
}
catch (const cli::exception& e)
{
@@ -104,10 +103,8 @@ handle (request& rq, response& rs)
}
size_t page (params.page ());
- const string& squery (params.query ());
- string squery_param (squery.empty ()
- ? ""
- : "?q=" + web::mime_url_encode (squery));
+ const string& squery (params.q ());
+ string equery (web::mime_url_encode (squery));
xml::serializer s (rs.content (), title);
@@ -145,7 +142,7 @@ handle (request& rq, response& rs)
package_db_->query_value<latest_package_count> (
search_param<latest_package_count> (squery, tenant)));
- s << FORM_SEARCH (squery)
+ s << FORM_SEARCH (squery, "packages")
<< DIV_COUNTER (pkg_count, "Package", "Packages");
// Enclose the subsequent tables to be able to use nth-child CSS selector.
@@ -164,7 +161,7 @@ handle (request& rq, response& rs)
s << TABLE(CLASS="proplist package")
<< TBODY
- << TR_NAME (p->name, squery_param, root, tenant)
+ << TR_NAME (p->name, equery, root, tenant)
<< TR_SUMMARY (p->summary)
<< TR_LICENSE (p->license_alternatives)
<< TR_TAGS (p->project, p->tags, root, tenant)
@@ -177,8 +174,19 @@ handle (request& rq, response& rs)
t.commit ();
- s << DIV_PAGER (page, pkg_count, res_page, options_->search_pages (),
- tenant_dir (root, tenant).string () + squery_param)
+ string url (tenant_dir (root, tenant).string () + "?packages");
+
+ if (!equery.empty ())
+ {
+ url += '=';
+ url += equery;
+ }
+
+ s << DIV_PAGER (page,
+ pkg_count,
+ res_page,
+ options_->search_pages (),
+ url)
<< ~DIV
<< ~BODY
<< ~HTML;
diff --git a/mod/mod-package-search.hxx b/mod/mod-packages.hxx
index 406476e..dd11136 100644
--- a/mod/mod-package-search.hxx
+++ b/mod/mod-packages.hxx
@@ -1,9 +1,9 @@
-// file : mod/mod-package-search.hxx -*- C++ -*-
+// file : mod/mod-packages.hxx -*- C++ -*-
// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
-#ifndef MOD_MOD_PACKAGE_SEARCH_HXX
-#define MOD_MOD_PACKAGE_SEARCH_HXX
+#ifndef MOD_MOD_PACKAGES_HXX
+#define MOD_MOD_PACKAGES_HXX
#include <libbrep/types.hxx>
#include <libbrep/utility.hxx>
@@ -13,30 +13,30 @@
namespace brep
{
- class package_search: public database_module
+ class packages: public database_module
{
public:
- package_search () = default;
+ packages () = default;
// Create a shallow copy (handling instance) if initialized and a deep
// copy (context exemplar) otherwise.
//
explicit
- package_search (const package_search&);
+ packages (const packages&);
virtual bool
handle (request&, response&);
virtual const cli::options&
- cli_options () const {return options::package_search::description ();}
+ cli_options () const {return options::packages::description ();}
private:
virtual void
init (cli::scanner&);
private:
- shared_ptr<options::package_search> options_;
+ shared_ptr<options::packages> options_;
};
}
-#endif // MOD_MOD_PACKAGE_SEARCH_HXX
+#endif // MOD_MOD_PACKAGES_HXX
diff --git a/mod/mod-repository-root.cxx b/mod/mod-repository-root.cxx
index b8777fd..b825ea1 100644
--- a/mod/mod-repository-root.cxx
+++ b/mod/mod-repository-root.cxx
@@ -7,6 +7,7 @@
#include <time.h> // tzset()
#include <sstream>
+#include <algorithm> // find()
#include <web/module.hxx>
@@ -16,11 +17,11 @@
#include <mod/mod-ci.hxx>
#include <mod/mod-submit.hxx>
#include <mod/mod-builds.hxx>
+#include <mod/mod-packages.hxx>
#include <mod/mod-build-log.hxx>
#include <mod/mod-build-task.hxx>
#include <mod/mod-build-force.hxx>
#include <mod/mod-build-result.hxx>
-#include <mod/mod-package-search.hxx>
#include <mod/mod-package-details.hxx>
#include <mod/mod-repository-details.hxx>
#include <mod/mod-package-version-details.hxx>
@@ -105,7 +106,7 @@ namespace brep
//
repository_root::
repository_root ()
- : package_search_ (make_shared<package_search> ()),
+ : packages_ (make_shared<packages> ()),
package_details_ (make_shared<package_details> ()),
package_version_details_ (make_shared<package_version_details> ()),
repository_details_ (make_shared<repository_details> ()),
@@ -126,10 +127,10 @@ namespace brep
// Deep/shallow-copy sub-handlers depending on whether this is an
// exemplar/handler.
//
- package_search_ (
+ packages_ (
r.initialized_
- ? r.package_search_
- : make_shared<package_search> (*r.package_search_)),
+ ? r.packages_
+ : make_shared<packages> (*r.packages_)),
package_details_ (
r.initialized_
? r.package_details_
@@ -185,7 +186,7 @@ namespace brep
options ()
{
option_descriptions r (handler::options ());
- append (r, package_search_->options ());
+ append (r, packages_->options ());
append (r, package_details_->options ());
append (r, package_version_details_->options ());
append (r, repository_details_->options ());
@@ -229,7 +230,7 @@ namespace brep
// Initialize sub-handlers.
//
- sub_init (*package_search_, "package_search");
+ sub_init (*packages_, "packages");
sub_init (*package_details_, "package_details");
sub_init (*package_version_details_, "package_version_details");
sub_init (*repository_details_, "repository_details");
@@ -255,6 +256,19 @@ namespace brep
options_ = make_shared<options::repository_root> (
s, unknown_mode::fail, unknown_mode::fail);
+ // Verify that the root default views are properly configured.
+ //
+ auto verify = [&fail] (const string& v, const char* what)
+ {
+ cstrings vs ({"packages", "builds", "about", "submit", "ci"});
+
+ if (find (vs.begin (), vs.end (), v) == vs.end ())
+ fail << what << " value '" << v << "' is invalid";
+ };
+
+ verify (options_->root_global_view (), "root-global-view");
+ verify (options_->root_tenant_view (), "root-tenant-view");
+
if (options_->root ().empty ())
options_->root (dir_path ("/"));
@@ -340,73 +354,97 @@ namespace brep
//
if (lpath.empty ())
{
- // Dispatch request handling to the repository_details or the one of
- // build_* handlers depending on the function name passed as a first HTTP
- // request parameter (example: cppget.org/?about). Dispatch to the
- // package_search handler if the function name is unavailable (no
- // parameters) or is not recognized.
+ // Dispatch request handling to one of the sub-handlers depending on the
+ // function name passed as a first HTTP request parameter (example:
+ // cppget.org/?about). If it doesn't denote a handler or there are no
+ // parameters, then dispatch to the default handler.
//
const name_values& params (rq.parameters (0 /* limit */,
true /* url_only */));
- if (!params.empty ())
+
+ auto dispatch = [&handle, this] (const string& func,
+ bool param) -> optional<bool>
{
- const string& fn (params.front ().name);
+ // When adding a new handler don't forget to check if need to add it
+ // to the default view list in the init() function.
+ //
+ if (func == "build-task")
+ {
+ if (handler_ == nullptr)
+ handler_.reset (new build_task (*build_task_));
- if (fn == "about")
+ return handle ("build_task", param);
+ }
+ else if (func == "build-result")
{
if (handler_ == nullptr)
- handler_.reset (new repository_details (*repository_details_));
+ handler_.reset (new build_result (*build_result_));
- return handle ("repository_details", true);
+ return handle ("build_result", param);
}
- else if (fn == "build-task")
+ else if (func == "build-force")
{
if (handler_ == nullptr)
- handler_.reset (new build_task (*build_task_));
+ handler_.reset (new build_force (*build_force_));
- return handle ("build_task", true);
+ return handle ("build_force", param);
}
- else if (fn == "build-result")
+ else if (func == "builds")
{
if (handler_ == nullptr)
- handler_.reset (new build_result (*build_result_));
+ handler_.reset (new builds (*builds_));
- return handle ("build_result", true);
+ return handle ("builds", param);
}
- else if (fn == "build-force")
+ else if (func == "packages")
{
if (handler_ == nullptr)
- handler_.reset (new build_force (*build_force_));
+ handler_.reset (new packages (*packages_));
- return handle ("build_force", true);
+ return handle ("packages", param);
}
- else if (fn == "builds")
+ else if (func == "about")
{
if (handler_ == nullptr)
- handler_.reset (new builds (*builds_));
+ handler_.reset (new repository_details (*repository_details_));
- return handle ("builds", true);
+ return handle ("repository_details", param);
}
- else if (fn == "submit")
+ else if (func == "submit")
{
if (handler_ == nullptr)
handler_.reset (new submit (*submit_));
- return handle ("submit", true);
+ return handle ("submit", param);
}
- else if (fn == "ci")
+ else if (func == "ci")
{
if (handler_ == nullptr)
handler_.reset (new ci (*ci_));
- return handle ("ci", true);
+ return handle ("ci", param);
}
- }
+ else
+ return nullopt;
+ };
+
+ optional<bool> r;
+
+ if (!params.empty () &&
+ (r = dispatch (params.front ().name, true /* param */)))
+ return *r;
- if (handler_ == nullptr)
- handler_.reset (new package_search (*package_search_));
+ const string& view (!tenant.empty ()
+ ? options_->root_tenant_view ()
+ : options_->root_global_view ());
+
+ r = dispatch (view, false /* param */);
+
+ // The default views are verified in the init() function.
+ //
+ assert (r);
- return handle ("package_search");
+ return *r;
}
else
{
diff --git a/mod/mod-repository-root.hxx b/mod/mod-repository-root.hxx
index 9a71849..a46f43f 100644
--- a/mod/mod-repository-root.hxx
+++ b/mod/mod-repository-root.hxx
@@ -13,7 +13,7 @@
namespace brep
{
- class package_search;
+ class packages;
class package_details;
class package_version_details;
class repository_details;
@@ -58,7 +58,7 @@ namespace brep
version ();
private:
- shared_ptr<package_search> package_search_;
+ shared_ptr<packages> packages_;
shared_ptr<package_details> package_details_;
shared_ptr<package_version_details> package_version_details_;
shared_ptr<repository_details> repository_details_;
diff --git a/mod/options.cli b/mod/options.cli
index 619df66..12f577c 100644
--- a/mod/options.cli
+++ b/mod/options.cli
@@ -311,7 +311,8 @@ namespace brep
// Handler options.
//
- class package_search: search, package_db, page, handler
+
+ class packages: search, package_db, page, handler
{
string search-title = "Packages"
{
@@ -532,6 +533,21 @@ namespace brep
class repository_root: handler
{
+ string root-global-view = "packages"
+ {
+ "<service>",
+ "The default view to display for the global repository root. The
+ <service> argument is one of the supported services (\c{packages},
+ \c{builds}, \c{submit}, \c{ci}, etc)."
+ }
+
+ string root-tenant-view = "packages"
+ {
+ "<service>"
+ "The default view to display for the tenant repository root. The
+ <service> argument is one of the supported services (\c{packages},
+ \c{builds}, \c{submit}, \c{ci}, etc)."
+ }
};
}
@@ -542,7 +558,7 @@ namespace brep
// Use parameters long names in the C++ code, short aliases (if present)
// in HTTP URL.
//
- class package_search
+ class packages
{
// Display package search result list starting from this page.
//
@@ -550,7 +566,10 @@ namespace brep
// Package search criteria.
//
- string query | q;
+ // Note that the packages parameter is renamed to '_' by the root
+ // handler (see the request_proxy class for details).
+ //
+ string q | _;
};
class package_details
diff --git a/mod/page.cxx b/mod/page.cxx
index 46f4879..ce12da6 100644
--- a/mod/page.cxx
+++ b/mod/page.cxx
@@ -98,7 +98,8 @@ namespace brep
<< TBODY
<< TR
<< TD(ID="search-txt")
- << *INPUT(TYPE="search", NAME="q", VALUE=query_, AUTOFOCUS="")
+ << *INPUT(TYPE="search", NAME=name_, VALUE=query_,
+ AUTOFOCUS="")
<< ~TD
<< TD(ID="search-btn")
<< *INPUT(TYPE="submit", VALUE="Search")
@@ -192,14 +193,15 @@ namespace brep
<< SPAN(CLASS="value")
<< A
<< HREF
-
- // Propagate search criteria to the package details page.
- //
<< tenant_dir (root_, tenant_) /
- path (mime_url_encode (name_.string (), false))
- << query_param_
+ path (mime_url_encode (name_.string (), false));
- << ~HREF
+ // Propagate search criteria to the package details page.
+ //
+ if (!query_.empty ())
+ s << "?q=" << query_;
+
+ s << ~HREF
<< name_
<< ~A
<< ~SPAN
@@ -255,7 +257,7 @@ namespace brep
<< SPAN(CLASS="value")
<< A
<< HREF
- << tenant_dir (root_, tenant_) << "?q="
+ << tenant_dir (root_, tenant_) << "?packages="
<< mime_url_encode (project_.string ())
<< ~HREF
<< project_
@@ -356,7 +358,8 @@ namespace brep
{
s << A
<< HREF
- << tenant_dir (root_, tenant_) << "?q=" << mime_url_encode (t)
+ << tenant_dir (root_, tenant_) << "?packages="
+ << mime_url_encode (t)
<< ~HREF
<< t
<< ~A;
@@ -500,8 +503,8 @@ namespace brep
if (r.empty ())
{
- // If there is no requirement alternatives specified, then
- // print the comment first word.
+ // If there is no requirement alternatives specified, then print the
+ // comment first word.
//
const auto& c (r.comment);
if (!c.empty ())
diff --git a/mod/page.hxx b/mod/page.hxx
index d3e10db..d9f4249 100644
--- a/mod/page.hxx
+++ b/mod/page.hxx
@@ -60,18 +60,20 @@ namespace brep
const string& tenant_;
};
- // Generates package search form element.
+ // Generates package search form element with the specified query input
+ // element name.
//
class FORM_SEARCH
{
public:
- FORM_SEARCH (const string& q): query_ (q) {}
+ FORM_SEARCH (const string& q, const string& n): query_ (q), name_ (n) {}
void
operator() (xml::serializer&) const;
private:
const string& query_;
+ const string& name_;
};
// Generates counter element.
@@ -160,7 +162,8 @@ namespace brep
const vector<pair<string, string>>& options_;
};
- // Generates package name element.
+ // Generates package name element with an optional search criteria. The
+ // search string should be url-encoded, if specified.
//
class TR_NAME
{
@@ -169,14 +172,14 @@ namespace brep
const string& q,
const dir_path& r,
const string& t)
- : name_ (n), query_param_ (q), root_ (r), tenant_ (t) {}
+ : name_ (n), query_ (q), root_ (r), tenant_ (t) {}
void
operator() (xml::serializer&) const;
private:
const package_name& name_;
- const string& query_param_;
+ const string& query_;
const dir_path& root_;
const string& tenant_;
};