[M5+] wire resolver::discover into cargoxx add
This commit is contained in:
@@ -4,11 +4,63 @@ import std;
|
||||
import cargoxx.util;
|
||||
import cargoxx.manifest;
|
||||
import cargoxx.linkdb;
|
||||
import cargoxx.resolver;
|
||||
|
||||
namespace cargoxx::cli {
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace {
|
||||
|
||||
// Returns true when the linkdb already has a recipe for this package (so
|
||||
// no discovery is needed), false when the lookup yielded
|
||||
// LinkdbUnknownPackage and we should fall through to auto-resolution.
|
||||
// Other errors (e.g. ComponentNotSupported) propagate unchanged.
|
||||
auto recipe_already_known(const std::string& name, const std::string& version,
|
||||
const std::vector<std::string>& components,
|
||||
const fs::path& overlay_path) -> util::Result<bool> {
|
||||
auto db = linkdb::Database::open(overlay_path);
|
||||
if (!db) {
|
||||
return std::unexpected(db.error());
|
||||
}
|
||||
auto check = db->resolve(name, version, components);
|
||||
if (check) {
|
||||
return true;
|
||||
}
|
||||
if (check.error().code != util::ErrorCode::LinkdbUnknownPackage) {
|
||||
return std::unexpected(check.error());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Drives the resolver chain (Conan → vcpkg → nix-cmake-scan), running a
|
||||
// real `cmd_build` against each candidate via verify_link. On success the
|
||||
// overlay carries a confirmed row for the package.
|
||||
auto run_auto_resolution(const std::string& name, const std::string& version,
|
||||
const std::vector<std::string>& components,
|
||||
const fs::path& overlay_path) -> util::Result<void> {
|
||||
auto build_fn = [&](const fs::path& root) {
|
||||
return cmd_build(root, /*no_build=*/false, /*release=*/false,
|
||||
/*target=*/std::nullopt, overlay_path);
|
||||
};
|
||||
const auto scratch_root =
|
||||
std::filesystem::temp_directory_path() /
|
||||
std::format("cargoxx-discover-{}", std::random_device{}());
|
||||
|
||||
auto disc = resolver::discover(name, version, components, overlay_path,
|
||||
scratch_root, build_fn);
|
||||
|
||||
std::error_code ec;
|
||||
std::filesystem::remove_all(scratch_root, ec);
|
||||
|
||||
if (!disc) {
|
||||
return std::unexpected(disc.error());
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto cmd_add(const fs::path& project_root, const std::string& name,
|
||||
const std::string& version_spec, std::vector<std::string> components,
|
||||
std::optional<fs::path> overlay_path) -> util::Result<void> {
|
||||
@@ -41,12 +93,30 @@ auto cmd_add(const fs::path& project_root, const std::string& name,
|
||||
}
|
||||
}
|
||||
|
||||
auto db = linkdb::Database::open(std::move(overlay_path));
|
||||
if (!db) {
|
||||
return std::unexpected(db.error());
|
||||
const auto effective_overlay = overlay_path.value_or(linkdb::default_overlay_path());
|
||||
|
||||
auto known = recipe_already_known(name, effective_version, components,
|
||||
effective_overlay);
|
||||
if (!known) {
|
||||
return std::unexpected(known.error());
|
||||
}
|
||||
if (auto check = db->resolve(name, effective_version, components); !check) {
|
||||
return std::unexpected(check.error());
|
||||
if (!*known) {
|
||||
// Tests opt out of the slow probe + verify-build chain by exporting
|
||||
// CARGOXX_NO_AUTORESOLVE; in that mode we surface the same
|
||||
// LinkdbUnknownPackage error the linkdb returned.
|
||||
if (auto* env = std::getenv("CARGOXX_NO_AUTORESOLVE"); env && *env) {
|
||||
return std::unexpected(util::Error{
|
||||
util::ErrorCode::LinkdbUnknownPackage,
|
||||
std::format("package '{}' has no known CMake link recipe", name),
|
||||
"auto-resolution is disabled (CARGOXX_NO_AUTORESOLVE)",
|
||||
std::nullopt, std::nullopt,
|
||||
});
|
||||
}
|
||||
if (auto r = run_auto_resolution(name, effective_version, components,
|
||||
effective_overlay);
|
||||
!r) {
|
||||
return std::unexpected(r.error());
|
||||
}
|
||||
}
|
||||
|
||||
m->dependencies.push_back(manifest::Dependency{
|
||||
|
||||
Reference in New Issue
Block a user