[M5+] resolve_version + cmd_add lockfile pin

This commit is contained in:
2026-05-10 12:34:48 +00:00
parent cb82e918d8
commit 6f8e9c4aeb
8 changed files with 155 additions and 9 deletions

View File

@@ -4,6 +4,7 @@ import std;
import cargoxx.util;
import cargoxx.manifest;
import cargoxx.linkdb;
import cargoxx.lockfile;
import cargoxx.resolver;
namespace cargoxx::cli {
@@ -33,6 +34,47 @@ auto recipe_already_known(const std::string& name, const std::string& version,
return false;
}
// Persists `nixpkgs_rev` for the (name, version) pair into Cargoxx.lock.
// Overwrites any existing entry for the same (name, version). Other
// lockfile entries (root package, sibling deps) are preserved verbatim.
auto record_lockfile_rev(const fs::path& project_root, const std::string& name,
const std::string& version, const std::string& rev)
-> util::Result<void> {
const auto lock_path = project_root / "Cargoxx.lock";
lockfile::Lockfile lock;
std::error_code ec;
if (std::filesystem::exists(lock_path, ec)) {
auto parsed = lockfile::parse(lock_path);
if (!parsed) {
return std::unexpected(parsed.error());
}
lock = std::move(*parsed);
} else {
lock.version = 1;
}
bool replaced = false;
for (auto& p : lock.packages) {
if (p.name == name && p.version == version) {
p.nixpkgs_rev = rev;
replaced = true;
break;
}
}
if (!replaced) {
lock.packages.push_back(lockfile::LockfilePackage{
.name = name,
.version = version,
.dependencies = {},
.nixpkgs_attr = std::nullopt,
.nixpkgs_rev = rev,
.linkdb_source = std::nullopt,
});
}
return lockfile::write(lock, lock_path);
}
// 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.
@@ -119,13 +161,42 @@ auto cmd_add(const fs::path& project_root, const std::string& name,
}
}
// Concrete @<version> is a hard pin — must yield a specific nixpkgs
// rev for the generated flake.nix. Resolve it BEFORE writing the
// manifest so a failure leaves nothing on disk. Wildcards (`*`) and
// CARGOXX_NO_AUTORESOLVE skip this step entirely; the dep tracks
// nixos-unstable.
const bool wildcard = effective_version == "*";
auto* env = std::getenv("CARGOXX_NO_AUTORESOLVE");
const bool autoresolve_disabled = env != nullptr && *env != 0;
std::optional<std::string> resolved_rev;
if (!wildcard && !autoresolve_disabled) {
auto rev = resolver::resolve_version(name, effective_version);
if (!rev) {
return std::unexpected(rev.error());
}
resolved_rev = std::move(*rev);
}
m->dependencies.push_back(manifest::Dependency{
.name = name,
.version_spec = effective_version,
.components = std::move(components),
});
return manifest::write(*m, manifest_path);
if (auto r = manifest::write(*m, manifest_path); !r) {
return std::unexpected(r.error());
}
if (resolved_rev) {
if (auto r = record_lockfile_rev(project_root, name, effective_version,
*resolved_rev);
!r) {
return std::unexpected(r.error());
}
}
return {};
}
} // namespace cargoxx::cli