sqlite3::exec(new_dep_st, | sqlite3::exec(new_dep_st, | ||||
std::forward_as_tuple(db_pkg_id, | std::forward_as_tuple(db_pkg_id, | ||||
dep.name, | dep.name, | ||||
dep.version.to_string(), | |||||
"[placeholder]")); | |||||
dep.version_range.low().to_string(), | |||||
dep.version_range.high().to_string())); | |||||
} | } | ||||
} | } | ||||
assert(git_url); | assert(git_url); | ||||
assert(git_ref); | 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; | |||||
auto deps = dependencies_of(pk_id); | |||||
return package_info{ | return package_info{ | ||||
pk_id, | pk_id, | ||||
deps, | |||||
std::move(deps), | |||||
git_remote_listing{ | git_remote_listing{ | ||||
*git_url, | *git_url, | ||||
*git_ref, | *git_ref, | ||||
std::vector<dependency> catalog::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>( // | std::string>( // | ||||
_stmt_cache, | _stmt_cache, | ||||
R"( | R"( | ||||
FROM dds_cat_pkgs | FROM dds_cat_pkgs | ||||
WHERE name = ? AND version = ? | WHERE name = ? AND version = ? | ||||
) | ) | ||||
SELECT dep_name, low | |||||
SELECT dep_name, low, high | |||||
FROM dds_cat_pkg_deps | FROM dds_cat_pkg_deps | ||||
WHERE pkg_id IN this_pkg_id | WHERE pkg_id IN this_pkg_id | ||||
ORDER BY dep_name | ORDER BY dep_name | ||||
)"_sql, | )"_sql, | ||||
std::forward_as_tuple(pkg.name, pkg.version.to_string())) // | std::forward_as_tuple(pkg.name, pkg.version.to_string())) // | ||||
| ranges::views::transform([](auto&& pair) { | | ranges::views::transform([](auto&& pair) { | ||||
auto& [name, ver] = pair; | |||||
return dependency{name, semver::version::parse(ver)}; | |||||
auto& [name, low, high] = pair; | |||||
return dependency{name, | |||||
semver::range(semver::version::parse(low), | |||||
semver::version::parse(high))}; | |||||
}) // | }) // | ||||
| ranges::to_vector; | | ranges::to_vector; | ||||
} | } | ||||
dep_name)); | dep_name)); | ||||
info.deps.push_back({ | info.deps.push_back({ | ||||
std::string(dep_name), | std::string(dep_name), | ||||
semver::version::parse(std::string(dep_version)), | |||||
semver::range::parse(std::string(dep_version)), | |||||
}); | }); | ||||
} | } | ||||
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")}, | ||||
{ | { | ||||
{"bar", semver::version::parse("1.2.5")}, | |||||
{"baz", semver::version::parse("5.3.2")}, | |||||
{"bar", semver::range::parse("=1.2.5")}, | |||||
{"baz", semver::range::parse("^5.3.2")}, | |||||
}, | }, | ||||
dds::git_remote_listing{"http://example.com", "master", std::nullopt}, | dds::git_remote_listing{"http://example.com", "master", std::nullopt}, | ||||
}); | }); | ||||
"foo": { | "foo": { | ||||
"1.2.3": { | "1.2.3": { | ||||
"depends": { | "depends": { | ||||
"bar": "4.2.1" | |||||
"bar": "~4.2.1" | |||||
}, | }, | ||||
"git": { | "git": { | ||||
"url": "http://example.com", | "url": "http://example.com", | ||||
auto deps = db.dependencies_of(pkgs[0]); | auto deps = db.dependencies_of(pkgs[0]); | ||||
REQUIRE(deps.size() == 1); | REQUIRE(deps.size() == 1); | ||||
CHECK(deps[0].name == "bar"); | CHECK(deps[0].name == "bar"); | ||||
CHECK(deps[0].version == semver::version::parse("4.2.1")); | |||||
CHECK(deps[0].version_range == semver::range::parse("~4.2.1")); | |||||
} | } |
std::vector<dds::dependency> deps; | std::vector<dds::dependency> deps; | ||||
for (const auto& dep : this->deps.Get()) { | for (const auto& dep : this->deps.Get()) { | ||||
auto dep_id = dds::package_id::parse(dep); | auto dep_id = dds::package_id::parse(dep); | ||||
deps.push_back({dep_id.name, dep_id.version}); | |||||
assert(false && "TODO"); | |||||
// deps.push_back({dep_id.name, dep_id.version}); | |||||
} | } | ||||
dds::package_info info{ident, std::move(deps), {}}; | dds::package_info info{ident, std::move(deps), {}}; | ||||
int run() { | int run() { | ||||
const auto man = parent.load_package_manifest(); | const auto man = parent.load_package_manifest(); | ||||
for (const auto& dep : man.dependencies) { | for (const auto& dep : man.dependencies) { | ||||
std::cout << dep.name << " " << dep.version.to_string() << '\n'; | |||||
std::cout << dep.name << " " << dep.version_range.to_string() << '\n'; | |||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
dds::repo_flags::write_lock | dds::repo_flags::create_if_absent, | dds::repo_flags::write_lock | dds::repo_flags::create_if_absent, | ||||
[&](dds::repository repo) { | [&](dds::repository repo) { | ||||
for (auto& dep : man.dependencies) { | for (auto& dep : man.dependencies) { | ||||
auto exists = !!repo.find(dep.name, dep.version); | |||||
if (!exists) { | |||||
spdlog::info("Pull remote: {}@{}", dep.name, dep.version.to_string()); | |||||
auto opt_pkg = catalog.get(dds::package_id{dep.name, dep.version}); | |||||
if (opt_pkg) { | |||||
auto tsd = dds::get_package_sdist(*opt_pkg); | |||||
repo.add_sdist(tsd.sdist, dds::if_exists::ignore); | |||||
} else { | |||||
spdlog::error("No remote listing for {}@{}", | |||||
dep.name, | |||||
dep.version.to_string()); | |||||
failed = true; | |||||
} | |||||
} else { | |||||
spdlog::info("Okay: {} {}", dep.name, dep.version.to_string()); | |||||
} | |||||
assert(false && "Not ready yet"); | |||||
// auto exists = !!repo.find(dep.name, dep.version_range); | |||||
// if (!exists) { | |||||
// spdlog::info("Pull remote: {}@{}", dep.name, | |||||
// dep.version_range.to_string()); auto opt_pkg = | |||||
// catalog.get(dds::package_id{dep.name, dep.version_range}); if | |||||
// (opt_pkg) { | |||||
// auto tsd = dds::get_package_sdist(*opt_pkg); | |||||
// repo.add_sdist(tsd.sdist, dds::if_exists::ignore); | |||||
// } else { | |||||
// spdlog::error("No remote listing for {}@{}", | |||||
// dep.name, | |||||
// dep.version_range.to_string()); | |||||
// failed = true; | |||||
// } | |||||
// } else { | |||||
// spdlog::info("Okay: {} {}", dep.name, dep.version_range.to_string()); | |||||
// } | |||||
} | } | ||||
}); | }); | ||||
if (failed) { | if (failed) { |
auto name = trim_view(std::string_view(str_begin, str_iter - str_begin)); | auto name = trim_view(std::string_view(str_begin, str_iter - str_begin)); | ||||
auto version_str = trim_view(std::string_view(str_iter, str_end - str_iter)); | auto version_str = trim_view(std::string_view(str_iter, str_end - str_iter)); | ||||
semver::version version; | |||||
try { | try { | ||||
version = semver::version::parse(version_str); | |||||
} catch (const semver::invalid_version&) { | |||||
throw std::runtime_error( | |||||
fmt::format("Invalid version string '{}' in dependency declaration '{}' (Should be a " | |||||
"semver string. See https://semver.org/ for info)", | |||||
version_str, | |||||
str)); | |||||
auto rng = semver::range::parse_restricted(version_str); | |||||
return dependency{std::string(name), rng}; | |||||
} catch (const semver::invalid_range&) { | |||||
throw std::runtime_error(fmt::format( | |||||
"Invalid version range string '{}' in dependency declaration '{}' (Should be a " | |||||
"semver range string. See https://semver.org/ for info)", | |||||
version_str, | |||||
str)); | |||||
} | } | ||||
return dependency{std::string(name), version}; | |||||
} | } | ||||
std::vector<sdist> dds::find_dependencies(const repository& repo, const dependency& dep) { | std::vector<sdist> dds::find_dependencies(const repository& repo, const dependency& dep) { | ||||
} | } | ||||
void detail::do_find_deps(const repository& repo, const dependency& dep, std::vector<sdist>& sd) { | void detail::do_find_deps(const repository& repo, const dependency& dep, std::vector<sdist>& sd) { | ||||
auto sdist_opt = repo.find(dep.name, dep.version); | |||||
auto sdist_opt = repo.find(dep.name, dep.version_range.low()); | |||||
if (!sdist_opt) { | if (!sdist_opt) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
fmt::format("Unable to find dependency to satisfy requirement: {} {}", | fmt::format("Unable to find dependency to satisfy requirement: {} {}", | ||||
dep.name, | dep.name, | ||||
dep.version.to_string())); | |||||
dep.version_range.to_string())); | |||||
} | } | ||||
const sdist& new_sd = *sdist_opt; | const sdist& new_sd = *sdist_opt; | ||||
for (const auto& inner_dep : new_sd.manifest.dependencies) { | for (const auto& inner_dep : new_sd.manifest.dependencies) { |
#include <dds/build/plan/full.hpp> | #include <dds/build/plan/full.hpp> | ||||
#include <semver/range.hpp> | |||||
#include <semver/version.hpp> | #include <semver/version.hpp> | ||||
#include <string_view> | #include <string_view> | ||||
}; | }; | ||||
struct dependency { | struct dependency { | ||||
std::string name; | |||||
semver::version version; | |||||
std::string name; | |||||
semver::range version_range; | |||||
static dependency parse_depends_string(std::string_view str); | static dependency parse_depends_string(std::string_view str); | ||||
}; | }; |