#include "kappa/resolve/plan.hpp" #include "kappa/config/merge.hpp" #include #include #include namespace kappa::resolve { BuildPlan resolve(const dsl::SystemConfig& cfg, const Registry& registry) { BuildPlan plan; std::unordered_map name_to_idx; std::vector nodes; for (auto& pref : cfg.packages) { auto rit = registry.find(pref.name); if (rit == registry.end()) { plan.missing.push_back(pref.name); continue; } auto& pkg = rit->second; auto resolved = config::resolve_package(pkg, cfg.system, pref); BuildStep step; step.name = pkg.name; step.package = &pkg; step.resolved = std::move(resolved); step.enabled_init = cfg.boot.init; for (auto& dep : pkg.depends) { if (!dep.feature.empty()) { auto fit = step.resolved.features.find(dep.feature); if (fit == step.resolved.features.end() || !fit->second.enabled) { continue; } } step.dependencies.push_back({dep.name, dep.version}); } name_to_idx[step.name] = nodes.size(); nodes.push_back(std::move(step)); } // Detect conflicts between selected packages std::unordered_set selected; for (auto& node : nodes) { selected.insert(node.name); } for (auto& node : nodes) { if (!node.package) continue; for (auto& conflict_name : node.package->conflicts) { if (selected.contains(conflict_name)) { plan.conflicts.push_back( std::format("{} conflicts with {}", node.name, conflict_name)); } } } std::vector in_degree(nodes.size(), 0); std::vector> adj(nodes.size()); for (std::size_t i = 0; i < nodes.size(); ++i) { for (auto& dep : nodes[i].dependencies) { auto it = name_to_idx.find(dep.name); if (it != name_to_idx.end()) { adj[it->second].push_back(i); in_degree[i]++; } } } std::queue q; for (std::size_t i = 0; i < nodes.size(); ++i) { if (in_degree[i] == 0) { q.push(i); } } std::vector visited(nodes.size(), false); while (!q.empty()) { auto u = q.front(); q.pop(); visited[u] = true; plan.steps.push_back(nodes[u]); for (auto v : adj[u]) { if (--in_degree[v] == 0) { q.push(v); } } } for (std::size_t i = 0; i < nodes.size(); ++i) { if (!visited[i]) { plan.cycles.push_back(nodes[i].name); } } return plan; } } // namespace kappa::resolve