[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. // repopulates it.
auto merge_lockfile(const manifest::Manifest& m, auto merge_lockfile(const manifest::Manifest& m,
const std::vector<linkdb::Recipe>& recipes, const std::vector<linkdb::Recipe>& recipes,
const std::vector<linkdb::Recipe>& dev_recipes,
const lockfile::Lockfile& prior) -> lockfile::Lockfile { const lockfile::Lockfile& prior) -> lockfile::Lockfile {
auto find_prior = [&](const std::string& name, const std::string& version) auto find_prior = [&](const std::string& name, const std::string& version)
-> std::optional<lockfile::LockfilePackage> { -> std::optional<lockfile::LockfilePackage> {
@@ -69,17 +70,13 @@ auto merge_lockfile(const manifest::Manifest& m,
for (const auto& dep : m.dependencies) { for (const auto& dep : m.dependencies) {
root.dependencies.push_back(std::format("{} {}", dep.name, dep.version_spec)); 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)); lock.packages.push_back(std::move(root));
for (std::size_t i = 0; i < m.dependencies.size(); ++i) { auto emit_dep = [&](const manifest::Dependency& dep, const linkdb::Recipe& rec) {
const auto& dep = m.dependencies[i];
const auto& rec = recipes[i];
std::optional<std::string> rev; 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; std::string attr = rec.nixpkgs_attr;
if (auto p = find_prior(dep.name, dep.version_spec); p) { if (auto p = find_prior(dep.name, dep.version_spec); p) {
rev = p->nixpkgs_rev; rev = p->nixpkgs_rev;
@@ -95,6 +92,12 @@ auto merge_lockfile(const manifest::Manifest& m,
.nixpkgs_rev = std::move(rev), .nixpkgs_rev = std::move(rev),
.linkdb_source = rec.source, .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; return lock;
} }
@@ -148,14 +151,26 @@ auto cmd_build(const fs::path& project_root, bool no_build, bool release,
return std::unexpected(db.error()); return std::unexpected(db.error());
} }
std::vector<linkdb::Recipe> recipes; auto resolve_list = [&](const std::vector<manifest::Dependency>& deps)
recipes.reserve(m->dependencies.size()); -> util::Result<std::vector<linkdb::Recipe>> {
for (const auto& dep : m->dependencies) { std::vector<linkdb::Recipe> out;
auto r = db->resolve(dep.name, dep.version_spec, dep.components); out.reserve(deps.size());
if (!r) { for (const auto& dep : deps) {
return std::unexpected(r.error()); 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; 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) { if (auto r = lockfile::parse(project_root / "Cargoxx.lock"); r) {
prior = std::move(*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{ codegen::GenerateInputs in{
.manifest = *m, .manifest = *m,
.layout = *layout_result, .layout = *layout_result,
.lock = lock, .lock = lock,
.recipes = recipes, .recipes = *recipes,
.dev_recipes = {}, .dev_recipes = *dev_recipes,
.project_root = project_root, .project_root = project_root,
}; };
auto flake_text = codegen::flake_nix(in); auto flake_text = codegen::flake_nix(in);