feat(install): orchestrate install via single root-package LocalProvide call
This commit is contained in:
@@ -684,3 +684,54 @@ The sandbox test (test 2) creates a sentinel file, serves an index containing `o
|
||||
- `dub test` passes — all 13 modules, including 6 new buildAll unittests.
|
||||
- `dub build` passes with `warningsAsErrors`.
|
||||
- Evidence logged to `.omo/evidence/task-15-tofu-core.log`.
|
||||
|
||||
---
|
||||
|
||||
## Task 17 — `tofu.install.installAll` (install orchestrator)
|
||||
|
||||
### Architecture
|
||||
- `installAll(BuildPlan plan, Config cfg)` added to `tofu.install` — single root-package `-LocalProvide` call.
|
||||
- Imports added: `tofu.types` (selective: `BuildPlan`, `BuildPlanEntry`, `Source`), `std.conv : to`, `std.file : exists`.
|
||||
- Reuses `runLocalProvide` — no new process-spawning logic.
|
||||
|
||||
### Algorithm
|
||||
1. **Empty plan** → `logInfo("nothing to install")`, return early.
|
||||
2. **Verify built cache**: for each `Source.recipe` entry, check `cfg.builtPackagesDir()/name/package.lua` exists. Missing → `InstallException("built package missing from cache: <name> (was the build skipped?)")`.
|
||||
3. **Root = last entry** in `plan.order()` — matches `deps.resolve`/`generateBuildPlan` convention (topological order, root last).
|
||||
4. **Single call**: `runLocalProvide(rootName, cfg)` — ZETA's `deps.resolve` walks the full tree from `ZETA_LOCAL_PACKAGES` + `ZETA_REPO`.
|
||||
5. **Success**: `logOk("installed <root> with N dependencies")` where N = `order.length - 1`.
|
||||
6. **InstallException from `runLocalProvide`**: propagates to caller (no catch needed — install command records state).
|
||||
|
||||
### "already installed" handling
|
||||
- Handled internally by `runLocalProvide` — exit 0 + "already installed" substring in output → `logInfo("already installed — skipping")`, no throw.
|
||||
- `installAll` continues to `logOk` after.
|
||||
|
||||
### Dependencies counted
|
||||
- All entries in `BuildPlan` are recipe-sourced (binary excluded by `generateBuildPlan`). Root is last entry. Dep count = `order.length - 1`.
|
||||
|
||||
### `@safe` / `@trusted` architecture
|
||||
- `installAll` is `@safe` public.
|
||||
- Only `std.file.exists` requires `@trusted` wrapper — inline lambda `() @trusted { pkgExists = exists(pkgPath); }()`.
|
||||
|
||||
### Imports strategy
|
||||
- Top-level selective import: `import tofu.types : BuildPlan, BuildPlanEntry, Source;` — avoids pulling in the full types module.
|
||||
- `import std.conv : to;` for `to!string(size_t)`.
|
||||
- `import std.file : exists;` at module level for the built-cache verification check.
|
||||
|
||||
### Unittests — 5 new test blocks (test 1–5 for installAll)
|
||||
- Reused existing test infrastructure: `makeTempDir`, `removeDir`, `writeFakeScript`, `testConfig`.
|
||||
- Test (1): plan [B, C, A] with all package.lua + fake zeta captures `$2` → "A" only, no "B"/"C".
|
||||
- Test (2): plan missing B's package.lua → `InstallException` "built package missing from cache: B".
|
||||
- Test (3): empty plan → no-op, no throw.
|
||||
- Test (4): fake zeta exits 1 → `InstallException` "install failed for A".
|
||||
- Test (5): fake zeta prints "already installed" + exits 0 → no throw, `logOk` succeeds.
|
||||
|
||||
### Arg capture pattern
|
||||
- Fake zeta script: `echo "$2" >> <path>` — `$2` = package name (args: `fake-zeta -LocalProvide <pkgName> --pass`).
|
||||
- Previous learnings used `$3` incorrectly — in bash, `$0`=script name, `$1`=-LocalProvide, `$2`=pkgName, `$3`=--pass.
|
||||
|
||||
### Build verified
|
||||
- `dub test` passes — all 13 modules, including 5 new installAll unittests (plus 5 pre-existing runLocalProvide tests = 10 total in install.d).
|
||||
- `dub build` passes with `warningsAsErrors`.
|
||||
- No D LSP server configured for `.d` — diagnostics verified via compiler.
|
||||
- Evidence logged to `.omo/evidence/task-17-tofu-core.log`.
|
||||
|
||||
Reference in New Issue
Block a user