feat(install): orchestrate install via single root-package LocalProvide call
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
Warning
|
||||
Warning ## Warning for package tofu ##
|
||||
Warning
|
||||
Warning The following compiler flags have been specified in the package description
|
||||
Warning file. They are handled by DUB and direct use in packages is discouraged.
|
||||
Warning Alternatively, you can set the DFLAGS environment variable to pass custom flags
|
||||
Warning to the compiler, or use one of the suggestions below:
|
||||
Warning
|
||||
Warning warningsAsErrors: Use "buildRequirements" to control the warning level
|
||||
Warning
|
||||
Generating test runner configuration 'tofu-test-application' for 'application' (executable).
|
||||
Warning Excluding main source file src/main.d from test.
|
||||
Starting Performing "unittest" build using /usr/bin/dmd for x86_64.
|
||||
Up-to-date toml 1.0.0: target for configuration [library] is up to date.
|
||||
Building tofu ~main: building configuration [tofu-test-application]
|
||||
Linking tofu-test-application
|
||||
Finished To force a rebuild of up-to-date targets, run again with --force
|
||||
Running tofu-test-application
|
||||
zeta-makepkg: building hello...zeta-makepkg: configure phasezeta-makepkg: build phasezeta-makepkg: install phasezeta-makepkg: building hello...zeta-makepkg: configure phasezeta-makepkg: build phasezeta-makepkg: install phasezeta-makepkg: building hello...zeta-makepkg: configure phasezeta-makepkg: build phasezeta-makepkg: install phasezeta-makepkg: building hello...zeta-makepkg: configure phasezeta-makepkg: build phasezeta-makepkg: install phasedonezeta-makepkg: building depA...zeta-makepkg: configure phasezeta-makepkg: build phasezeta-makepkg: install phasezeta-makepkg: building depB...zeta-makepkg: configure phasezeta-makepkg: build phasezeta-makepkg: install phasezeta-makepkg: building target...zeta-makepkg: configure phasezeta-makepkg: build phasezeta-makepkg: install phasezeta-makepkg: building depA...zeta-makepkg: configure phasezeta-makepkg: build phasezeta-makepkg: install phase[31merror[0m build failed for depA: build failed for depA:
|
||||
zeta-makepkg: building depA...
|
||||
zeta-makepkg: configure phase
|
||||
zeta-makepkg: build phase
|
||||
zeta-makepkg: install phase
|
||||
zeta-makepkg: building pkg...zeta-makepkg: configure phasezeta-makepkg: build phasezeta-makepkg: install phase[31merror[0m build failed for noexist: recipe not found at /tmp/tofu-test-build-buildall-norecipe-216783/nonexistent.recipe
|
||||
[33mwarn corrupted cache for pkg: Found 'h' when expecting 'r'. (Line 1:2)[0m
|
||||
Warning: malformed TOML config at /tmp/tofu-test-config-bad-216783.toml: Invalid table key declaration (2:0)
|
||||
Warning: invalid TOFU_DEFAULT_JOBS 'not-a-number', using default 1
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] "GET /recipes/hello/hello.recipe HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] "GET /recipes/hello/package.lua HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] "GET /recipes/hello/build.sh HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] code 404, message File not found
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] "GET /recipes/hello/hello.recipe HTTP/1.1" 404 -
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] "GET /recipes/hello/hello.recipe HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] code 404, message File not found
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] "GET /recipes/hello/package.lua HTTP/1.1" 404 -
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] code 404, message File not found
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] "GET /recipes/hello/build.sh HTTP/1.1" 404 -
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] "GET /recipes/hello/scripts/build.sh HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] "GET /recipes/hello/hello.recipe HTTP/1.1" 200 -
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] code 404, message File not found
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] "GET /recipes/hello/package.lua HTTP/1.1" 404 -
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] code 404, message File not found
|
||||
127.0.0.1 - - [08/Aug/2026 18:12:13] "GET /recipes/hello/build.sh HTTP/1.1" 404 -
|
||||
[33mwarn skipping index entry with empty name[0m
|
||||
[33mwarn skipping index entry with empty name[0m
|
||||
[33mwarn skipping index entry 'badpool': invalid pool 'bad_pool_value'[0m
|
||||
[2m . checking binary firefox ...[0m
|
||||
- binary firefox-2.1.0 satisfies firefox>=2.0
|
||||
[2m . checking binary libfoo ...[0m
|
||||
- binary libfoo-1.9 does not satisfy libfoo>=2.0
|
||||
[2m . checking binary noexist ...[0m
|
||||
[2m . checking binary brokenpkg ...[0m
|
||||
[2m . checking binary badpkg ...[0m
|
||||
[2m . checking binary testpkg ...[0m
|
||||
- binary testpkg-2.1.0 satisfies testpkg
|
||||
[36m==> ──── building depA (1/3) ────[0m
|
||||
[32m ok depA[0m
|
||||
[36m==> ──── building depB (2/3) ────[0m
|
||||
[32m ok depB[0m
|
||||
[36m==> ──── building target (3/3) ────[0m
|
||||
[32m ok target[0m
|
||||
[36m==> ──── building depA (1/3) ────[0m
|
||||
- nothing to build
|
||||
[36m==> ──── building pkg (1/1) ────[0m
|
||||
- pkg already built, skipping
|
||||
[36m==> ──── building pkg (1/1) ────[0m
|
||||
[32m ok pkg[0m
|
||||
[36m==> fetching recipe hello[0m
|
||||
[2m . downloading hello.recipe[0m
|
||||
[2m . downloading package.lua[0m
|
||||
[2m . downloading build.sh[0m
|
||||
[32m ok recipe hello downloaded[0m
|
||||
[36m==> fetching recipe hello[0m
|
||||
[2m . downloading hello.recipe[0m
|
||||
[36m==> fetching recipe hello[0m
|
||||
[2m . downloading hello.recipe[0m
|
||||
[2m . downloading package.lua[0m
|
||||
- no package.lua for hello (optional manifest)
|
||||
[2m . downloading build.sh[0m
|
||||
- no build.sh for hello (optional build script)
|
||||
[2m . custom build system: fetching scripts/build.sh[0m
|
||||
[32m ok recipe hello downloaded[0m
|
||||
[36m==> fetching recipe hello[0m
|
||||
[2m . downloading hello.recipe[0m
|
||||
[2m . downloading package.lua[0m
|
||||
- no package.lua for hello (optional manifest)
|
||||
[2m . downloading build.sh[0m
|
||||
- no build.sh for hello (optional build script)
|
||||
[32m ok recipe hello downloaded[0m
|
||||
[36m==> fetching recipe hello[0m
|
||||
[2m . downloading hello.recipe[0m
|
||||
[2m . fetching index http://127.0.0.1:50721//index.lua[0m
|
||||
[32m ok index loaded: 3 packages[0m
|
||||
[2m . fetching index http://127.0.0.1:47569//index.lua[0m
|
||||
[2m . fetching index http://127.0.0.1:42797//index.lua[0m
|
||||
[2m . fetching index http://127.0.0.1:42795//index.lua[0m
|
||||
[2m . fetching index http://127.0.0.1:51365//index.lua[0m
|
||||
[32m ok index loaded: 0 packages[0m
|
||||
[2m . fetching index http://127.0.0.1:51389//index.lua[0m
|
||||
[32m ok index loaded: 1 packages[0m
|
||||
[2m . fetching index http://127.0.0.1:42841//index.lua[0m
|
||||
[32m ok index loaded: 2 packages[0m
|
||||
[2m . fetching index http://127.0.0.1:59485//index.lua[0m
|
||||
[2m . fetching index http://127.0.0.1:35061//index.lua[0m
|
||||
[32m ok index loaded: 1 packages[0m
|
||||
installing package...error: build failedreason: missing dependencytestpkg-2.1 is already installed -- use -ReProvide to reinstall - already installed — skipping
|
||||
[32m ok installed A with 2 dependencies[0m
|
||||
- nothing to install
|
||||
install failed: conflict detectedtestpkg-2.1 is already installed -- use -ReProvide to reinstall13 modules passed unittests
|
||||
- already installed — skipping
|
||||
[32m ok installed A with 0 dependencies[0m
|
||||
- binary libfoo-2.1 satisfies libfoo>=2.0
|
||||
- libfoo: binary 1.9 too old, building from recipe
|
||||
- libfoo: binary 1.9 too old, building from recipe
|
||||
- binary libbar-3.0 satisfies libbar (unconstrained)
|
||||
- libbaz: no binary available, building from recipe
|
||||
- binary libfoo-1.5 satisfies libfoo>=1.0
|
||||
- libfoo: binary 1.5 too old, building from recipe
|
||||
- binary parentA-1.5 satisfies parentA (unconstrained)
|
||||
- binary parentB-1.5 satisfies parentB (unconstrained)
|
||||
[36m==> generating build plan[0m
|
||||
- + C (recipe)
|
||||
- + A (recipe)
|
||||
[32m ok build plan: 2 packages[0m
|
||||
[36m==> generating build plan[0m
|
||||
- recipe libfoo not in cache, re-fetching
|
||||
- + libfoo (recipe)
|
||||
[32m ok build plan: 1 packages[0m
|
||||
[36m==> generating build plan[0m
|
||||
[36m==> generating build plan[0m
|
||||
- nothing to build (all binary)
|
||||
[36m==> generating build plan[0m
|
||||
- + mypkg (recipe)
|
||||
[32m ok build plan: 1 packages[0m
|
||||
[36m==> generating build plan[0m
|
||||
- + libfoo (recipe)
|
||||
- + mypkg (recipe)
|
||||
[32m ok build plan: 2 packages[0m
|
||||
Warning
|
||||
Warning ## Warning for package tofu ##
|
||||
Warning
|
||||
Warning The following compiler flags have been specified in the package description
|
||||
Warning file. They are handled by DUB and direct use in packages is discouraged.
|
||||
Warning Alternatively, you can set the DFLAGS environment variable to pass custom flags
|
||||
Warning to the compiler, or use one of the suggestions below:
|
||||
Warning
|
||||
Warning warningsAsErrors: Use "buildRequirements" to control the warning level
|
||||
Warning
|
||||
Starting Performing "debug" build using /usr/bin/dmd for x86_64.
|
||||
Up-to-date toml 1.0.0: target for configuration [library] is up to date.
|
||||
Up-to-date tofu ~main: target for configuration [application] is up to date.
|
||||
Finished To force a rebuild of up-to-date targets, run again with --force
|
||||
@@ -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