aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-06-12 12:32:06 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-06-17 19:28:03 +0200
commit54e3c33fb327efe0cbfd806c5468cbe390dafeaa (patch)
tree2118df87f8ef53ea36f6e53b135cced7590a4648
parent2fda89944fa528e05c9f6b4fdcd684f2606582a8 (diff)
Implement object model for packages
-rw-r--r--brep/package367
-rw-r--r--brep/package.cxx21
-rw-r--r--brep/search3
-rw-r--r--brep/search.cxx70
-rw-r--r--brep/view3
-rw-r--r--brep/view.cxx87
-rwxr-xr-xbuild.sh5
-rw-r--r--build/root.build1
-rw-r--r--buildfile2
-rw-r--r--etc/config6
-rwxr-xr-xetc/pgctl62
-rw-r--r--www/htdocs/index.html28
12 files changed, 629 insertions, 26 deletions
diff --git a/brep/package b/brep/package
new file mode 100644
index 0000000..1ad11b2
--- /dev/null
+++ b/brep/package
@@ -0,0 +1,367 @@
+// file : brep/package -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BPKG_PACKAGE
+#define BPKG_PACKAGE
+
+#include <map>
+#include <string>
+#include <vector>
+#include <memory> // shared_ptr
+#include <utility> // pair
+
+#include <odb/core.hxx>
+#include <odb/forward.hxx> // database
+#include <odb/lazy-ptr.hxx>
+#include <odb/nullable.hxx>
+
+namespace brep
+{
+ // @@ If namespace, then should probably call it 'repo'.
+ //
+ // @@ Should probably use optional from libbutl instead of odb::nullable
+ // for consistency. Create butl profile?
+ //
+ // @@ Might make sense to put some heavy members (e.g., description,
+ // containers) into a separate section.
+ //
+ // @@ Not sure there is a benefit in making tags a full-blown container
+ // (i.e., a separate table). Maybe provide a mapping of vector<string>
+ // to TEXT as a comma-separated list.
+ //
+
+ // Forward declarations.
+ //
+ struct package;
+ struct package_version;
+
+ using strings = std::vector<std::string>;
+
+ #pragma db value
+ struct package_version_id
+ {
+ std::string package;
+ std::string version;
+
+ // Database mapping.
+ //
+ #pragma db member(package) points_to(package)
+ };
+
+ inline bool
+ operator< (const package_version_id& x, const package_version_id& y)
+ {
+ int r (x.package.compare (y.package));
+ return r < 0 || r == 0 && x.version < y.version;
+ }
+
+ #pragma db value
+ class priority
+ {
+ public:
+ enum value_type {low, medium, high, security};
+
+ value_type value; // Shouldn't be necessary to access directly.
+ std::string comment;
+
+ priority (value_type v = low): value (v) {}
+ operator value_type () const {return value;}
+
+ // Database mapping.
+ //
+ #pragma db member(value) column("")
+ };
+
+ #pragma db value
+ struct url: std::string
+ {
+ std::string comment;
+
+ // Database mapping.
+ //
+ #pragma db member(value) virtual(std::string) before \
+ access(this) column("")
+ };
+
+ #pragma db value
+ struct email: std::string
+ {
+ std::string comment;
+
+ // Database mapping.
+ //
+ #pragma db member(value) virtual(std::string) before \
+ access(this) column("")
+ };
+
+ // licenses
+ //
+ #pragma db value
+ struct licenses: strings
+ {
+ std::string comment;
+ };
+
+ using license_alternatives = std::vector<licenses>;
+
+ // dependencies
+ //
+ enum class comparison {eq, lt, gt, le, ge};
+
+ #pragma db value
+ struct version_comparison
+ {
+ std::string value;
+ comparison operation;
+ };
+
+ #pragma db value
+ struct dependency
+ {
+ using package_type = brep::package;
+
+ // Notes:
+ //
+ // 1. Will the package be always resolvable? What if it is in
+ // another repository (i.e., a "chained" third-party repo).
+ // The question is then whether we will load such "third-
+ // party packages" (i.e., packages that are not in our
+ // repository). If the answer is yes, then we can have
+ // a pointer here. If the answer is no, then we can't.
+ // Also, if the answer is yes, we probably don't need to
+ // load as much information as for "our own" packages. We
+ // also shouldn't be showing them in search results, etc.
+ // I think all we need is to know which repository this
+ // package comes from so that we can tell the user. How are
+ // we going to capture this? Poly hierarchy of packages?
+ //
+ // 2. I believe we don't need to use a weak pointer here since
+ // there should be no package dependency cycles (and therefore
+ // ownership cycles).
+ //
+ // 3. Actually there can be dependency cycle as dependency referes not to
+ // just a package but a specific version, so for the same pair of
+ // packages dependency for different versions can have an opposite
+ // directions. The possible solution is instead of a package we point
+ // to the earliest version that satisfies the condition. But this
+ // approach requires to ensure no cycles exist before instantiating
+ // package objects which in presense of "foreign" packages can be
+ // tricky. Can stick to just a package name until get some clarity on
+ // "foreign" package resolution.
+ //
+ std::string package;
+ odb::nullable<version_comparison> version;
+
+ // Database mapping.
+ //
+ #pragma db member(package) not_null
+ };
+
+ #pragma db value
+ struct dependency_alternatives: std::vector<dependency>
+ {
+ bool conditional;
+ std::string comment;
+ };
+
+ using dependencies = std::vector<dependency_alternatives>;
+
+ // requirements
+ //
+ #pragma db value
+ struct requirement_alternatives: strings
+ {
+ bool conditional;
+ std::string comment;
+ };
+
+ using requirements = std::vector<requirement_alternatives>;
+
+ #pragma db object pointer(std::shared_ptr) session
+ struct package
+ {
+ // Manifest data.
+ //
+ using url_type = brep::url;
+ using email_type = brep::email;
+
+ std::string name;
+ std::string summary;
+ std::string tags;
+ std::string description;
+ url_type url;
+ odb::nullable<url_type> package_url;
+ email_type email;
+ odb::nullable<email_type> package_email;
+ std::vector<odb::lazy_weak_ptr<package_version>> versions;
+
+ // Additional data.
+ //
+
+ // Database mapping.
+ //
+ #pragma db member(name) id
+ #pragma db member(versions) inverse(id.package)
+ };
+
+ #pragma db object pointer(std::shared_ptr) session
+ struct package_version
+ {
+ // Manifest data.
+ //
+ using package_type = brep::package;
+ using priority_type = brep::priority;
+ using license_alternatives_type = brep::license_alternatives;
+ using dependencies_type = brep::dependencies;
+ using requirements_type = brep::requirements;
+
+ std::string version;
+ std::shared_ptr<package_type> package;
+ priority_type priority;
+ license_alternatives_type license_alternatives;
+ std::string changes;
+ dependencies_type dependencies;
+ requirements_type requirements;
+
+ // Additional data.
+ //
+ std::string repository; // E.g., "stable", "testing".
+
+ // Database mapping.
+ //
+
+ // id
+ //
+ package_version_id
+ id () const {return package_version_id {package->name, version};}
+
+ void
+ id (const package_version_id&, odb::database&);
+
+ #pragma db member(version) transient
+ #pragma db member(package) transient
+ #pragma db member(id) virtual(package_version_id) before id \
+ get(id) set(id ((?), (!))) column("")
+
+ // license
+ //
+ using _license_key = std::pair<std::size_t, std::size_t>;
+ using _licenses_type = std::map<_license_key, std::string>;
+
+ #pragma db value(_license_key)
+ #pragma db member(_license_key::first) column("alternative")
+ #pragma db member(_license_key::second) column("index")
+
+ #pragma db member(license_alternatives) id_column("") value_column("")
+ #pragma db member(licenses) \
+ virtual(_licenses_type) \
+ after(license_alternatives) \
+ get(_get (this.license_alternatives)) \
+ set(_set (this.license_alternatives, (?))) \
+ id_column("") key_column("") value_column("license")
+
+ // dependencies
+ //
+ using _dependency_key = std::pair<std::size_t, std::size_t>;
+ using _dependency_alternatives_type =
+ std::map<_dependency_key, dependency>;
+
+ #pragma db value(_dependency_key)
+ #pragma db member(_dependency_key::first) column("dependency")
+ #pragma db member(_dependency_key::second) column("index")
+
+ #pragma db member(dependencies) id_column("") value_column("")
+ #pragma db member(dependency_alternatives) \
+ virtual(_dependency_alternatives_type) \
+ after(dependencies) \
+ get(_get (this.dependencies)) \
+ set(_set (this.dependencies, (?))) \
+ id_column("") key_column("") value_column("dep_")
+
+ // requirements
+ //
+ using _requirement_key = std::pair<std::size_t, std::size_t>;
+ using _requirement_alternatives_type =
+ std::map<_requirement_key, std::string>;
+
+ #pragma db value(_requirement_key)
+ #pragma db member(_requirement_key::first) column("requirement")
+ #pragma db member(_requirement_key::second) column("index")
+
+ #pragma db member(requirements) id_column("") value_column("")
+ #pragma db member(requirement_alternatives) \
+ virtual(_requirement_alternatives_type) \
+ after(requirements) \
+ get(_get (this.requirements)) \
+ set(_set (this.requirements, (?))) \
+ id_column("") key_column("") value_column("id")
+ };
+}
+
+// Nested container emulation support for ODB.
+//
+// Note that the outer index in the inner container should strictly
+// speaking be a foreign key pointing to the index of the outer
+// container. The only way to achieve this currently is to manually
+// add the constraint via ALTER TABLE ADD CONSTRAINT. Note, however,
+// that as long as we only modify these tables via the ODB container
+// interface, not having the foreign key (and not having ON DELETE
+// CASCADE) should be harmless (since we have a foreign key pointing
+// to the object id).
+//
+#include <map>
+#include <vector>
+#include <cstddef> // size_t
+#include <utility> // pair, declval()
+#include <cassert>
+#include <type_traits> // remove_reference
+
+namespace odb
+{
+ template <typename O>
+ struct _inner: std::remove_reference<decltype (std::declval<O> ()[0])> {};
+
+ template <typename O>
+ std::map<std::pair<std::size_t, std::size_t>, typename _inner<O>::type>
+ _get (const std::vector<O>& v)
+ {
+ using namespace std;
+
+ using I = typename _inner<O>::type;
+ using key = pair<size_t, size_t>;
+
+ map<key, I> r;
+ for (size_t n (0); n != v.size (); ++n)
+ {
+ const O& o (v[n]);
+ for (size_t m (0); m != o.size (); ++m)
+ r.emplace (key (n, m), o[m]);
+ }
+ return r;
+ }
+
+ //@@ Second argument should be && once ODB uses move().
+ //
+ template <typename I, typename O>
+ void
+ _set (std::vector<O>& v, std::map<std::pair<std::size_t, std::size_t>, I>& r)
+ {
+ using namespace std;
+
+ using key = pair<size_t, size_t>;
+
+ for (auto& p: r)
+ {
+ size_t n (p.first.first);
+ size_t m (p.first.second);
+ I& i (p.second);
+
+ assert (n < v.size ());
+ assert (m == v[n].size ());
+ v[n].push_back (std::move (i));
+ }
+ }
+}
+
+#endif // BPKG_PACKAGE
diff --git a/brep/package.cxx b/brep/package.cxx
new file mode 100644
index 0000000..9331f55
--- /dev/null
+++ b/brep/package.cxx
@@ -0,0 +1,21 @@
+// file : brep/package.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <brep/package>
+
+#include <odb/database.hxx>
+
+#include <brep/package-odb.hxx>
+
+namespace brep
+{
+ // package_version
+ //
+ void package_version::
+ id (const package_version_id& v, odb::database& db)
+ {
+ version = v.version;
+ package = db.load<package_type> (v.package);
+ }
+}
diff --git a/brep/search b/brep/search
index 9670899..078922e 100644
--- a/brep/search
+++ b/brep/search
@@ -7,6 +7,8 @@
#include <memory> // shared_ptr
+#include <odb/database.hxx>
+
#include <brep/module>
#include <brep/options>
@@ -23,6 +25,7 @@ namespace brep
private:
std::shared_ptr<search_options> options_;
+ std::shared_ptr<odb::core::database> db_;
};
}
diff --git a/brep/search.cxx b/brep/search.cxx
index 3f50383..9fc37e2 100644
--- a/brep/search.cxx
+++ b/brep/search.cxx
@@ -8,9 +8,19 @@
#include <chrono>
#include <ostream>
+#include <odb/session.hxx>
+#include <odb/database.hxx>
+#include <odb/transaction.hxx>
+
+#include <odb/pgsql/database.hxx>
+
#include <web/module>
+#include <brep/package>
+#include <brep/package-odb.hxx>
+
using namespace std;
+using namespace odb::core;
namespace brep
{
@@ -23,6 +33,12 @@ namespace brep
cli::unknown_mode::fail,
cli::unknown_mode::fail);
+ db_ = make_shared<odb::pgsql::database>("",
+ "",
+ "brep",
+ options_->db_host (),
+ options_->db_port ());
+
if (options_->results_on_page () > 30)
fail << "too many search results on page: "
<< options_->results_on_page ();
@@ -36,6 +52,60 @@ namespace brep
{
MODULE_DIAG;
+ std::shared_ptr<package> cli (make_shared<package> ());
+
+ cli->name = "cli";
+ cli->summary = "CLI is ...";
+ cli->description = "This is CLI";
+ cli->tags = "compiler, C++";
+
+ licenses l;
+ l.comment = "License\"A'";
+ l.push_back ("XXX");
+ l.push_back ("AAA");
+ l.push_back ("BBB");
+ l.push_back ("CCC");
+
+ std::shared_ptr<package_version> v (make_shared<package_version> ());
+
+ v->version = "1.1";
+ v->package = cli;
+
+ v->license_alternatives.push_back (l);
+
+ dependency_alternatives da;
+ da.push_back ({"icl", version_comparison{"1.3.3", comparison::gt}});
+ da.push_back ({"ocl", version_comparison{"1.5.5", comparison::lt}});
+
+ v->dependencies.push_back (da);
+
+ {
+ requirement_alternatives ra;
+ ra.push_back ("TAO");
+ ra.push_back ("ORBacus");
+
+ v->requirements.push_back (ra);
+ }
+
+ {
+ requirement_alternatives ra;
+ ra.push_back ("Xerces");
+
+ v->requirements.push_back (ra);
+ }
+
+ cli->versions.push_back (v);
+
+ transaction t (db_->begin ());
+// t.tracer (odb::stderr_full_tracer);
+
+ {
+ db_->persist (cli);
+ db_->persist (v);
+ }
+
+ t.commit ();
+
chrono::seconds ma (60);
rs.cookie ("Oh", " Ah\n\n", &ma, "/");
rs.cookie ("Hm", ";Yes", &ma);
diff --git a/brep/view b/brep/view
index 9b3030e..69c7d3c 100644
--- a/brep/view
+++ b/brep/view
@@ -7,6 +7,8 @@
#include <memory> // shared_ptr
+#include <odb/database.hxx>
+
#include <brep/module>
#include <brep/options>
@@ -23,6 +25,7 @@ namespace brep
private:
std::shared_ptr<view_options> options_;
+ std::shared_ptr<odb::core::database> db_;
};
}
diff --git a/brep/view.cxx b/brep/view.cxx
index 0ec6c67..48c8188 100644
--- a/brep/view.cxx
+++ b/brep/view.cxx
@@ -7,10 +7,21 @@
#include <memory> // shared_ptr, make_shared()
#include <ostream>
+#include <odb/session.hxx>
+#include <odb/database.hxx>
+#include <odb/transaction.hxx>
+
+#include <odb/pgsql/database.hxx>
+
#include <web/module>
+#include <brep/package>
+#include <brep/package-odb.hxx>
+
using namespace std;
+using namespace odb::core;
+#pragma db namespace session
namespace brep
{
void view::
@@ -19,11 +30,29 @@ namespace brep
options_ = make_shared<view_options> (s,
cli::unknown_mode::fail,
cli::unknown_mode::fail);
+
+ db_ = make_shared<odb::pgsql::database>("",
+ "",
+ "brep",
+ options_->db_host (),
+ options_->db_port ());
}
void view::
handle (request& rq, response& rs)
{
+ session s;
+ transaction t (db_->begin ());
+
+ shared_ptr<package> p (db_->load<package> ("cli"));
+
+ for (auto& vp : p->versions)
+ {
+ s.cache_insert<package_version> (*db_, vp.object_id (), vp.load ());
+ }
+
+ t.commit ();
+
ostream& o (rs.content (200, "text/html;charset=utf-8", false));
o << "<html><head></head><body>";
@@ -40,6 +69,64 @@ namespace brep
o << "<br>\n" << c.name << "=" << c.value;
}
+ o << "<p>\n" << p->name << ": " << p->versions.size ();
+
+ for (const auto& vp : p->versions)
+ {
+ shared_ptr<package_version> v (
+ s.cache_find<package_version> (*db_, vp.object_id ()));
+
+ if (!v)
+ {
+ o << "<br>no version in cache !";
+ }
+ else
+ {
+ o << "<br>licenses:" << v->license_alternatives.size ();
+
+ for (const auto& la : v->license_alternatives)
+ {
+ o << "<br>";
+
+ for (const auto& l : la)
+ {
+ o << " |" << l << "|";
+ }
+ }
+
+ o << "<br>deps:" << v->dependencies.size ();
+
+ for (const auto& da : v->dependencies)
+ {
+ o << "<br>";
+
+ for (const auto& d : da)
+ {
+ o << " |" << d.package;
+
+ if (!d.version.null ())
+ {
+ o << "," << d.version->value << ","
+ << static_cast<int> (d.version->operation) << "|";
+ }
+ }
+ }
+
+ o << "<br>requirements:" << v->requirements.size ();
+
+ for (const auto& ra : v->requirements)
+ {
+ o << "<br>";
+
+ for (const auto& r : ra)
+ {
+ o << " |" << r << "|";
+ }
+ }
+ }
+
+ }
+
o << "<p><a href='search?a=1&b&c=2&d=&&x=a+b'>Search</a>"
<< "</body></html>";
}
diff --git a/build.sh b/build.sh
index 2a39f48..ef4e11a 100755
--- a/build.sh
+++ b/build.sh
@@ -3,5 +3,8 @@ DEBUG="-g -ggdb -fno-inline"
cd ./brep; cli --generate-file-scanner --suppress-usage --hxx-suffix "" \
--option-prefix "" ./options.cli; cd ..
+cd ./brep; odb -d pgsql --std c++11 --generate-query --generate-schema \
+ package; cd ..
+
g++ -shared $DEBUG -std=c++11 -I. -I/usr/include/apr-1 \
- -fPIC -o libbrep.so `find . -name '*.cxx'`
+ -fPIC -o libbrep.so `find . -name '*.cxx'` -lodb-pgsql -lodb
diff --git a/build/root.build b/build/root.build
index d9c5766..bfa96d0 100644
--- a/build/root.build
+++ b/build/root.build
@@ -2,3 +2,4 @@ using cxx
cxx.std = 11
cxx.poptions += -I$src_root -I/usr/include/apr-1
+cxx.libs = -lodb-pgsql -lodb
diff --git a/buildfile b/buildfile
index 6180ebf..21ed86f 100644
--- a/buildfile
+++ b/buildfile
@@ -1,4 +1,4 @@
-brep=brep/{diagnostics module options search view}
+brep=brep/{diagnostics module options package package-odb search view}
web=web/apache/{request service}
libso{brep}: cxx{$brep $web services}
diff --git a/etc/config b/etc/config
index a1e851c..31a03a2 100644
--- a/etc/config
+++ b/etc/config
@@ -6,17 +6,17 @@ WORKSPACE_DIR="$PROJECT_DIR/var"
# PostgreSQL settings (used in pgctl)
PG_PORT=8432
+PG_SCHEMA_DIR="$PROJECT_DIR/brep"
PG_DATA_DIR="$WORKSPACE_DIR/lib/pgsql"
-PG_SOCKET_DIR="$WORKSPACE_DIR/run/pgsql"
PG_LOG_DIR="$WORKSPACE_DIR/log/pgsql"
-PG_OUT_FILE="$WORKSPACE_DIR/run/pgsql/out"
+PG_WORKSPACE_DIR="$WORKSPACE_DIR/run/pgsql"
# Apache settings (used in apachectl)
AP_PORT=8080
AP_SERVER_NAME="cppget.org:$AP_PORT"
AP_ADMIN_EMAIL=admin@cppget.org
AP_LOG_LEVEL=trace1
-AP_DB_HOST="$PG_SOCKET_DIR"
+AP_DB_HOST="$PG_WORKSPACE_DIR"
AP_DB_PORT=$PG_PORT
AP_MODULE_DIR="$PROJECT_DIR"
AP_WWW_DIR="$PROJECT_DIR/www"
diff --git a/etc/pgctl b/etc/pgctl
index 26ad888..4331ca1 100755
--- a/etc/pgctl
+++ b/etc/pgctl
@@ -7,11 +7,13 @@
. `dirname $0`/config
-cmd="$1"
+CMD="$1"
+SOCKET_DIR="$PG_WORKSPACE_DIR"
+OUT_FILE="$PG_WORKSPACE_DIR/out"
# Print usage description and exit.
#
-case $cmd in
+case $CMD in
init|start|stop|status|connect) ;;
*)
echo "Usage: pgctl (init|start|stop|status|connect)"
@@ -21,10 +23,10 @@ esac
ERROR=0
-# Initilization includes creating PostgreSQL DB cluster, creating and
-# populating brep DB.
+# Initialization includes creating PostgreSQL DB cluster, creating brep DB
+# and schema.
#
-if test "$cmd" = "init"; then
+if test "$CMD" = "init"; then
if test -d "$PG_DATA_DIR"; then
echo "PostgreSQL DB cluster directory $PG_DATA_DIR already exist"
else
@@ -41,7 +43,7 @@ if test "$cmd" = "init"; then
fi
fi
-case $cmd in
+case $CMD in
start|init)
# Start DB server if not running yet.
#
@@ -57,21 +59,21 @@ case $cmd in
echo "PostgreSQL server starting ..."
- mkdir -p `dirname $PG_OUT_FILE`
+ mkdir -p `dirname $OUT_FILE`
mkdir -p "$PG_LOG_DIR"
- mkdir -p "$PG_SOCKET_DIR"
+ mkdir -p "$SOCKET_DIR"
pg_ctl start -D "$PG_DATA_DIR" -w -o \
- "-c port=$PG_PORT -c unix_socket_directories=$PG_SOCKET_DIR \
+ "-c port=$PG_PORT -c unix_socket_directories=$SOCKET_DIR \
-c logging_collector=on -c log_directory=$PG_LOG_DIR" \
- 1>"$PG_OUT_FILE" 2>&1
+ 1>"$OUT_FILE" 2>&1
ERROR=$?
if test $ERROR -eq 0; then
echo "server started"
else
- cat "$PG_OUT_FILE" 1>&2
+ cat "$OUT_FILE" 1>&2
echo "server starting failed"
exit $ERROR
fi
@@ -104,15 +106,14 @@ case $cmd in
connect)
echo "connecting to PostgreSQL server ..."
- psql --host=$PG_SOCKET_DIR --port=$PG_PORT brep
+ psql --host=$SOCKET_DIR --port=$PG_PORT brep
;;
esac
-if test "$cmd" = "init"; then
+if test "$CMD" = "init"; then
# Create brep DB if not exist.
#
- psql --host=$PG_SOCKET_DIR --port=$PG_PORT -c "" brep \
- 1>>"$PG_OUT_FILE" 2>&1
+ psql --host=$SOCKET_DIR --port=$PG_PORT -c "" brep 1>/dev/null 2>&1
ERROR=$?
@@ -121,7 +122,7 @@ if test "$cmd" = "init"; then
else
if test $ERROR -eq 2; then
echo "creating brep DB ..."
- createdb --host=$PG_SOCKET_DIR --port=$PG_PORT brep
+ createdb --host=$SOCKET_DIR --port=$PG_PORT brep
ERROR=$?
if test $ERROR -eq 0; then
@@ -136,8 +137,29 @@ if test "$cmd" = "init"; then
fi
fi
- # Populate brep DB if required.
- # psql --host=$PG_SOCKET_DIR --port=$PG_PORT -c "select count(1) ..." brep \
- # 1>>"$PG_OUT_FILE" 2>&1
- # ...
+ # Create brep DB schema if not exist.
+ #
+ psql --host=$SOCKET_DIR --port=$PG_PORT -c "select count(1) from package" \
+ brep 1>/dev/null 2>&1
+
+ ERROR=$?
+
+ if test $ERROR -eq 0; then
+ echo "brep DB schema already exist"
+ else
+ echo "creating brep DB schema ..."
+
+ psql -v ON_ERROR_STOP=1 --host=$SOCKET_DIR --port=$PG_PORT \
+ --file="$PG_SCHEMA_DIR/package.sql" brep 1>"$OUT_FILE" 2>&1
+
+ ERROR=$?
+
+ if test $ERROR -eq 0; then
+ echo "brep DB schema created"
+ else
+ cat "$OUT_FILE" 1>&2
+ echo "brep DB schema creating failed"
+ exit $ERROR;
+ fi
+ fi
fi
diff --git a/www/htdocs/index.html b/www/htdocs/index.html
index 3d6d51e..d8c1185 100644
--- a/www/htdocs/index.html
+++ b/www/htdocs/index.html
@@ -1,5 +1,31 @@
+<!DOCTYPE html>
<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1"/>
+ <style type="text/css">
+body {
+ font-size : 1.1em;
+ line-height : 1.4em;
+
+ text-align: justify;
+
+
+ /* 320px ~ 20em @ 1 font-size. This is factored in when doing font
+ boosting. Specifying 320px directly seems to mess it up. */
+ min-width: 17em;
+ max-width: 40em;
+}
+ </style>
+ </head>
<body>
- <b>Home Page</b>
+ <p>Home Page</p>
+ build2 is a build system aimed at improving cross-platform C++ software building and library use. It will be accompanied by a C++ package manager and a central repository of open source C++ libraries.
+ build2 is a build system aimed build2 is a build system aimed at improving cross-platform C++ software building and library use. It will be accompanied by a C++ package manager and a central repository of open source C++ libraries.
+ build2 is a build system aimed at improving cross-platform C++ at improving cross-platform C++ at improving cross-platform C++ software building and library use. It will be accompanied by a C++ package manager and a central repository of open source C++ libraries.
+ build2 is a build system aimed at ddw improving cross-platform C++ software building and library use. It will be accompanied by a C++ package manager and a central repository of open source C++ libraries.
+ build2 is a build system aimed at improving cross-platform C++ software building and library use. It will be accompanied by a C++ package manager and a central repository of open source C++ libraries.
+ build2 is a build system aimed at improving cross-platform C++ software building and library use. It will be accompanied by a C++ package manager and a central repository of open source C++ libraries.
+ build2 is a build sdhjsd system aimed at improving cross-platform C++ software building and library use. It will be accompanied by a C++ package manager and a central repository of open source C++ libraries.
+ build2 is a build system aimed at rkdf improving cross-platform C++ software building and library use. It will be accompanied by a C++ package manager and a central repository of open source C++ libraries.
</body>
</html>