[M6] cmd_build: resolve dev_dependencies + thread into lockfile/codegen

This commit is contained in:
2026-05-13 23:59:06 +00:00
parent 2c3bc4fda0
commit a757149f99

View File

@@ -44,6 +44,7 @@ auto write_text(const fs::path& path, std::string_view content) -> util::Result<
// repopulates it.
auto merge_lockfile(const manifest::Manifest& m,
const std::vector<linkdb::Recipe>& recipes,
const std::vector<linkdb::Recipe>& dev_recipes,
const lockfile::Lockfile& prior) -> lockfile::Lockfile {
auto find_prior = [&](const std::string& name, const std::string& version)
-> std::optional<lockfile::LockfilePackage> {
@@ -69,17 +70,13 @@ auto merge_lockfile(const manifest::Manifest& m,
for (const auto& dep : m.dependencies) {
root.dependencies.push_back(std::format("{} {}", dep.name, dep.version_spec));
}
for (const auto& dep : m.dev_dependencies) {
root.dependencies.push_back(std::format("{} {}", dep.name, dep.version_spec));
}
lock.packages.push_back(std::move(root));
for (std::size_t i = 0; i < m.dependencies.size(); ++i) {
const auto& dep = m.dependencies[i];
const auto& rec = recipes[i];
auto emit_dep = [&](const manifest::Dependency& dep, const linkdb::Recipe& rec) {
std::optional<std::string> rev;
// The recipe's nixpkgs_attr is correct for unpinned deps (it's
// curated against nixos-unstable). When the prior lockfile
// already carries an attr — written by `cargoxx add <pkg>@<v>`
// from devbox's authoritative attr_paths for the pinned rev —
// that one wins.
std::string attr = rec.nixpkgs_attr;
if (auto p = find_prior(dep.name, dep.version_spec); p) {
rev = p->nixpkgs_rev;
@@ -95,6 +92,12 @@ auto merge_lockfile(const manifest::Manifest& m,
.nixpkgs_rev = std::move(rev),
.linkdb_source = rec.source,
});
};
for (std::size_t i = 0; i < m.dependencies.size(); ++i) {
emit_dep(m.dependencies[i], recipes[i]);
}
for (std::size_t i = 0; i < m.dev_dependencies.size(); ++i) {
emit_dep(m.dev_dependencies[i], dev_recipes[i]);
}
return lock;
}
@@ -148,14 +151,26 @@ auto cmd_build(const fs::path& project_root, bool no_build, bool release,
return std::unexpected(db.error());
}
std::vector<linkdb::Recipe> recipes;
recipes.reserve(m->dependencies.size());
for (const auto& dep : m->dependencies) {
auto r = db->resolve(dep.name, dep.version_spec, dep.components);
if (!r) {
return std::unexpected(r.error());
auto resolve_list = [&](const std::vector<manifest::Dependency>& deps)
-> util::Result<std::vector<linkdb::Recipe>> {
std::vector<linkdb::Recipe> out;
out.reserve(deps.size());
for (const auto& dep : deps) {
auto r = db->resolve(dep.name, dep.version_spec, dep.components);
if (!r) {
return std::unexpected(r.error());
}
out.push_back(std::move(*r));
}
recipes.push_back(std::move(*r));
return out;
};
auto recipes = resolve_list(m->dependencies);
if (!recipes) {
return std::unexpected(recipes.error());
}
auto dev_recipes = resolve_list(m->dev_dependencies);
if (!dev_recipes) {
return std::unexpected(dev_recipes.error());
}
lockfile::Lockfile prior;
@@ -163,17 +178,15 @@ auto cmd_build(const fs::path& project_root, bool no_build, bool release,
if (auto r = lockfile::parse(project_root / "Cargoxx.lock"); r) {
prior = std::move(*r);
}
// A malformed prior lockfile is non-fatal — we just rebuild from
// scratch. The user can re-pin by running `cargoxx add` again.
}
auto lock = merge_lockfile(*m, recipes, prior);
auto lock = merge_lockfile(*m, *recipes, *dev_recipes, prior);
codegen::GenerateInputs in{
.manifest = *m,
.layout = *layout_result,
.lock = lock,
.recipes = recipes,
.dev_recipes = {},
.recipes = *recipes,
.dev_recipes = *dev_recipes,
.project_root = project_root,
};
auto flake_text = codegen::flake_nix(in);