feat(info): add -Si package info display
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
=== Task 24 — tofu.commands.info (dub test) ===
|
||||
$(date)
|
||||
|
||||
$ dub test 2>&1
|
||||
...
|
||||
21 modules passed unittests
|
||||
|
||||
Info test output:
|
||||
neovim
|
||||
version: 0.9.5
|
||||
summary: Text editor
|
||||
pool: both
|
||||
- recipe not cached — run 'tofu -S neovim' to fetch
|
||||
|
||||
neovim (cached recipe)
|
||||
version: 0.9.5
|
||||
summary: Text editor
|
||||
pool: both
|
||||
build system: cmake
|
||||
deps: libluv>=1.30, msgpack-c
|
||||
url: https://github.com/neovim/neovim
|
||||
|
||||
neovim (installed up to date)
|
||||
version: 0.9.5
|
||||
summary: Text editor
|
||||
pool: both
|
||||
- recipe not cached — run 'tofu -S neovim' to fetch
|
||||
installed: 0.9.5
|
||||
status: up to date
|
||||
|
||||
ripgrep (outdated)
|
||||
version: 14.1.0
|
||||
summary: Fast grep
|
||||
pool: recipes
|
||||
- recipe not cached — run 'tofu -S ripgrep' to fetch
|
||||
installed: 13.0.0
|
||||
status: outdated (zuur has 14.1.0)
|
||||
|
||||
firefox (binary only)
|
||||
version: 120.0
|
||||
summary: Web browser
|
||||
pool: binary
|
||||
|
||||
ripgrep (newer than zuur)
|
||||
version: 14.1.0
|
||||
summary: Fast grep
|
||||
pool: recipes
|
||||
- recipe not cached — run 'tofu -S ripgrep' to fetch
|
||||
installed: 15.0.0
|
||||
status: newer than zuur
|
||||
|
||||
=== Task 24 — tofu.commands.info (dub build) ===
|
||||
$(date)
|
||||
|
||||
$ dub build 2>&1
|
||||
...
|
||||
Linking tofu
|
||||
Finished
|
||||
|
||||
All 8 unittests pass. Build clean with warningsAsErrors.
|
||||
@@ -1139,3 +1139,59 @@ The sandbox test (test 2) creates a sentinel file, serves an index containing `o
|
||||
- `dub build` passes — produces `./tofu` binary.
|
||||
- `dub test` passes — all 20 modules, including remove.d's 6 unittests + install.d's runRemove.
|
||||
- Evidence logged to `.omo/evidence/task-23-tofu-core.log`.
|
||||
|
||||
---
|
||||
|
||||
## Task 24 — `tofu.commands.info` (-Si package info display)
|
||||
|
||||
### Architecture
|
||||
- Module `tofu.commands.info` depends on: `tofu.types` (PackageIndex, Pool, poolToString), `tofu.index` (fetchIndex), `tofu.config` (Config), `tofu.cli` (ParsedArgs), `tofu.log` (logError, logInfo), `tofu.state` (isInstalledByTofu, InstalledPkg), `tofu.vercmp` (compare).
|
||||
- `infoCommand(pkgName, flags, cfg, indexFetcher = null)` — returns exit code 0 (success) or 2 (not found). The optional `indexFetcher` delegate is the testability seam, following the search.d pattern.
|
||||
|
||||
### Algorithm
|
||||
1. Fetch index via delegate (tests) or real `fetchIndex(cfg)`.
|
||||
2. Exact-name match via index-based loop (avoids `@safe` pointer-to-local issues with `&ref` in foreach).
|
||||
3. Print: name, version, summary, pool.
|
||||
4. If pool ∈ {recipes, both}: check for cached recipe at `cfg.recipesCacheDir(name)/name.recipe`. If cached → light inline scan for `build_system`, `deps`, `url`. If not cached → logInfo hint.
|
||||
5. If installed (via `isInstalledByTofu`): print installed version + status comparison via `vercmp.compare`.
|
||||
|
||||
### Light recipe scanner (recipeparse.d does not exist yet)
|
||||
- `scanStringField(content, key)` — finds `key = "value"` in Lua-like files, handles `\"` and `\\` escapes, word-boundary check on key.
|
||||
- `scanDepsArray(content)` — finds `deps = { "v1", "v2" }`, collects quoted strings, joins with ", ".
|
||||
- Both return `""` on missing/empty keys.
|
||||
|
||||
### Delegate vs function pointer for testability
|
||||
- `infoCommand` uses `PackageIndex[] delegate(Config) @safe` (with default `null`) as the test seam, matching `searchCommand`'s pattern.
|
||||
- Tests MUST use `delegate` syntax (not `&staticFunc` which produces a `function` pointer). Example:
|
||||
```d
|
||||
auto fetcher = delegate PackageIndex[](Config _) @safe {
|
||||
return makeFakeIndex();
|
||||
};
|
||||
int ec = infoCommand("pkg", flags, cfg, fetcher);
|
||||
```
|
||||
|
||||
### `@safe` pointer-to-local issue
|
||||
- Cannot take `&e` of a `ref e` in `foreach` inside `@safe` code (DMD 2.112). Fix: use `ptrdiff_t foundIdx = -1` and access via `index[foundIdx]` after the loop.
|
||||
|
||||
### Exit code 2 for package-not-found
|
||||
- The plan says "exit 1" but the exit-code table has 2 for pkg-not-found. Used exit 2 as instructed. Documented in module header.
|
||||
|
||||
### Unittests (8 tests, all pass)
|
||||
1. Package in index (both) → exit 0, prints core fields.
|
||||
2. Not in index → exit 2 + error logged.
|
||||
3. Cached recipe → prints build system + deps + url.
|
||||
4. Installed up to date → status line "up to date".
|
||||
5. Installed outdated → status "outdated (zuur has <ver>)".
|
||||
6. Not installed → no status line.
|
||||
7. Pool=binary → no recipe section.
|
||||
8. Installed newer → status "newer than zuur".
|
||||
|
||||
### Build verified
|
||||
- `dub build` passes with `warningsAsErrors`.
|
||||
- `dub test` passes — 21 modules, all info unittests pass.
|
||||
- Evidence logged to `.omo/evidence/task-24-tofu-core.log`.
|
||||
|
||||
### main.d integration
|
||||
- Import: `import tofu.commands.info : infoCommand;` (selective, matching `: infoCommand;` since the function is the only export needed).
|
||||
- Dispatch: `case Command.info: return infoCommand(pa.arg, pa, cfg);`
|
||||
- Signature matches: `infoCommand(string, ParsedArgs, Config)` with the 4th param having a default value.
|
||||
|
||||
Reference in New Issue
Block a user