aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--brep/mod-package-version-details.cxx3
-rw-r--r--brep/package7
-rw-r--r--brep/package.cxx4
-rw-r--r--brep/package.xml1
-rw-r--r--brep/page14
-rw-r--r--brep/page.cxx11
-rw-r--r--load/buildfile3
-rw-r--r--load/load.cli37
-rw-r--r--load/load.cxx172
-rw-r--r--migrate/buildfile4
-rw-r--r--migrate/migrate.cli31
-rw-r--r--migrate/migrate.cxx110
-rw-r--r--tests/load/1/math/packages2
-rw-r--r--tests/load/1/misc/packages4
-rw-r--r--tests/load/driver.cxx183
-rw-r--r--www/package-version-details-body.css6
16 files changed, 398 insertions, 194 deletions
diff --git a/brep/mod-package-version-details.cxx b/brep/mod-package-version-details.cxx
index cbf9c86..992b829 100644
--- a/brep/mod-package-version-details.cxx
+++ b/brep/mod-package-version-details.cxx
@@ -161,7 +161,7 @@ handle (request& rq, response& rs)
: P_DESCRIPTION (*d, options_->package_description (),
url (!full, id)));
- assert (pkg->location);
+ assert (pkg->location && pkg->sha256sum);
s << TABLE(CLASS="proplist", ID="version")
<< TBODY
@@ -175,6 +175,7 @@ handle (request& rq, response& rs)
<< TR_LOCATION (pkg->internal_repository.object_id (), root)
<< TR_DOWNLOAD (pkg->internal_repository.load ()->location.string () +
"/" + pkg->location->string ())
+ << TR_SHA256SUM (*pkg->sha256sum)
<< ~TBODY
<< ~TABLE
diff --git a/brep/package b/brep/package
index fa129f3..67f0e31 100644
--- a/brep/package
+++ b/brep/package
@@ -132,7 +132,7 @@ namespace brep
std::chrono::nanoseconds::period>::value,
"The following timestamp ODB mapping is invalid");
- // As it pointed out in butl/timestamp we will overflow in year 2262 but
+ // As it pointed out in butl/timestamp we will overflow in year 2262, but
// by that time some larger basic type will be available for mapping.
//
#pragma db map type(timestamp) as(uint64_t) \
@@ -470,6 +470,7 @@ namespace brep
dependencies_type,
requirements_type,
optional<path> location,
+ optional<string> sha256sum,
shared_ptr<repository_type>);
// Create external package object.
@@ -506,6 +507,10 @@ namespace brep
//
optional<path> location;
+ // Present only for internal packages.
+ //
+ optional<string> sha256sum;
+
vector<lazy_shared_ptr<repository_type>> other_repositories;
// Database mapping.
diff --git a/brep/package.cxx b/brep/package.cxx
index 1f93a56..d1bbe21 100644
--- a/brep/package.cxx
+++ b/brep/package.cxx
@@ -62,6 +62,7 @@ namespace brep
dependencies_type dp,
requirements_type rq,
optional<path> lc,
+ optional<string> sh,
shared_ptr<repository_type> rp)
: id (move (nm), vr),
version (move (vr)),
@@ -78,7 +79,8 @@ namespace brep
dependencies (move (dp)),
requirements (move (rq)),
internal_repository (move (rp)),
- location (move (lc))
+ location (move (lc)),
+ sha256sum (move (sh))
{
assert (internal_repository->internal);
}
diff --git a/brep/package.xml b/brep/package.xml
index 6abbf1d..14598a5 100644
--- a/brep/package.xml
+++ b/brep/package.xml
@@ -87,6 +87,7 @@
<column name="package_email_comment" type="TEXT" null="true"/>
<column name="internal_repository" type="TEXT" null="true"/>
<column name="location" type="TEXT" null="true"/>
+ <column name="sha256sum" type="TEXT" null="true"/>
<column name="search_index" type="tsvector" null="true"/>
<primary-key>
<column name="name"/>
diff --git a/brep/page b/brep/page
index 4f97ef8..512c11a 100644
--- a/brep/page
+++ b/brep/page
@@ -293,6 +293,20 @@ namespace brep
const string& url_;
};
+ // Generates sha256sum element.
+ //
+ class TR_SHA256SUM
+ {
+ public:
+ TR_SHA256SUM (const string& s): sha256sum_ (s) {}
+
+ void
+ operator() (xml::serializer&) const;
+
+ private:
+ const string& sha256sum_;
+ };
+
// Generates comment element.
//
class SPAN_COMMENT
diff --git a/brep/page.cxx b/brep/page.cxx
index 27e1b2a..689ee20 100644
--- a/brep/page.cxx
+++ b/brep/page.cxx
@@ -481,6 +481,17 @@ namespace brep
<< ~TR;
}
+ // TR_SHA256SUM
+ //
+ void TR_SHA256SUM::
+ operator() (serializer& s) const
+ {
+ s << TR(CLASS="sha256")
+ << TH << "sha256" << ~TH
+ << TD << SPAN(CLASS="value") << sha256sum_ << ~SPAN << ~TD
+ << ~TR;
+ }
+
// SPAN_COMMENT
//
void SPAN_COMMENT::
diff --git a/load/buildfile b/load/buildfile
index 6b72dae..333c091 100644
--- a/load/buildfile
+++ b/load/buildfile
@@ -15,6 +15,7 @@ exe{brep-load}: \
../brep/lib{brep} $libs
cli.options += -I $src_root --include-with-brackets --include-prefix load \
---guard-prefix LOAD
+--guard-prefix LOAD --generate-specifier --page-usage print_ --ansi-color \
+--long-usage
{hxx ixx cxx}{load-options}: cli{load}
diff --git a/load/load.cli b/load/load.cli
index 751d1bd..5c30c14 100644
--- a/load/load.cli
+++ b/load/load.cli
@@ -2,6 +2,7 @@
// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
+include <vector>;
include <string>;
include <cstdint>; // uint16_t
@@ -21,9 +22,9 @@ include <cstdint>; // uint16_t
\h|DESCRIPTION|
\cb{brep-load} reads the list of repositories from the specified
- configuration <file>, fetches their manifest files, and loads the repository
- and package information into the database, suitable for consumption by the
- \cb{brep} web module.
+ configuration <file>, fetches their manifest files, and loads the
+ repository and package information into the database, suitable for
+ consumption by the \cb{brep} web module.
Note that \cb{brep-load} expects the database schema to have already been
created using \l{brep-migrate(1)}."
@@ -67,6 +68,36 @@ class options
"Database port number. If not specified, the default port is used."
}
+ std::string --pager // String to allow empty value.
+ {
+ "<path>",
+ "The pager program to be used to show long text. Commonly used pager
+ programs are \cb{less} and \cb{more}. You can also specify additional
+ options that should be passed to the pager program with
+ \cb{--pager-option}. If an empty string is specified as the pager
+ program, then no pager will be used. If the pager program is not
+ explicitly specified, then \cb{brep-load} will try to use \cb{less}. If
+ it is not available, then no pager will be used."
+ }
+
+ std::vector<std::string> --pager-option
+ {
+ "<opt>",
+ "Additional option to be passed to the pager program. See \cb{--pager}
+ for more information on the pager program. Repeat this option to
+ specify multiple pager options."
+ }
+
bool --help {"Print usage information and exit."}
bool --version {"Print version and exit."}
};
+
+"\h|EXIT STATUS|
+
+\cb{0} Successful termination.
+
+\cb{1} \cb{brep-load} or \l{brep-migrate(1)} instance is running. Try
+ again.
+
+\cb{2} Fatal error.
+"
diff --git a/load/load.cxx b/load/load.cxx
index b4dcd11..7556449 100644
--- a/load/load.cxx
+++ b/load/load.cxx
@@ -2,7 +2,6 @@
// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
-#include <sstream>
#include <fstream>
#include <iostream>
#include <algorithm> // find(), find_if()
@@ -14,6 +13,7 @@
#include <odb/pgsql/database.hxx>
+#include <butl/pager>
#include <butl/filesystem>
#include <bpkg/manifest-parser> // manifest_parsing
@@ -34,15 +34,12 @@ using namespace butl;
using namespace bpkg;
using namespace brep;
-static void
-usage (ostream& os)
-{
- os << "Usage: brep-load [options] <file>" << endl
- << "File lists internal repositories." << endl
- << "Options:" << endl;
+// Operation failed, diagnostics has already been issued.
+//
+struct failed: std::exception {};
- options::print_usage (os);
-}
+static const char* help_info (
+ " info: run 'brep-load --help' for more information");
static inline bool
space (char c) noexcept
@@ -75,7 +72,10 @@ load_repositories (path p)
ifstream ifs (p.string ());
if (!ifs.is_open ())
- throw ifstream::failure (p.string () + ": unable to open");
+ {
+ cerr << "error: unable to open " << p << " in read mode" << endl;
+ throw failed ();
+ }
ifs.exceptions (ifstream::badbit);
@@ -108,11 +108,13 @@ load_repositories (path p)
auto pb (i); // Location begin.
skip (false); // Find end of location.
- auto bad_line ([&p, l, &pb, &b](const string& d) {
- ostringstream os;
- os << p << ':' << l << ':' << pb - b + 1 << ": error: " << d;
- throw runtime_error (os.str ());
- });
+ auto bad_line = [&p, l, &pb, &b](const string& d)
+ {
+ cerr << p << ':' << l << ':' << pb - b + 1 << ": error: " << d
+ << endl;
+
+ throw failed ();
+ };
repository_location location;
@@ -186,7 +188,8 @@ load_repositories (path p)
}
catch (const ifstream::failure&)
{
- throw ifstream::failure (p.string () + ": io failure");
+ cerr << "error: unable to read " << p << endl;
+ throw failed ();
}
return repos;
@@ -208,7 +211,8 @@ changed (const internal_repositories& repos, database& db)
db.find<repository> (r.location.canonical_name ()));
if (pr == nullptr || r.location.string () != pr->location.string () ||
- r.display_name != pr->display_name || r.local_path != pr->local_path ||
+ r.display_name != pr->display_name ||
+ r.local_path != pr->local_path ||
file_mtime (r.packages_path ()) != pr->packages_timestamp ||
file_mtime (r.repositories_path ()) != pr->repositories_timestamp ||
!pr->internal)
@@ -224,8 +228,8 @@ changed (const internal_repositories& repos, database& db)
//
return
!db.query<repository> (
- query::internal && !query::name.in_range (names.begin (), names.end ())).
- empty ();
+ query::internal &&
+ !query::name.in_range (names.begin (), names.end ())).empty ();
}
static timestamp
@@ -233,7 +237,10 @@ manifest_stream (const path& p, ifstream& f)
{
f.open (p.string ());
if (!f.is_open ())
- throw ifstream::failure (p.string () + ": unable to open");
+ {
+ cerr << "error: unable to open " << p << " in read mode" << endl;
+ throw failed ();
+ }
f.exceptions (ifstream::badbit | ifstream::failbit);
return file_mtime (p);
@@ -268,7 +275,13 @@ load_packages (const shared_ptr<repository>& rp, database& db)
for (auto& pm: pkm)
{
- shared_ptr<package> p (db.find<package> (package_id (pm.name, pm.version)));
+ shared_ptr<package> p (
+ db.find<package> (package_id (pm.name, pm.version)));
+
+ // sha256sum should always be present if the package manifest comes from
+ // the 'packages' file.
+ //
+ assert (pm.sha256sum);
if (p == nullptr)
{
@@ -338,6 +351,7 @@ load_packages (const shared_ptr<repository>& rp, database& db)
move (ds),
move (pm.requirements),
move (pm.location),
+ move (pm.sha256sum),
rp);
}
else
@@ -349,16 +363,19 @@ load_packages (const shared_ptr<repository>& rp, database& db)
}
else
{
- // @@ Need to ensure that the same packages coming from different
- // repositories are equal. Probably will invent hashsum at some point
- // for this purpose.
- //
-
// As soon as internal repositories get loaded first, the internal
// package can duplicate an internal package only.
//
assert (!rp->internal || p->internal ());
+ if (rp->internal && pm.sha256sum != p->sha256sum)
+ cerr << "warning: sha256sum mismatch for package " << p->id.name
+ << " " << p->version << endl
+ << " info: " << p->internal_repository.load ()->location
+ << " has " << *p->sha256sum << endl
+ << " info: " << rp->location << " has " << *pm.sha256sum
+ << endl;
+
p->other_repositories.push_back (rp);
db.update (p);
}
@@ -402,7 +419,8 @@ load_repositories (const shared_ptr<repository>& rp, database& db)
for (auto& rm: rpm)
{
- if (rm.effective_role () == repository_role::prerequisite && !rp->internal)
+ if (rm.effective_role () == repository_role::prerequisite &&
+ !rp->internal)
continue; // Ignore the external repository prerequisite entry.
if (rm.effective_role () == repository_role::base)
@@ -449,12 +467,12 @@ load_repositories (const shared_ptr<repository>& rp, database& db)
auto bad_location (
[&rp, &rm]()
{
- ostringstream o;
- o << "invalid location '" << rm.location.string ()
- << "' of the prerequisite repository for internal "
- "repository '" << rp->location.string () << "'";
+ cerr << "error: invalid prerequisite repository location "
+ << rm.location << endl
+ << " info: base (internal) repository location is "
+ << rp->location << endl;
- throw runtime_error (o.str ());
+ throw failed ();
});
try
@@ -508,12 +526,12 @@ load_repositories (const shared_ptr<repository>& rp, database& db)
}
catch (const invalid_path&)
{
- ostringstream o;
- o << "can't normalize local path'" << lp.string ()
- << "' of the prerequisite repository for internal "
- "repository '" << rp->location.string () << "'";
+ cerr << "error: can't normalize prerequisite repository local path '"
+ << lp << "'" << endl
+ << " info: base (internal) repository location is "
+ << rp->location << endl;
- throw runtime_error (o.str ());
+ throw failed ();
}
}
@@ -536,7 +554,8 @@ find (const lazy_shared_ptr<repository>& r,
assert (r != nullptr);
const auto& o (p.other_repositories);
- if (r == p.internal_repository || find (o.begin (), o.end (), r) != o.end ())
+ if (r == p.internal_repository ||
+ find (o.begin (), o.end (), r) != o.end ())
return true;
auto rp (r.load ());
@@ -629,17 +648,18 @@ resolve_dependencies (package& p, database& db)
if (d.package.object_id ().version.empty ())
{
- ostringstream o;
- o << "can't resolve dependency " << d << " of the package "
- << p.id.name << " " << p.version.string ()
- << " (" << p.internal_repository.load ()->name << ")";
+ cerr << "error: can't resolve dependency " << d << " of the package "
+ << p.id.name << " " << p.version << endl
+ << " info: repository "
+ << p.internal_repository.load ()->location
+ << " appears to be broken" << endl;
// Practically it is enough to resolve at least one dependency
// alternative to build a package. Meanwhile here we consider an error
// specifying in the manifest file an alternative which can't be
// resolved.
//
- throw runtime_error (o.str ());
+ throw failed ();
}
}
}
@@ -650,14 +670,15 @@ resolve_dependencies (package& p, database& db)
using package_ids = vector<package_id>;
// Ensure the package dependency chain do not contain the package id. Throw
-// runtime_error otherwise. Continue the chain with the package id and call
-// itself recursively for each prerequisite of the package. Should be called
-// once per internal package.
+// failed otherwise. Continue the chain with the package id and call itself
+// recursively for each prerequisite of the package. Should be called once per
+// internal package.
//
// @@ This should probably be eventually moved to bpkg.
//
static void
-detect_dependency_cycle (const package_id& id, package_ids& chain, database& db)
+detect_dependency_cycle (
+ const package_id& id, package_ids& chain, database& db)
{
// Package of one version depending on the same package of another version
// is something obscure. So the comparison is made up to a package name.
@@ -667,11 +688,10 @@ detect_dependency_cycle (const package_id& id, package_ids& chain, database& db)
if (i != chain.end ())
{
- ostringstream o;
- o << "package dependency cycle: ";
+ cerr << "error: package dependency cycle: ";
auto prn (
- [&o, &db](const package_id& id)
+ [&db](const package_id& id)
{
shared_ptr<package> p (db.load<package> (id));
assert (p->internal () || !p->other_repositories.empty ());
@@ -681,17 +701,18 @@ detect_dependency_cycle (const package_id& id, package_ids& chain, database& db)
? p->internal_repository.load ()
: p->other_repositories[0].load ());
- o << id.name << " " << p->version.string () << " (" << r->name << ")";
+ cerr << id.name << " " << p->version << " (" << r->name << ")";
});
for (; i != chain.end (); ++i)
{
prn (*i);
- o << " -> ";
+ cerr << " -> ";
}
prn (id);
- throw runtime_error (o.str ());
+ cerr << endl;
+ throw failed ();
}
chain.push_back (id);
@@ -731,22 +752,30 @@ try
//
if (ops.help ())
{
- usage (cout);
- return 0;
+ pager p ("brep-load help",
+ false,
+ ops.pager_specified () ? &ops.pager () : nullptr,
+ &ops.pager_option ());
+
+ print_usage (p.stream ());
+
+ // If the pager failed, assume it has issued some diagnostics.
+ //
+ return p.wait () ? 0 : 2;
}
if (argc < 2)
{
- cerr << "<file> argument not provided" << endl;
- usage (cerr);
- return 1;
+ cerr << "error: configuration file path argument expected" << endl
+ << help_info << endl;
+ return 2;
}
if (argc > 2)
{
- cerr << "unexpected argument encountered" << endl;
- usage (cerr);
- return 1;
+ cerr << "error: unexpected argument encountered" << endl
+ << help_info << endl;
+ return 2;
}
odb::pgsql::database db (ops.db_user (),
@@ -766,8 +795,9 @@ try
//
if (schema_catalog::current_version (db) != db.schema_version ())
{
- cerr << "database schema differs from the current one" << endl;
- return 1;
+ cerr << "error: database schema differs from the current one" << endl
+ << " info: use brep-migrate to migrate the database" << endl;
+ return 2;
}
// Load the description of all the internal repositories from the
@@ -827,22 +857,26 @@ try
}
t.commit ();
+ return 0;
}
catch (const database_locked&)
{
cerr << "brep-load or brep-migrate instance is running" << endl;
- return 2;
+ return 1;
}
catch (const cli::exception& e)
{
- cerr << e << endl;
- usage (cerr);
- return 1;
+ cerr << "error: " << e << endl << help_info << endl;
+ return 2;
+}
+catch (const failed&)
+{
+ return 2; // Diagnostics has already been issued.
}
// Fully qualified to avoid ambiguity with odb exception.
//
catch (const std::exception& e)
{
- cerr << e.what () << endl;
- return 1;
+ cerr << "error: " << e.what () << endl;
+ return 2;
}
diff --git a/migrate/buildfile b/migrate/buildfile
index cd0b9c8..1722fea 100644
--- a/migrate/buildfile
+++ b/migrate/buildfile
@@ -2,6 +2,7 @@
# copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
# license : MIT; see accompanying LICENSE file
+import libs += libbutl%lib{butl}
import libs += libodb-pgsql%lib{odb-pgsql}
import libs += libodb%lib{odb}
@@ -13,6 +14,7 @@ exe{brep-migrate}: \
../brep/lib{brep} $libs
cli.options += -I $src_root --include-with-brackets --include-prefix migrate \
---guard-prefix MIGRATE
+--guard-prefix MIGRATE --generate-specifier --page-usage print_ --ansi-color \
+--long-usage
{hxx ixx cxx}{migrate-options}: cli{migrate}
diff --git a/migrate/migrate.cli b/migrate/migrate.cli
index 35d082f..dcbf667 100644
--- a/migrate/migrate.cli
+++ b/migrate/migrate.cli
@@ -2,6 +2,7 @@
// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
+include <vector>;
include <string>;
include <cstdint>; // uint16_t
@@ -85,6 +86,36 @@ class options
"Database port number. If not specified, the default port is used."
}
+ std::string --pager // String to allow empty value.
+ {
+ "<path>",
+ "The pager program to be used to show long text. Commonly used pager
+ programs are \cb{less} and \cb{more}. You can also specify additional
+ options that should be passed to the pager program with
+ \cb{--pager-option}. If an empty string is specified as the pager
+ program, then no pager will be used. If the pager program is not
+ explicitly specified, then \cb{brep-migrate} will try to use \cb{less}.
+ If it is not available, then no pager will be used."
+ }
+
+ std::vector<std::string> --pager-option
+ {
+ "<opt>",
+ "Additional option to be passed to the pager program. See \cb{--pager}
+ for more information on the pager program. Repeat this option to
+ specify multiple pager options."
+ }
+
bool --help {"Print usage information and exit."}
bool --version {"Print version and exit."}
};
+
+"\h|EXIT STATUS|
+
+\cb{0} Successful termination.
+
+\cb{1} \cb{brep-migrate} or \l{brep-load(1)} instance is running. Try
+ again.
+
+\cb{2} Fatal error.
+"
diff --git a/migrate/migrate.cxx b/migrate/migrate.cxx
index 702eba0..70ba54f 100644
--- a/migrate/migrate.cxx
+++ b/migrate/migrate.cxx
@@ -13,6 +13,8 @@
#include <odb/pgsql/database.hxx>
+#include <butl/pager>
+
#include <brep/types>
#include <brep/utility>
#include <brep/version>
@@ -25,6 +27,13 @@ using namespace std;
using namespace odb::core;
using namespace brep;
+// Operation failed, diagnostics has already been issued.
+//
+struct failed: std::exception {};
+
+static const char* help_info (
+ " info: run 'brep-migrate --help' for more information");
+
// Helper class that encapsulates both the ODB-generated schema and the
// extra that comes from a .sql file (via xxd).
//
@@ -108,19 +117,28 @@ schema (const char* s)
if (strcasecmp (kw.c_str (), "FUNCTION") == 0)
{
if (!read_until ("$$") || !read_until ("$$"))
- throw invalid_argument (
- "function body must be defined using $$-quoted strings");
+ {
+ cerr << "error: function body must be defined using $$-quoted "
+ "strings" << endl;
+ throw failed ();
+ }
}
else if (strcasecmp (kw.c_str (), "TYPE") == 0)
{
// Fall through.
}
else
- throw invalid_argument ("unexpected CREATE statement");
+ {
+ cerr << "error: unexpected CREATE statement" << endl;
+ throw failed ();
+ }
if (!read_until (";\n"))
- throw invalid_argument (
- "expected ';\\n' at the end of CREATE statement");
+ {
+ cerr << "error: expected ';\\n' at the end of CREATE statement"
+ << endl;
+ throw failed ();
+ }
assert (!statement.empty ());
create_statements_.emplace_back (move (statement));
@@ -128,15 +146,21 @@ schema (const char* s)
else if (strcasecmp (op.c_str (), "DROP") == 0)
{
if (!read_until (";\n"))
- throw invalid_argument (
- "expected ';\\n' at the end of DROP statement");
+ {
+ cerr << "error: expected ';\\n' at the end of DROP statement"
+ << endl;
+ throw failed ();
+ }
assert (!statement.empty ());
drop_statements_.emplace_back (move (statement));
}
else
- throw invalid_argument (
- "unexpected statement starting with '" + op + "'");
+ {
+ cerr << "error: unexpected statement starting with '" << op << "'"
+ << endl;
+ throw failed ();
+ }
}
}
}
@@ -166,17 +190,6 @@ create (database& db) const
db.execute (s);
}
-// Utility functions
-//
-static void
-usage (ostream& os)
-{
- os << "Usage: brep-migrate [options]" << endl
- << "Options:" << endl;
-
- options::print_usage (os);
-}
-
// main() function
//
int
@@ -204,22 +217,30 @@ try
//
if (ops.help ())
{
- usage (cout);
- return 0;
+ butl::pager p ("brep-migrate help",
+ false,
+ ops.pager_specified () ? &ops.pager () : nullptr,
+ &ops.pager_option ());
+
+ print_usage (p.stream ());
+
+ // If the pager failed, assume it has issued some diagnostics.
+ //
+ return p.wait () ? 0 : 2;
}
if (argc > 1)
{
- cerr << "unexpected argument encountered" << endl;
- usage (cerr);
- return 1;
+ cerr << "error: unexpected argument encountered" << endl
+ << help_info << endl;
+ return 2;
}
if (ops.recreate () && ops.drop ())
{
- cerr << "inconsistent options specified" << endl;
- usage (cerr);
- return 1;
+ cerr << "error: inconsistent options specified" << endl
+ << help_info << endl;
+ return 2;
}
odb::pgsql::database db (ops.db_user (),
@@ -247,10 +268,16 @@ try
if (schema_version > 0)
{
if (schema_version < schema_catalog::base_version (db))
- throw runtime_error ("database schema is too old");
+ {
+ cerr << "error: database schema is too old" << endl;
+ throw failed ();
+ }
if (schema_version > schema_catalog::current_version (db))
- throw runtime_error ("database schema is too new");
+ {
+ cerr << "error: database schema is too new" << endl;
+ throw failed ();
+ }
}
bool drop (ops.drop ());
@@ -264,7 +291,12 @@ try
//
if ((create || drop) && schema_version != 0 &&
schema_version != schema_catalog::current_version (db))
- throw runtime_error ("database schema requires migration");
+ {
+ cerr << "error: database schema requires migration" << endl
+ << " info: either migrate the database first or drop the entire "
+ "database using, for example, psql" << endl;
+ throw failed ();
+ }
transaction t (db.begin ());
@@ -292,22 +324,26 @@ try
}
t.commit ();
+ return 0;
}
catch (const database_locked&)
{
cerr << "brep-migrate or brep-load instance is running" << endl;
- return 2;
+ return 1;
}
catch (const cli::exception& e)
{
- cerr << e << endl;
- usage (cerr);
- return 1;
+ cerr << "error: " << e << endl << help_info << endl;
+ return 2;
+}
+catch (const failed&)
+{
+ return 2; // Diagnostics has already been issued.
}
// Fully qualified to avoid ambiguity with odb exception.
//
catch (const std::exception& e)
{
- cerr << e.what () << endl;
- return 1;
+ cerr << "error: " << e.what () << endl;
+ return 2;
}
diff --git a/tests/load/1/math/packages b/tests/load/1/math/packages
index 9c8bfea..115e3f1 100644
--- a/tests/load/1/math/packages
+++ b/tests/load/1/math/packages
@@ -74,4 +74,4 @@ license: MIT
url: http://www.example.com/foo/
email: foo-users@example.com
location: libfoo-1.0.tar.gz
-sha256sum: 45ccba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93
+sha256sum: 754cba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93
diff --git a/tests/load/1/misc/packages b/tests/load/1/misc/packages
index 9cffca5..f4f7f59 100644
--- a/tests/load/1/misc/packages
+++ b/tests/load/1/misc/packages
@@ -24,7 +24,7 @@ license: MIT
url: http://www.example.com/foo/
email: foo-users@example.com
location: libfoo-1.0.tar.gz
-sha256sum: 71ccba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93
+sha256sum: 754cba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93
:
name: libfoo
version: 0.1
@@ -42,7 +42,7 @@ license: MIT
url: http://www.example.com/foo/
email: foo-users@example.com
location: libfoo-1.2.4+1.tar.gz
-sha256sum: 73ccba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93
+sha256sum: 35ccba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93
:
name: libfoo
version: 1.2.4+2
diff --git a/tests/load/driver.cxx b/tests/load/driver.cxx
index 41e4623..a9b9823 100644
--- a/tests/load/driver.cxx
+++ b/tests/load/driver.cxx
@@ -39,11 +39,11 @@ static bool
check_external (const package& p)
{
return p.summary.empty () && p.tags.empty () && !p.description &&
- p.url.empty () && !p.package_url && p.email.empty () && !p.package_email &&
- !p.internal () && p.other_repositories.size () > 0 &&
+ p.url.empty () && !p.package_url && p.email.empty () &&
+ !p.package_email && !p.internal () && p.other_repositories.size () > 0 &&
p.priority == priority () && p.changes.empty () &&
p.license_alternatives.empty () && p.dependencies.empty () &&
- p.requirements.empty ();
+ p.requirements.empty () && !p.sha256sum;
}
int
@@ -122,27 +122,6 @@ main (int argc, char* argv[])
assert (sr->repositories_timestamp ==
file_mtime (dir_path (sr->local_path) / path ("repositories")));
assert (sr->internal);
-
- shared_ptr<package> fpv1 (
- db.load<package> (package_id ("libfoo", version ("1.0"))));
- assert (check_location (fpv1));
-
- shared_ptr<package> fpv2 (
- db.load<package> (package_id ("libfoo", version ("1.2.2"))));
- assert (check_location (fpv2));
-
- shared_ptr<package> fpv2a (
- db.load<package> (package_id ("libfoo", version ("1.2.2-alpha.1"))));
- assert (check_location (fpv2a));
-
- shared_ptr<package> fpv3 (
- db.load<package> (package_id ("libfoo", version ("1.2.3+4"))));
- assert (check_location (fpv3));
-
- shared_ptr<package> fpv4 (
- db.load<package> (package_id ("libfoo", version ("1.2.4"))));
- assert (check_location (fpv4));
-
assert (sr->complements.empty ());
assert (sr->prerequisites.size () == 2);
assert (sr->prerequisites[0].load () == cr);
@@ -152,6 +131,9 @@ main (int argc, char* argv[])
//
// libfoo-1.0
//
+ shared_ptr<package> fpv1 (
+ db.load<package> (package_id ("libfoo", version ("1.0"))));
+
assert (fpv1->summary == "The Foo Library");
assert (fpv1->tags.empty ());
assert (!fpv1->description);
@@ -175,8 +157,16 @@ main (int argc, char* argv[])
assert (fpv1->dependencies.empty ());
assert (fpv1->requirements.empty ());
+ assert (check_location (fpv1));
+
+ assert (fpv1->sha256sum && *fpv1->sha256sum ==
+ "754cba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93");
+
// libfoo-1.2.2
//
+ shared_ptr<package> fpv2 (
+ db.load<package> (package_id ("libfoo", version ("1.2.2"))));
+
assert (fpv2->summary == "The Foo library");
assert (fpv2->tags == strings ({"c++", "foo"}));
assert (!fpv2->description);
@@ -202,7 +192,8 @@ main (int argc, char* argv[])
[&db](const char* n,
const optional<dependency_constraint>& c) -> dependency
{
- return {lazy_shared_ptr<package> (db, package_id (n, version ())), c};
+ return {
+ lazy_shared_ptr<package> (db, package_id (n, version ())), c};
});
assert (fpv2->dependencies[0][0] ==
@@ -219,8 +210,16 @@ main (int argc, char* argv[])
dependency_constraint (
version ("1~1.2"), false, version ("1~1.2"), false))));
+ assert (check_location (fpv2));
+
+ assert (fpv2->sha256sum && *fpv2->sha256sum ==
+ "751cba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93");
+
// libfoo-1.2.2-alpha.1
//
+ shared_ptr<package> fpv2a (
+ db.load<package> (package_id ("libfoo", version ("1.2.2-alpha.1"))));
+
assert (fpv2a->summary == "The Foo library");
assert (fpv2a->tags == strings ({"c++", "foo"}));
assert (!fpv2a->description);
@@ -280,8 +279,16 @@ main (int argc, char* argv[])
assert (fpv2a->requirements.empty ());
+ assert (check_location (fpv2a));
+
+ assert (fpv2a->sha256sum && *fpv2a->sha256sum ==
+ "752cba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93");
+
// libfoo-1.2.3-4
//
+ shared_ptr<package> fpv3 (
+ db.load<package> (package_id ("libfoo", version ("1.2.3+4"))));
+
assert (fpv3->summary == "The Foo library");
assert (fpv3->tags == strings ({"c++", "foo"}));
assert (!fpv3->description);
@@ -309,8 +316,16 @@ main (int argc, char* argv[])
dependency_constraint (
version ("2.0.0"), false, nullopt, true))));
+ assert (check_location (fpv3));
+
+ assert (fpv3->sha256sum && *fpv3->sha256sum ==
+ "750cba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93");
+
// libfoo-1.2.4
//
+ shared_ptr<package> fpv4 (
+ db.load<package> (package_id ("libfoo", version ("1.2.4"))));
+
assert (fpv4->summary == "The Foo Library");
assert (fpv4->tags == strings ({"c++", "foo"}));
assert (*fpv4->description == "Very good foo library.");
@@ -339,6 +354,11 @@ main (int argc, char* argv[])
dependency_constraint (
version ("2.0.0"), false, nullopt, true))));
+ assert (check_location (fpv4));
+
+ assert (fpv4->sha256sum && *fpv4->sha256sum ==
+ "753cba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93");
+
// Verify 'math' repository.
//
assert (mr->location.canonical_name () == "cppget.org/math");
@@ -362,24 +382,15 @@ main (int argc, char* argv[])
file_mtime (dir_path (mr->local_path) / path ("repositories")));
assert (mr->internal);
- shared_ptr<package> epv (
- db.load<package> (package_id ("libexp", version ("1~1.2+1"))));
- assert (check_location (epv));
-
- shared_ptr<package> fpv5 (
- db.load<package> (package_id ("libfoo", version ("1.2.4+1"))));
- assert (check_location (fpv5));
-
- shared_ptr<package> xpv (
- db.load<package> (package_id ("libstudxml", version ("1.0.0+1"))));
- assert (check_location (xpv));
-
assert (mr->complements.empty ());
assert (mr->prerequisites.size () == 1);
assert (mr->prerequisites[0].load () == cr);
// Verify libstudxml package version.
//
+ shared_ptr<package> xpv (
+ db.load<package> (package_id ("libstudxml", version ("1.0.0+1"))));
+
assert (xpv->summary == "Modern C++ XML API");
assert (xpv->tags == strings ({"c++", "xml", "parser", "serializer",
"pull", "streaming", "modern"}));
@@ -417,18 +428,26 @@ main (int argc, char* argv[])
assert (xpv->requirements.empty ());
+ assert (check_location (xpv));
+
+ assert (xpv->sha256sum && *xpv->sha256sum ==
+ "05ccba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93");
+
// Verify libfoo package versions.
//
// libfoo-1.2.4-1
//
+ shared_ptr<package> fpv5 (
+ db.load<package> (package_id ("libfoo", version ("1.2.4+1"))));
+
assert (fpv5->summary == "The Foo Math Library");
assert (fpv5->tags == strings ({"c++", "foo", "math"}));
assert (*fpv5->description ==
- "A modern C++ library with easy to use linear algebra and lot of "
- "optimization\ntools.\n\nThere are over 100 functions in total "
- "with an extensive test suite. The API is\nsimilar to MATLAB."
- "\n\nUseful for conversion of research code into production "
- "environments.");
+ "A modern C++ library with easy to use linear algebra and lot "
+ "of optimization\ntools.\n\nThere are over 100 functions in "
+ "total with an extensive test suite. The API is\nsimilar to "
+ "MATLAB.\n\nUseful for conversion of research code into "
+ "production environments.");
assert (fpv5->url == "http://www.example.com/foo/");
assert (fpv5->package_url &&
*fpv5->package_url == "http://www.example.com/foo/pack");
@@ -518,10 +537,18 @@ main (int argc, char* argv[])
assert (fpvr5[3].conditional);
assert (fpvr5[3].comment == "Only if using VC++ on Windows.");
+ assert (check_location (fpv5));
+
+ assert (fpv5->sha256sum && *fpv5->sha256sum ==
+ "35ccba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93");
+
// Verify libexp package version.
//
// libexp-1+1.2
//
+ shared_ptr<package> epv (
+ db.load<package> (package_id ("libexp", version ("1~1.2+1"))));
+
assert (epv->summary == "The exponent");
assert (epv->tags == strings ({"c++", "exponent"}));
assert (epv->description && *epv->description ==
@@ -546,6 +573,11 @@ main (int argc, char* argv[])
assert (epv->requirements.empty ());
+ assert (check_location (epv));
+
+ assert (epv->sha256sum && *epv->sha256sum ==
+ "15ccba3da34dd0296866027a26b6bacf08cacc80f54516d3b8d8eeccbe31ab93");
+
// Verify 'misc' repository.
//
assert (cr->location.canonical_name () == "cppget.org/misc");
@@ -566,19 +598,6 @@ main (int argc, char* argv[])
assert (cr->repositories_timestamp ==
file_mtime (dir_path (cr->local_path) / path ("repositories")));
assert (!cr->internal);
-
- shared_ptr<package> bpv (
- db.load<package> (package_id ("libbar", version ("2.4.0+3"))));
- assert (check_location (bpv));
-
- shared_ptr<package> fpv0 (
- db.load<package> (package_id ("libfoo", version ("0.1"))));
- assert (check_location (fpv0));
-
- shared_ptr<package> fpv6 (
- db.load<package> (package_id ("libfoo", version ("1.2.4+2"))));
- assert (check_location (fpv6));
-
assert (cr->prerequisites.empty ());
assert (cr->complements.size () == 1);
assert (cr->complements[0].load () == tr);
@@ -587,23 +606,35 @@ main (int argc, char* argv[])
//
// libbar-2.4.0+3
//
+ shared_ptr<package> bpv (
+ db.load<package> (package_id ("libbar", version ("2.4.0+3"))));
+
assert (check_external (*bpv));
assert (bpv->other_repositories.size () == 1);
assert (bpv->other_repositories[0].load () == cr);
+ assert (check_location (bpv));
// Verify libfoo package versions.
//
// libfoo-0.1
//
+ shared_ptr<package> fpv0 (
+ db.load<package> (package_id ("libfoo", version ("0.1"))));
+
assert (check_external (*fpv0));
assert (fpv0->other_repositories.size () == 1);
assert (fpv0->other_repositories[0].load () == cr);
+ assert (check_location (fpv0));
// libfoo-1.2.4-2
//
+ shared_ptr<package> fpv6 (
+ db.load<package> (package_id ("libfoo", version ("1.2.4+2"))));
+
assert (check_external (*fpv6));
assert (fpv6->other_repositories.size () == 1);
assert (fpv6->other_repositories[0].load () == cr);
+ assert (check_location (fpv6));
// Verify 'testing' repository.
//
@@ -625,15 +656,6 @@ main (int argc, char* argv[])
assert (tr->repositories_timestamp ==
file_mtime (dir_path (tr->local_path) / path ("repositories")));
assert (!tr->internal);
-
- shared_ptr<package> mpv0 (
- db.load<package> (package_id ("libmisc", version ("2.4.0"))));
- assert (check_location (mpv0));
-
- shared_ptr<package> mpv1 (
- db.load<package> (package_id ("libmisc", version ("2.3.0+1"))));
- assert (check_location (mpv1));
-
assert (tr->prerequisites.empty ());
assert (tr->complements.size () == 1);
assert (tr->complements[0].load () == gr);
@@ -642,15 +664,23 @@ main (int argc, char* argv[])
//
// libmisc-2.4.0
//
+ shared_ptr<package> mpv0 (
+ db.load<package> (package_id ("libmisc", version ("2.4.0"))));
+
assert (check_external (*mpv0));
assert (mpv0->other_repositories.size () == 1);
assert (mpv0->other_repositories[0].load () == tr);
+ assert (check_location (mpv0));
// libmisc-2.3.0+1
//
+ shared_ptr<package> mpv1 (
+ db.load<package> (package_id ("libmisc", version ("2.3.0+1"))));
+
assert (check_external (*mpv1));
assert (mpv1->other_repositories.size () == 1);
assert (mpv1->other_repositories[0].load () == tr);
+ assert (check_location (mpv1));
// Verify 'staging' repository.
//
@@ -672,19 +702,6 @@ main (int argc, char* argv[])
assert (gr->repositories_timestamp ==
file_mtime (dir_path (gr->local_path) / path ("repositories")));
assert (!gr->internal);
-
- shared_ptr<package> tpv (
- db.load<package> (package_id ("libexpat", version ("5.1"))));
- assert (check_location (tpv));
-
- shared_ptr<package> gpv (
- db.load<package> (package_id ("libgenx", version ("1.0"))));
- assert (check_location (gpv));
-
- shared_ptr<package> mpv2 (
- db.load<package> (package_id ("libmisc", version ("1.0"))));
- assert (check_location (mpv2));
-
assert (gr->prerequisites.empty ());
assert (gr->complements.empty ());
@@ -692,25 +709,37 @@ main (int argc, char* argv[])
//
// libexpat-5.1
//
+ shared_ptr<package> tpv (
+ db.load<package> (package_id ("libexpat", version ("5.1"))));
+
assert (check_external (*tpv));
assert (tpv->other_repositories.size () == 1);
assert (tpv->other_repositories[0].load () == gr);
+ assert (check_location (tpv));
// Verify libgenx package version.
//
// libgenx-1.0
//
+ shared_ptr<package> gpv (
+ db.load<package> (package_id ("libgenx", version ("1.0"))));
+
assert (check_external (*gpv));
assert (gpv->other_repositories.size () == 1);
assert (gpv->other_repositories[0].load () == gr);
+ assert (check_location (gpv));
// Verify libmisc package version.
//
// libmisc-1.0
//
+ shared_ptr<package> mpv2 (
+ db.load<package> (package_id ("libmisc", version ("1.0"))));
+
assert (check_external (*mpv2));
assert (mpv2->other_repositories.size () == 1);
assert (mpv2->other_repositories[0].load () == gr);
+ assert (check_location (mpv2));
// Change package summary, update the object persistent state, rerun
// loader and ensure the model were not rebuilt.
diff --git a/www/package-version-details-body.css b/www/package-version-details-body.css
index 8af54bc..2b16668 100644
--- a/www/package-version-details-body.css
+++ b/www/package-version-details-body.css
@@ -103,6 +103,12 @@ h1, h2, h3
font-size: 0.94em;
}
+#version tr.sha256 td .value
+{
+ /* Increase the chances of 64-char value not to be truncated. */
+ font-size: 0.9em;
+}
+
/*
* Package details table.
*/