} | } | ||||
} | } | ||||
std::optional<package_info> catalog::get(const package_id& pk_id) const noexcept { | |||||
auto& st = _stmt_cache(R"( | |||||
SELECT | |||||
pkg_id, | |||||
name, | |||||
version, | |||||
git_url, | |||||
git_ref, | |||||
lm_name, | |||||
lm_namespace | |||||
FROM dds_cat_pkgs | |||||
WHERE name = ? AND version = ? | |||||
)"_sql); | |||||
st.reset(); | |||||
st.bindings = std::forward_as_tuple(pk_id.name, pk_id.version.to_string()); | |||||
auto opt_tup = sqlite3::unpack_single_opt<std::int64_t, | |||||
std::string, | |||||
std::string, | |||||
std::optional<std::string>, | |||||
std::optional<std::string>, | |||||
std::optional<std::string>, | |||||
std::optional<std::string>>(st); | |||||
if (!opt_tup) { | |||||
return std::nullopt; | |||||
} | |||||
const auto& [pkg_id, name, version, git_url, git_ref, lm_name, lm_namespace] = *opt_tup; | |||||
assert(pk_id.name == name); | |||||
assert(pk_id.version == semver::version::parse(version)); | |||||
assert(git_url); | |||||
assert(git_ref); | |||||
auto deps = sqlite3::exec_iter<std::string, std::string>( // | |||||
_stmt_cache, | |||||
R"( | |||||
SELECT dep_name, low | |||||
FROM dds_cat_pkg_deps | |||||
WHERE pkg_id = ? | |||||
)"_sql, | |||||
std::tie(pkg_id)) | |||||
| ranges::views::transform([](auto&& pair) { | |||||
const auto& [name, ver] = pair; | |||||
return dependency{name, semver::version::parse(ver)}; | |||||
}) // | |||||
| ranges::to_vector; | |||||
return package_info{ | |||||
pk_id, | |||||
deps, | |||||
git_remote_listing{ | |||||
*git_url, | |||||
*git_ref, | |||||
lm_name ? std::make_optional(lm::usage{*lm_name, *lm_namespace}) : std::nullopt, | |||||
}, | |||||
}; | |||||
} | |||||
std::vector<package_id> catalog::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, |
#include <dds/package_id.hpp> | #include <dds/package_id.hpp> | ||||
#include <dds/repo/remote.hpp> | #include <dds/repo/remote.hpp> | ||||
#include <dds/util/fs.hpp> | #include <dds/util/fs.hpp> | ||||
#include <dds/catalog/git.hpp> | |||||
#include <neo/sqlite3/database.hpp> | #include <neo/sqlite3/database.hpp> | ||||
#include <neo/sqlite3/statement.hpp> | #include <neo/sqlite3/statement.hpp> | ||||
static catalog open(path_ref db_path) { return open(db_path.string()); } | static catalog open(path_ref db_path) { return open(db_path.string()); } | ||||
void store(const package_info& info); | void store(const package_info& info); | ||||
std::optional<package_info> get(const package_id& id) const noexcept; | |||||
std::vector<package_id> by_name(std::string_view sv) const noexcept; | std::vector<package_id> by_name(std::string_view sv) const noexcept; | ||||
std::vector<dependency> dependencies_of(const package_id& pkg) const noexcept; | std::vector<dependency> dependencies_of(const package_id& pkg) const noexcept; |
#include "./get.hpp" | |||||
#include <dds/catalog/catalog.hpp> | |||||
#include <dds/proc.hpp> | |||||
#include <spdlog/spdlog.h> | |||||
using namespace dds; | |||||
namespace { | |||||
temporary_sdist do_pull_sdist(const package_info& listing, const git_remote_listing& git) { | |||||
auto tmpdir = dds::temporary_dir::create(); | |||||
using namespace std::literals; | |||||
spdlog::info("Cloning Git repository: {} [{}] ...", git.url, git.ref); | |||||
auto command = {"git"s, | |||||
"clone"s, | |||||
"--depth=1"s, | |||||
"--branch"s, | |||||
git.ref, | |||||
git.url, | |||||
tmpdir.path().generic_string()}; | |||||
auto git_res = run_proc(command); | |||||
if (!git_res.okay()) { | |||||
throw std::runtime_error( | |||||
fmt::format("Git clone operation failed [Git command: {}] [Exitted {}]:\n{}", | |||||
quote_command(command), | |||||
git_res.retc, | |||||
git_res.output)); | |||||
} | |||||
spdlog::info("Create sdist from clone ..."); | |||||
if (git.auto_lib.has_value()) { | |||||
spdlog::info("Generating library data automatically"); | |||||
auto pkg_strm = dds::open(tmpdir.path() / "package.dds", std::ios::binary | std::ios::out); | |||||
pkg_strm << "Name: " << listing.ident.name << '\n' // | |||||
<< "Version: " << listing.ident.version.to_string() << '\n' // | |||||
<< "Namespace: " << git.auto_lib->namespace_; | |||||
auto lib_strm = dds::open(tmpdir.path() / "library.dds", std::ios::binary | std::ios::out); | |||||
lib_strm << "Name: " << git.auto_lib->name; | |||||
} | |||||
sdist_params params; | |||||
params.project_dir = tmpdir.path(); | |||||
auto sd_tmp_dir = dds::temporary_dir::create(); | |||||
params.dest_path = sd_tmp_dir.path(); | |||||
params.force = true; | |||||
auto sd = create_sdist(params); | |||||
return {sd_tmp_dir, sd}; | |||||
} | |||||
} // namespace | |||||
temporary_sdist dds::get_package_sdist(const package_info& pkg) { | |||||
auto tsd = std::visit([&](auto&& remote) { return do_pull_sdist(pkg, remote); }, pkg.remote); | |||||
if (!(tsd.sdist.manifest.pk_id == pkg.ident)) { | |||||
throw std::runtime_error(fmt::format( | |||||
"The package name@version in the generated sdist does not match the name listed in " | |||||
"the remote listing file (expected '{}', but got '{}')", | |||||
pkg.ident.to_string(), | |||||
tsd.sdist.manifest.pk_id.to_string())); | |||||
} | |||||
return tsd; | |||||
} |
#pragma once | |||||
#include <dds/sdist.hpp> | |||||
#include <dds/temp.hpp> | |||||
namespace dds { | |||||
struct package_info; | |||||
struct temporary_sdist { | |||||
temporary_dir tmpdir; | |||||
dds::sdist sdist; | |||||
}; | |||||
temporary_sdist get_package_sdist(const package_info&); | |||||
} // namespace dds |
#pragma once | |||||
#include <dds/util/fs.hpp> | |||||
#include <libman/package.hpp> | |||||
#include <optional> | |||||
#include <string> | |||||
namespace dds { | |||||
struct git_remote_listing { | |||||
std::string url; | |||||
std::string ref; | |||||
std::optional<lm::usage> auto_lib; | |||||
void clone(path_ref path) const; | |||||
}; | |||||
} // namespace dds |
#include <dds/build.hpp> | #include <dds/build.hpp> | ||||
#include <dds/catalog/catalog.hpp> | #include <dds/catalog/catalog.hpp> | ||||
#include <dds/catalog/get.hpp> | |||||
#include <dds/repo/remote.hpp> | #include <dds/repo/remote.hpp> | ||||
#include <dds/repo/repo.hpp> | #include <dds/repo/repo.hpp> | ||||
#include <dds/sdist.hpp> | #include <dds/sdist.hpp> | ||||
"requirement", | "requirement", | ||||
"The package IDs to obtain"}; | "The package IDs to obtain"}; | ||||
int run() { return 23; } | |||||
int run() { | |||||
auto cat = dds::catalog::open(path.Get()); | |||||
for (const auto& req : requirements.Get()) { | |||||
auto id = dds::package_id::parse(req); | |||||
auto info = cat.get(id); | |||||
if (!info) { | |||||
throw std::runtime_error( | |||||
fmt::format("No package in the catalog matched the given ID")); | |||||
} | |||||
dds::get_package_sdist(*info); | |||||
} | |||||
return 0; | |||||
} | |||||
} get{*this}; | } get{*this}; | ||||
int run() { | int run() { |
#include <dds/sdist.hpp> | #include <dds/sdist.hpp> | ||||
#include <dds/temp.hpp> | #include <dds/temp.hpp> | ||||
#include <dds/catalog/git.hpp> | |||||
#include <dds/catalog/get.hpp> | |||||
#include <libman/library.hpp> | #include <libman/library.hpp> | ||||
#include <semver/version.hpp> | #include <semver/version.hpp> | ||||
namespace dds { | namespace dds { | ||||
struct temporary_sdist { | |||||
temporary_dir tmpdir; | |||||
dds::sdist sdist; | |||||
}; | |||||
struct git_remote_listing { | |||||
std::string url; | |||||
std::string ref; | |||||
std::optional<lm::usage> auto_lib; | |||||
void clone(path_ref path) const; | |||||
}; | |||||
struct remote_listing { | struct remote_listing { | ||||
package_id pk_id; | package_id pk_id; | ||||
std::variant<git_remote_listing> remote; | std::variant<git_remote_listing> remote; |
import json | |||||
from tests import dds, DDS | |||||
from tests.fileutil import ensure_dir | |||||
def test_get(dds: DDS): | |||||
dds.scope.enter_context(ensure_dir(dds.build_dir)) | |||||
cat_path = dds.build_dir / 'catalog.db' | |||||
dds.catalog_create(cat_path) | |||||
json_path = dds.build_dir / 'catalog.json' | |||||
import_data = { | |||||
'version': 1, | |||||
'packages': { | |||||
'neo-sqlite3': { | |||||
'0.2.2': { | |||||
'depends': {}, | |||||
'git': { | |||||
'url': 'https://github.com/vector-of-bool/neo-sqlite3.git', | |||||
'ref': '0.2.2', | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
} | |||||
dds.scope.enter_context( | |||||
dds.set_contents(json_path, | |||||
json.dumps(import_data).encode())) | |||||
dds.catalog_import(cat_path, json_path) | |||||
dds.catalog_get(cat_path, 'neo-sqlite3@0.2.2') |