Commit Graph
30 Commits
Author SHA1 Message Date
huntedbytheirs ac530e94a7 fix: install software-properties-common for llvm.sh on Debian
CI / build-and-test (push) Failing after 1m13s
Debian 11 (bullseye) doesn't have add-apt-repository by default.
llvm.sh needs it to add the LLVM apt repo.
2026-08-04 14:28:33 -04:00
huntedbytheirs 71d2eadcb9 fix: force clang-18 via LLVM script, prefer highest version
CI / build-and-test (push) Failing after 19s
<llvm.sh 18 all> installs clang-18 with full C++23 support.
sort -V ensures the highest clang version is selected when
multiple are installed. Removes -stdlib=libc++ (clang-18
provides <format> via its own header, no flag needed).
2026-08-04 14:27:13 -04:00
huntedbytheirs dc782e941c fix: install libc++ alongside clang for <format> support
CI / build-and-test (push) Failing after 39s
Clang 16 on Ubuntu 22.04 uses libstdc++ 12 which lacks <format>.
Install libc++-dev and pass -stdlib=libc++ to CMake.
2026-08-04 14:25:41 -04:00
huntedbytheirs 3302712336 fix: correct C++ compiler naming in CI (clang++-16 not clang-16++)
CI / build-and-test (push) Failing after 34s
Clang installs the C++ compiler as clang++-16, not clang-16++.
Use sed to properly transform the C compiler path.
2026-08-04 14:24:09 -04:00
huntedbytheirs 4a8b87e2cd fix: use find instead of ls for clang detection in CI
CI / build-and-test (push) Failing after 33s
ls returns exit code 2 when glob has no matches, which fails the
build step under set -e + pipefail. find returns 0 even when no
files are found.
2026-08-04 14:22:46 -04:00
huntedbytheirs 5668708fed fix: detect and install Clang 15-18 with LLVM fallback
CI / build-and-test (push) Failing after 30s
- Tries apt clang-18/17/16/15 first (Ubuntu 22.04+)
- Falls back to LLVM repo install for Ubuntu 20.04
- Auto-detects installed clang version for CMake compiler flags
- Both CMake 3.28 (binary download) and C++23 compiler required
2026-08-04 14:21:10 -04:00
huntedbytheirs 07a485a535 fix: install CMake 3.28 in CI (runner has 3.18, we need 3.20+)
CI / build-and-test (push) Failing after 26s
Download official CMake binary from Kitware releases instead of
relying on the distro package manager which provides an older version.
2026-08-04 14:17:52 -04:00
huntedbytheirs d10679d267 test: add 85 comprehensive tests and Gitea CI/CD workflow
CI / build-and-test (push) Failing after 56s
- test-full.sh: 85 tests covering CLI, DSL parsing (all keywords),
  config parsing, users/groups, assertions, imports, doctor diagnostics,
  repos/remotes, index generation, add/remove operations, install DB,
  resolver (conflicts + missing), scheduler (deptree ordering),
  build execution + error handling, env operators,
  init systems, bootloaders, variable interpolation, --root override,
  rollback config, system env, feature flags, rebuild dry-run

- .gitea/workflows/ci.yml: builds on Ubuntu with clang+cmake+ninja,
  runs all three test suites on push/PR to main

Total test count: 31 (DSL) + 23 (init-switch) + 85 (comprehensive) = 139
2026-08-04 14:15:50 -04:00
huntedbytheirs 09dde98159 fix: report package conflicts in resolve and rebuild handlers
Conflicts were detected in the resolver but silently ignored in both
the resolve and rebuild subcommands. Both now print conflict errors
and abort before any builds start.
2026-08-04 14:05:16 -04:00
huntedbytheirs 7345b026cc feat: add kappa add and kappa remove subcommands
- kappa add <pkg> [version] — adds/updates package in system config
  packages{} block; creates config if it doesn't exist

