#include "./repodb.hpp" | |||||
#include "./catalog.hpp" | |||||
#include <neo/sqlite3/exec.hpp> | #include <neo/sqlite3/exec.hpp> | ||||
#include <neo/sqlite3/iter_tuples.hpp> | #include <neo/sqlite3/iter_tuples.hpp> | ||||
} // namespace | } // namespace | ||||
repo_database repo_database::open(const std::string& db_path) { | |||||
catalog catalog::open(const std::string& db_path) { | |||||
auto db = sqlite3::database::open(db_path); | auto db = sqlite3::database::open(db_path); | ||||
try { | try { | ||||
ensure_migrated(db); | ensure_migrated(db); | ||||
e.what()); | e.what()); | ||||
throw; | throw; | ||||
} | } | ||||
return repo_database(std::move(db)); | |||||
return catalog(std::move(db)); | |||||
} | } | ||||
repo_database::repo_database(sqlite3::database db) | |||||
catalog::catalog(sqlite3::database db) | |||||
: _db(std::move(db)) {} | : _db(std::move(db)) {} | ||||
void repo_database::_store_pkg(const package_info& pkg, const git_remote_listing& git) { | |||||
void catalog::_store_pkg(const package_info& pkg, const git_remote_listing& git) { | |||||
auto lm_usage = git.auto_lib.value_or(lm::usage{}); | auto lm_usage = git.auto_lib.value_or(lm::usage{}); | ||||
sqlite3::exec( // | sqlite3::exec( // | ||||
_stmt_cache, | _stmt_cache, | ||||
lm_usage.namespace_)); | lm_usage.namespace_)); | ||||
} | } | ||||
void repo_database::store(const package_info& pkg) { | |||||
void catalog::store(const package_info& pkg) { | |||||
sqlite3::transaction_guard tr{_db}; | sqlite3::transaction_guard tr{_db}; | ||||
std::visit([&](auto&& remote) { _store_pkg(pkg, remote); }, pkg.remote); | std::visit([&](auto&& remote) { _store_pkg(pkg, remote); }, pkg.remote); | ||||
} | } | ||||
} | } | ||||
std::vector<package_id> repo_database::by_name(std::string_view sv) const noexcept { | |||||
std::vector<package_id> catalog::by_name(std::string_view sv) const noexcept { | |||||
return sqlite3::exec_iter<std::string, std::string>( // | return sqlite3::exec_iter<std::string, std::string>( // | ||||
_stmt_cache, | _stmt_cache, | ||||
R"( | R"( | ||||
| ranges::to_vector; | | ranges::to_vector; | ||||
} | } | ||||
std::vector<dependency> repo_database::dependencies_of(const package_id& pkg) const noexcept { | |||||
std::vector<dependency> catalog::dependencies_of(const package_id& pkg) const noexcept { | |||||
return sqlite3::exec_iter<std::string, | return sqlite3::exec_iter<std::string, | ||||
std::string>( // | std::string>( // | ||||
_stmt_cache, | _stmt_cache, | ||||
} // namespace | } // namespace | ||||
void repo_database::import_json_str(std::string_view content) { | |||||
void catalog::import_json_str(std::string_view content) { | |||||
using nlohmann::json; | using nlohmann::json; | ||||
auto root = json::parse(content); | auto root = json::parse(content); |
std::variant<git_remote_listing> remote; | std::variant<git_remote_listing> remote; | ||||
}; | }; | ||||
class repo_database { | |||||
class catalog { | |||||
neo::sqlite3::database _db; | neo::sqlite3::database _db; | ||||
mutable neo::sqlite3::statement_cache _stmt_cache{_db}; | mutable neo::sqlite3::statement_cache _stmt_cache{_db}; | ||||
explicit repo_database(neo::sqlite3::database db); | |||||
repo_database(const repo_database&) = delete; | |||||
explicit catalog(neo::sqlite3::database db); | |||||
catalog(const catalog&) = delete; | |||||
void _store_pkg(const package_info&, const git_remote_listing&); | void _store_pkg(const package_info&, const git_remote_listing&); | ||||
public: | public: | ||||
repo_database(repo_database&&) = default; | |||||
repo_database& operator=(repo_database&&) = default; | |||||
catalog(catalog&&) = default; | |||||
catalog& operator=(catalog&&) = default; | |||||
static repo_database open(const std::string& db_path); | |||||
static repo_database open(path_ref db_path) { return open(db_path.string()); } | |||||
static catalog open(const std::string& db_path); | |||||
static catalog open(path_ref db_path) { return open(db_path.string()); } | |||||
void store(const package_info& info); | void store(const package_info& info); | ||||
#include <dds/repo/repodb.hpp> | |||||
#include <dds/repo/catalog.hpp> | |||||
#include <catch2/catch.hpp> | #include <catch2/catch.hpp> | ||||
TEST_CASE("Create a simple database") { | TEST_CASE("Create a simple database") { | ||||
// Just create and run migrations on an in-memory database | // Just create and run migrations on an in-memory database | ||||
auto repo = dds::repo_database::open(":memory:"s); | |||||
auto repo = dds::catalog::open(":memory:"s); | |||||
} | } | ||||
class repo_test_case { | |||||
class catalog_test_case { | |||||
public: | public: | ||||
dds::repo_database db = dds::repo_database::open(":memory:"s); | |||||
dds::catalog db = dds::catalog::open(":memory:"s); | |||||
}; | }; | ||||
TEST_CASE_METHOD(repo_test_case, "Store a simple package") { | |||||
TEST_CASE_METHOD(catalog_test_case, "Store a simple package") { | |||||
db.store(dds::package_info{ | db.store(dds::package_info{ | ||||
dds::package_id("foo", semver::version::parse("1.2.3")), | dds::package_id("foo", semver::version::parse("1.2.3")), | ||||
{}, | {}, | ||||
REQUIRE(pkgs.size() == 1); | REQUIRE(pkgs.size() == 1); | ||||
} | } | ||||
TEST_CASE_METHOD(repo_test_case, "Package requirements") { | |||||
TEST_CASE_METHOD(catalog_test_case, "Package requirements") { | |||||
db.store(dds::package_info{ | db.store(dds::package_info{ | ||||
dds::package_id{"foo", semver::version::parse("1.2.3")}, | dds::package_id{"foo", semver::version::parse("1.2.3")}, | ||||
{ | { | ||||
CHECK(deps[1].name == "baz"); | CHECK(deps[1].name == "baz"); | ||||
} | } | ||||
TEST_CASE_METHOD(repo_test_case, "Parse JSON repo") { | |||||
TEST_CASE_METHOD(catalog_test_case, "Parse JSON repo") { | |||||
db.import_json_str(R"({ | db.import_json_str(R"({ | ||||
"version": 1, | "version": 1, | ||||
"packages": { | "packages": { |