feat: system-agnostic package manager — 5 inits, 2 bootloaders, parallel scheduler
Complete rewrite of kappa from a sequential build tool into a
system-agnostic package manager with runtime init switching.
Core additions:
- 5 init system backends: systemd, openrc, s6, runit, dinit
(service file generation, enable/disable, init_paths)
- 2 bootloader backends: grub, limine (config generation, fallback entries)
- Parallel scheduler with worker pool, depth-based priority (Beta/Alpha/Zeta),
atomic claiming, dependency tracking, deduplication, and failure propagation
- Init-switch impact analysis: only rebuild packages using ${enabledinit}
- Init-agnostic service definitions: flat NamedService blocks replace
per-init nesting
- Package conflicts: mutual incompatibility detection in resolver
- System groups: init-agnostic group creation in DSL
- Init-agnostic hostname/timezone: direct /etc/hostname and /etc/localtime writes
- Source tarball caching at /kappa/cache/ with atomic write-then-rename
- Package recipe caching with remote fetching and version comparison
- remotes = [...] block in system config for package repositories
- Auto-fetch: rebuild resolves missing packages from remotes
- uninstall phase in package definitions
- ${enabledinit} eval variable for init-conditional builds
- Shared util module (to_lower, shell_escape)
- 54 integration tests across two shell test suites
- Comprehensive README and CONTRIBUTING guide
Bug fixes from review:
- CRITICAL: Replace std::system() with fork+execvp (command injection)
- CRITICAL: Fix scheduler deadlock on successful completion
- CRITICAL: Fix rebuild init/kernel/bootloader change detection
- HIGH: Fix path traversal via unsanitized package names in cache
- HIGH: Fix TOCTOU race in cache write with atomic rename
- HIGH: Fix formatter dropping remotes/imports blocks
- HIGH: Fix formatter stripping empty-string assert values
- HIGH: Fix formatter non-idempotent output (sorted key iteration)
- HIGH: Populate ${enabledinit} from boot.init in BuildStep
- MEDIUM: Fix data race on non-atomic scheduler stop flag
- MEDIUM: Fix compute_depths() traversal direction
- MEDIUM: Add runit to doctor supported-init warning
- MEDIUM: Extract to_lower/shell_escape to shared kappa::util
- MEDIUM: Consolidate generator declarations in headers
This commit is contained in:
+20
-3
@@ -1,7 +1,9 @@
|
||||
#include "kappa/resolve/plan.hpp"
|
||||
#include "kappa/config/merge.hpp"
|
||||
|
||||
#include <format>
|
||||
#include <queue>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace kappa::resolve {
|
||||
|
||||
@@ -21,9 +23,10 @@ BuildPlan resolve(const dsl::SystemConfig& cfg, const Registry& registry) {
|
||||
auto resolved = config::resolve_package(pkg, cfg.system, pref);
|
||||
|
||||
BuildStep step;
|
||||
step.name = pkg.name;
|
||||
step.package = &pkg;
|
||||
step.resolved = std::move(resolved);
|
||||
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()) {
|
||||
@@ -39,6 +42,20 @@ BuildPlan resolve(const dsl::SystemConfig& cfg, const Registry& registry) {
|
||||
nodes.push_back(std::move(step));
|
||||
}
|
||||
|
||||
// Detect conflicts between selected packages
|
||||
std::unordered_set<std::string> 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<int> in_degree(nodes.size(), 0);
|
||||
std::vector<std::vector<std::size_t>> adj(nodes.size());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user