- kappa remove <pkg> — removes package from config; idempotent
  (no error if package isn't present)

- Supports --root flag for custom KAPPA_ROOT

- User workflow: kappa add make && kappa rebuild
  No manual config editing needed.
2026-08-04 14:00:51 -04:00
huntedbytheirs 7b0538c392 feat: add index-aware recipe resolution with repo support
- fetch_recipe_from_repos() iterates repos by priority, channels, with
  mirror fallback — caches indexes at /cache/indexes/

- Conditional HTTP downloads (curl -z) to only re-fetch stale indexes

- build_registry and fetch-package prefer repos { } over remotes = [...]
  when both are present

- Fallback chain: local .kap → repos (index-aware) → remotes (legacy)
2026-08-04 13:50:29 -04:00
huntedbytheirs 4f1ce17ec8 feat: add repos DSL, index format, and kappa index command
- Add repos { } block to system config with named repos, channels,
  mirrors, and priority

- Add index "name" { } file format for package indexes

- Add kappa index <dir> subcommand that scans .kap files and
  generates index.kap

- parse_index() and build_index() in DSL module

- format_index() roundtrip support in tools module

- validate and format subcommands handle all three formats
  (package, config, index) with automatic detection

- Backward compatible: remotes = [...] still works unchanged
2026-08-04 13:48:25 -04:00
huntedbytheirs 86f578bd4a feat: add GNU Make 4.4.1 package definition
Full autotools build (./configure, make, make check, make install)
verified end-to-end — builds, installs, produces working binary.
2026-08-04 13:29:31 -04:00
huntedbytheirs d02ab4b7b6 docs: update examples with += env operator and env usage docs
- foo.kap: document all three env operators (=, ?=, +=) in header,
  demonstrate += in env block with comments

- postgres.kap: demonstrate += for appending security hardening flags

- config.kap: demonstrate system-level += for inherited flags
2026-08-04 13:19:59 -04:00
huntedbytheirs e817e58698 feat: implement build backend and += env operator, add style guide
- Replace build stub with full phase execution (prepare/build/check/install)
  via /bin/sh with variable interpolation, config file generation, and
  env handling (hard-set, soft/?=, append/+=)

- Add += append operator for environment variables across DSL, parser,
  system config parser, build backend, and formatter

- Add STYLEGUIDE.md documenting all codebase conventions

- Replace EnvEntry bool soft with EnvMode enum (Set/Soft/Append)

- Add Plus token type to lexer for += parsing
2026-08-04 12:58:38 -04:00
huntedbytheirs 0aca4b49ca qol: implement easier building and distribution 2026-08-04 12:19:52 -04:00
huntedbytheirs 486a476b90 feat: wire rebuild pipeline (scheduler \u2192 build \u2192 install \u2192 services \u2192 bootloader)
The rebuild subcommand now executes the full pipeline:
- build_registry() -> resolve() -> sched::run()
- install::install() for each built package
- service::install_service() for enabled services
- boot::install_bootloader_config() for bootloader config
- system::write_hostname() / write_timezone() for system activation

Added --dry-run flag for report-only behavior (backward compat with
test suite). Added -w flag for worker parallelism and --dry-run to help.
Fixed .gitignore: 'kappa' -> '/kappa' (was matching include/kappa/,
preventing header files from being tracked since initial commit).
This commit also adds all previously-gitignored header files.
2026-07-31 08:38:53 -04:00
huntedbytheirs 7e93db2d07 feat: portability, correctness, and quality improvements for v0.2
Portability (Linux distro-agnostic):
- Remove hardcoded Clang compiler enforcement; GCC now builds
- Add find_package(Threads REQUIRED) for older glibc
- Add cmake install() target
- FHS 3.0 default root: /kappa -> /usr/local/kappa
- fs::path operator/ for all init/bootloader paths (fixes prefix fragility)
- Multi-distro zoneinfo search (FHS, NixOS, Guix, alt)
- Portable tar extraction (drop GNU-only --no-same-permissions)
- Runit enable/disable commands now prefix-aware
- --root CLI flag before/after subcommand, lazy directory creation
- Shebang constants de-duplicated to types.hpp

Correctness (race conditions, UB, corruption):
- Fix CWD race in scheduler: per-child chdir() instead of process-global
- Fix UB const_cast in exec_cmd/exec_capture: mutable argv buffers
- Fix non-atomic installed DB writes: tmp+rename pattern
- Fix read_file() no longer calls exit(1), throws instead
- Fix silent catch(...) parse errors now print diagnostics
- Fix rebuild false positives with config_hash change detection
- Fix s6 disable_cmd copy-paste bug (was identical to enable)
- Fix runit enable_cmd incomplete, disable_cmd wrong target
- Fix dinit env vars: functional env-file + companion .env

Quality:
- Add -Wall -Wextra -Wpedantic to CMake, fix 2 pre-existing warnings
- Move parse_int from error.hpp to parse_util.hpp
- Fix hash verification guard checks all three hash types
- Check patch return code in fetch.cpp
- Add explicit system_dir creation in ensure_directories()
- Add resolve to needs_dirs for build_registry() consistency
- Update stale /kappa path references in examples
- Remove inaccurate -Werror claim in CONTRIBUTING.md
- Add build-gcc/ and agent dirs to .gitignore
- Suppress clang-tidy portability-avoid-pragma-once
- Fix .gitignore /kappa pattern (was matching include/kappa/)
- Delete stale vcpkg_installed/ directory

54/54 tests pass. Builds on Clang and GCC with 0 warnings.
2026-07-31 08:28:49 -04:00
huntedbytheirs dd984f96d4 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
2026-07-31 05:32:57 -04:00
huntedbytheirs d6612d0a4a fix: rebuild review — dead include, service detection, version compare
- Removed unused <format> include from rebuild.cpp
- Service change detection simplified: any enabled service flags change
  (services aren't stored as DB entries, so element-wise compare impossible)
- Version comparison: checks if version/features/config are non-empty
  in PackageRef (conservative — rebuilds if any constraint is specified)
- Empty config with unchanged packages correctly reports 'nothing to rebuild'
2026-07-30 05:56:17 -04:00
huntedbytheirs 7712f88386 feat: rebuild, list, rollback — Phase 5 completion
- kappa rebuild: diffs config vs installed DB, reports changed/added/removed
  packages, detects kernel/init/bootloader/service changes
- kappa list: shows installed packages with versions, hashes, provides
- kappa rollback: lists available generations from /kappa/db/generations
- list + rollback don't require a file argument (no-file subcommands)
- Rebuild wired to compute_changes() → per-package change detection

Full pipeline: resolve → fetch → build → install → list/rollback/rebuild
2026-07-30 05:53:00 -04:00
huntedbytheirs c276465f3a fix: CWD restore, install error checks, fetch EINTR
- build.cpp: save/restore CWD on both success and failure paths
- install.cpp: check error_code after each filesystem op, abort on failure
- install.cpp: check write_installed() return value
- fetch.cpp: EINTR retry loop on both waitpid calls (exec_cmd + exec_capture)
2026-07-30 05:31:59 -04:00
huntedbytheirs 6c993d2d17 fix: Phase 3+4 review — deterministic hash, EINTR, env restore, installer wiring
- std::hash→FNV-1a (deterministic across runs, null-byte-separated)
- waitpid EINTR retry loop (prevents zombie processes under signals)
- setenv save/restore between builds (prevents cross-package env leaks)
- install::install() wired into kappa build CLI (store + DB + generations)
- Zero-padded generation filenames (gen-0001, lexicographic sort correct)
- Hardcoded paths fixed: /tmp/kappa-build→paths::temp_dir()/build
- Hardcoded destdir: /kappa/temp/destdir→paths::temp_dir()/destdir
- ensure_directories() called at main() startup
- build subcommand: -j N, --root wired end-to-end
2026-07-30 05:14:51 -04:00
huntedbytheirs d7fc9d45fb fix: fetcher security — fork+execve, hash verification, tar safety, CLI --help
B1: Replaced all std::system()/popen() with fork+execve — zero shell injection
B2+B3: Added sha256/sha512/md5 fields to PackageDef, parser support, actual hash comparison in verify_hash()
B4: tar --no-same-owner --no-same-permissions, zip uses unzip instead of tar
B5: Patch sha256 verified before application via -i flag (no shell redirect)
B6: kappa fetch --help now prints usage and exits 0
Also: removed dead ternary code, added <cstdlib>/<sys/wait.h>/<unistd.h>
2026-07-30 03:59:15 -04:00
huntedbytheirs 72e582eb15 fix: oracle review fixes — resolver exit code, dead include, pointer compose
- Exit code: plan.missing.empty() ? 0 : 1 (was always returning 0)
- Removed dead <algorithm> include from plan.cpp
- BuildStep now composes config::ResolvedPackage instead of duplicating
  features/config fields; PackageDef stored as const pointer
2026-07-30 00:47:50 -04:00
huntedbytheirs ee9f280346 feat: dependency resolver (Phase 1) + formatter + doctor + assertion evaluation
Resolver (Phase 1):
- resolve::resolve() takes SystemConfig + Registry → BuildPlan
- Three-layer feature/config merge (uses config::resolve_package)
- Feature-gated dependencies: deps with feature=X skipped if feature disabled
- Topological sort via Kahn's algorithm (BFS on in-degree)
- Cycle detection, missing package warnings
- CLI: kappa resolve <config> [<package>]

Formatter:
- format_package() + format_config() → canonical output
- Consistent 4-space indent, canonical declaration order

Doctor:
- check_package() + check_config() → warnings for common issues
- Missing fields, empty configs, root shell, feature warnings

Assertion evaluation:
- evaluate_assertions() resolves dotted field paths
- Supports == and != operators for config validation
- kappa validate now runs assertion checks

Review fixes:
- plan.steps.empty() exit code corrected to 0
- Removed unused <unordered_set> include
- Eliminated duplicate merge logic (uses config::resolve_package)
2026-07-30 00:36:38 -04:00
huntedbytheirs 0c1e82d66b fix: review fixes + feat: imports, assertions, merge engine, per-package overrides
Review fixes (8 blocking issues):
- Extract ParseError to shared error.hpp (ODR fix)
- Remove dead package.cpp/package.hpp + tomlplusplus dep
- Safe parse_int() helper replacing crash-prone std::stoi
- consume_string() now accepts bare numbers and idents
- line_at() fixed for post-EOF line numbers
- Subcommand validation before file read in CLI
- KwService/KwAssert/KwImport added to consume_ident()
- root partition promoted to first-class BootBlock field

New features:
- Imports: imports = [...] with recursive merge resolution
- Assertions: assert { "msg" : field op value } in both parsers
- Merge engine: resolve_package() with features/config merge + force support
- Per-package overrides: /kappa/system/builds/<name>.kap
- .gitignore: added vcpkg_installed/ and kappa binary
2026-07-29 23:52:03 -04:00
huntedbytheirs d5f7d397ed feat: system config DSL, services, CLI with rustc diagnostics
- System config parser (system/packages/services/boot/users blocks)
- Boot block: kernel, init, efi, swap, bootloader, root partition
- System-wide features, rollback config, swap partition
- Service block: per-init variants (runit, s6, etc.), system init selection via boot.init
- Feature-gated dependencies, config values accept numbers/bools/strings
- CLI: parse-package, parse-config, validate subcommands
- Rustc-style error diagnostics with source context, carets, help text
- Diagnostic module with ANSI color output
2026-07-29 22:50:39 -04:00
huntedbytheirs a8b53681fc feat: DSL parser, eval system, and project structure
- Hand-written lexer + recursive-descent parser for .kap package definitions
- Package constructs: const, license, provides, outputs, patches, depends
  (version-constrained, feature-gated, output-targeted), features (enabled/
  forced/flag), config files (default/replace/merge with cfg interpolation),
  env (?= soft-set), prepare/build/check/install phases
- Evaluator: recursive  resolver for prefix, jobopts, destdir, userargs,
  cfg.*, feature.*, package vars
- Comments: // single-line, /* */ multi-line
- /kappa/{bin,temp,db,system,system/builds} path layout
- Clang 22, C++23, CMake + vcpkg (tomlplusplus)
- .clangd + .clang-tidy configured
2026-07-29 22:16:16 -04:00
huntedbytheirs 6fd31b694b Initial commit 2026-07-29 19:59:49 -04:00