diff options
Diffstat (limited to 'docs/superpowers')
| -rw-r--r-- | docs/superpowers/plans/2026-06-13-check-populate-missing-sections.md | 379 | ||||
| -rw-r--r-- | docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md | 155 |
2 files changed, 534 insertions, 0 deletions
diff --git a/docs/superpowers/plans/2026-06-13-check-populate-missing-sections.md b/docs/superpowers/plans/2026-06-13-check-populate-missing-sections.md new file mode 100644 index 0000000..6d76262 --- /dev/null +++ b/docs/superpowers/plans/2026-06-13-check-populate-missing-sections.md @@ -0,0 +1,379 @@ +# `--check` Populate Missing Sections Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Make `mkhint --check` offer to populate `nvchecker.toml` for hint files that have no `[pkg]` section, instead of silently skipping them. + +**Architecture:** Add a small `_has_nvchecker_section` helper (DRY the existing section-presence grep), refactor `add_nvchecker_section` to use it, then extend `check_updates` to collect missing-section packages during its classify loop and, after the loop, batch-prompt to append sections via the existing `add_nvchecker_section` autodetect. On accept, the run stops with a "review and re-run" message. + +**Tech Stack:** bash, grep, find, sort -V. Tests use the existing mock-based suite (`tests/mkhint_test.sh`). + +--- + +## Background for the implementer + +Read before starting: + +- **Spec:** `docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md` — this plan implements it exactly. +- **Main script:** `mkhint`. Relevant anchors (current line numbers): + - `add_nvchecker_section()` starts at line 266. Its duplicate-guard grep is line 275: + ```bash + if grep -qE "^\[${pkg}\][[:space:]]*$" "$NVCHECKER_CONFIG"; then + ``` + - `check_updates()` starts at line 606. The classify loop is lines 633-648. The "no result" skip is line 638: + ```bash + latest=$(nvchecker_latest "$pkg") || { echo "skip ${pkg}: no nvchecker source"; continue; } + ``` + The "nothing outdated" check is lines 650-653. + - `list_hint_files()` (earlier in the file) locates a package's `.info` with: + ```bash + find "$REPO_DIR" -mindepth 2 -name "${pkg}.info" 2>/dev/null | head -1 + ``` + Reuse this exact pattern. +- **`set -e`** is active. Command substitutions and `read` are safe; `add_nvchecker_section` returns 0. No new unguarded fallible calls are introduced. +- **Test harness:** `tests/mkhint_test.sh`. + - `run_mkhint` sed-patches `REPO_DIR`/`HINT_DIR`/`TMP_DIR`/`NVCHECKER_CONFIG` to mock paths. + - `setup()` creates fixtures including `ghpkg` (github `.info` under `$MOCK_REPO/development/ghpkg/ghpkg.info`) and a base `$MOCK_BASE/nvchecker.toml` containing only `[__config__]`, plus `$MOCK_BASE/new_ver.json` seeded with curl + clion versions. + - Interactive prompts are fed via `< <(printf '...')`. + - Assertions: `assert_contains`, `assert_not_contains`, `assert_file_exists`, `assert_file_not_exists`, `assert_exit_code`. Output-substring checks use the inline `grep -q` + `(( PASS++ ))` pattern (see T24/T27 in the file). + - The current suite has 69 passing assertions (T1–T28). + +## File Structure + +- `mkhint` — `_has_nvchecker_section` helper; `add_nvchecker_section` refactor; `check_updates` missing-section collection + populate prompt. +- `tests/mkhint_test.sh` — T29–T31, plus one orphan fixture for T31. +- `CLAUDE.md` / `README.md` — document the populate prompt. + +Single-file tool; keep everything in `mkhint`. + +--- + +## Task 1: Add `_has_nvchecker_section` helper and refactor `add_nvchecker_section` + +Pure refactor — no behaviour change. Establishes the helper that Task 2 reuses. + +**Files:** +- Modify: `mkhint` (add helper just above `add_nvchecker_section` at line 266; change line 275-278) + +- [ ] **Step 1: Add the helper above `add_nvchecker_section`** + +Immediately before the `# Append an nvchecker [pkg] section...` comment (line 264), add: + +```bash +# Return 0 if NVCHECKER_CONFIG already has a [pkg] section +_has_nvchecker_section() { + local pkg="$1" + [[ -f "$NVCHECKER_CONFIG" ]] || return 1 + grep -qE "^\[${pkg}\][[:space:]]*$" "$NVCHECKER_CONFIG" +} +``` + +- [ ] **Step 2: Use the helper inside `add_nvchecker_section`** + +Replace the duplicate-guard block (currently lines 274-278): + +```bash + # Skip if section already present + if grep -qE "^\[${pkg}\][[:space:]]*$" "$NVCHECKER_CONFIG"; then + echo "nvchecker: [${pkg}] already present in $NVCHECKER_CONFIG" + return 0 + fi +``` + +with: + +```bash + # Skip if section already present + if _has_nvchecker_section "$pkg"; then + echo "nvchecker: [${pkg}] already present in $NVCHECKER_CONFIG" + return 0 + fi +``` + +Note: `add_nvchecker_section` still runs `mkdir -p`/`touch` on the config before this check, so `_has_nvchecker_section`'s `[[ -f ]]` guard is belt-and-suspenders here but matters for Task 2's caller (which checks before any touch). + +- [ ] **Step 3: Syntax check + full suite (no regressions)** + +Run: `bash -n mkhint && bash tests/mkhint_test.sh` +Expected: syntax clean; `Results: 69 passed, 0 failed` (refactor changes nothing observable; T16-T19/T29 not yet added). + +- [ ] **Step 4: Commit** + +```bash +git add mkhint +git commit -m "refactor: extract _has_nvchecker_section helper" +``` + +--- + +## Task 2: Collect missing sections and add the populate prompt in `check_updates` + +**Files:** +- Modify: `mkhint` `check_updates` — classify loop (line 638) and after the loop (before line 650) + +- [ ] **Step 1: Distinguish missing-section from no-result in the classify loop** + +First, declare the `missing_sections` array alongside the other locals. Change line 631: + +```bash + local outdated_pkgs=() outdated_old=() outdated_new=() outdated_flag=() +``` + +to: + +```bash + local outdated_pkgs=() outdated_old=() outdated_new=() outdated_flag=() + local missing_sections=() +``` + +Then replace the no-result skip (line 638): + +```bash + latest=$(nvchecker_latest "$pkg") || { echo "skip ${pkg}: no nvchecker source"; continue; } +``` + +with: + +```bash + if ! latest=$(nvchecker_latest "$pkg"); then + if _has_nvchecker_section "$pkg"; then + echo "skip ${pkg}: no nvchecker result" + else + echo "skip ${pkg}: no nvchecker section" + missing_sections+=("$pkg") + fi + continue + fi +``` + +(`set -e` note: `latest=$(...)` inside an `if !` is a guarded context — the non-zero return does not abort.) + +- [ ] **Step 2: Add the populate prompt after the classify loop** + +The classify loop ends at the `done` (line 648). Immediately after that `done`, and before the `if [[ ${#outdated_pkgs[@]} -eq 0 ]]; then` block (line 650), insert: + +```bash + # Offer to populate nvchecker.toml for packages with no section + if [[ ${#missing_sections[@]} -gt 0 ]]; then + echo "" + echo "${#missing_sections[@]} package(s) have no nvchecker section: ${missing_sections[*]}" + local answer + read -r -p "Populate ${NVCHECKER_CONFIG} now? [Y/n] " answer + answer="${answer:-Y}" + if [[ "$answer" =~ ^[Yy]$ ]]; then + local mp info + for mp in "${missing_sections[@]}"; do + info=$(find "$REPO_DIR" -mindepth 2 -name "${mp}.info" 2>/dev/null | head -1) + if [[ -z "$info" ]]; then + echo "skip ${mp}: no .info found in $REPO_DIR" + continue + fi + add_nvchecker_section "$mp" "$info" + done + echo "" + echo "Sections added. Review $NVCHECKER_CONFIG (fill any stubs), then re-run 'mkhint -C'." + return 0 + fi + fi +``` + +- [ ] **Step 3: Syntax check + full suite (no regressions)** + +Run: `bash -n mkhint && bash tests/mkhint_test.sh` +Expected: syntax clean; `Results: 69 passed, 0 failed`. (Existing `-C` tests T23-T28 all use packages that already have sections or are explicitly named with seeded keyfile entries, so none trigger the new missing-section path. Verify they still pass — if T24's "all up to date" now prints a missing-section prompt instead, investigate: T24 uses `curl` which has a keyfile entry, so it should classify as up-to-date, not missing.) + +- [ ] **Step 4: Commit** + +```bash +git add mkhint +git commit -m "feat: --check offers to populate missing nvchecker sections" +``` + +--- + +## Task 3: Add tests T29–T31 + +**Files:** +- Modify: `tests/mkhint_test.sh` — orphan fixture in `setup()`; T29-T31 before the SUMMARY section + +- [ ] **Step 1: Add an orphan hint fixture path note** + +T31 needs a package that has a hint file but NO `.info` anywhere in `MOCK_REPO`. We create the hint file inline in the test (no `.info`), so no `setup()` change is strictly required. No fixture edit needed — proceed to the tests. + +- [ ] **Step 2: Add T29 — accept populate, github section written, run stops, hint unchanged** + +In `tests/mkhint_test.sh`, find the T28 block (the last test, `assert_contains "scan-all updated curl"`), which is immediately before: + +```bash +# ─── SUMMARY ────────────────────────────────────────────────────────────────── +teardown +``` + +Insert the following three test blocks between the end of T28 and the `# ─── SUMMARY` line: + +```bash +# ── T29: --check missing section, accept populate → section added, run stops ─── +echo "" +echo "T29: --check missing section, accept populate → github section appended, no update" +# ghpkg has a github .info in MOCK_REPO but no [ghpkg] in toml and not in keyfile. +# Reset toml to only [__config__] so ghpkg is genuinely missing. +cat > "$MOCK_BASE/nvchecker.toml" << EOF +[__config__] +oldver = "$MOCK_BASE/old_ver.json" +newver = "$MOCK_BASE/new_ver.json" +EOF +cat > "$MOCK_BASE/new_ver.json" << 'EOF' +{ "version": 2, "data": {} } +EOF +rm -f "$MOCK_HINT"/*.hint "$MOCK_HINT"/*.bak 2>/dev/null +cat > "$MOCK_HINT/ghpkg.hint" << 'EOF' +VERSION="1.0.0" +ARCH="x86_64" +DOWNLOAD="https://github.com/someowner/ghpkg/archive/v1.0.0/ghpkg-1.0.0.tar.gz" +MD5SUM="11111111111111111111111111111111" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +EOF +out=$(run_mkhint -C ghpkg < <(printf 'Y\n') 2>&1) +assert_contains "ghpkg section appended" "$MOCK_BASE/nvchecker.toml" '\[ghpkg\]' +assert_contains "github source detected" "$MOCK_BASE/nvchecker.toml" 'source = "github"' +echo "$out" | grep -q "Review .*re-run" \ + && { echo " PASS: review/re-run message shown"; (( PASS++ )); } \ + || { echo " FAIL: review message missing"; echo "$out" | sed 's/^/ /'; (( FAIL++ )); ERRORS+=("T29 review msg"); } +assert_contains "ghpkg hint version unchanged" "$MOCK_HINT/ghpkg.hint" 'VERSION="1.0.0"' + +# ── T30: --check missing section, decline populate → no section added ────────── +echo "" +echo "T30: --check missing section, decline populate → nothing added" +cat > "$MOCK_BASE/nvchecker.toml" << EOF +[__config__] +oldver = "$MOCK_BASE/old_ver.json" +newver = "$MOCK_BASE/new_ver.json" +EOF +cat > "$MOCK_BASE/new_ver.json" << 'EOF' +{ "version": 2, "data": {} } +EOF +rm -f "$MOCK_HINT"/*.hint "$MOCK_HINT"/*.bak 2>/dev/null +cat > "$MOCK_HINT/ghpkg.hint" << 'EOF' +VERSION="1.0.0" +ARCH="x86_64" +DOWNLOAD="https://github.com/someowner/ghpkg/archive/v1.0.0/ghpkg-1.0.0.tar.gz" +MD5SUM="11111111111111111111111111111111" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +EOF +run_mkhint -C ghpkg < <(printf 'n\n') >/dev/null 2>&1 +assert_not_contains "no ghpkg section after decline" "$MOCK_BASE/nvchecker.toml" '\[ghpkg\]' + +# ── T31: --check missing section, no .info in repo, accept → skipped, no section +echo "" +echo "T31: --check missing section but no .info → skipped, no section added" +cat > "$MOCK_BASE/nvchecker.toml" << EOF +[__config__] +oldver = "$MOCK_BASE/old_ver.json" +newver = "$MOCK_BASE/new_ver.json" +EOF +cat > "$MOCK_BASE/new_ver.json" << 'EOF' +{ "version": 2, "data": {} } +EOF +rm -f "$MOCK_HINT"/*.hint "$MOCK_HINT"/*.bak 2>/dev/null +# orphanpkg has NO .info anywhere in MOCK_REPO +cat > "$MOCK_HINT/orphanpkg.hint" << 'EOF' +VERSION="3.0.0" +ARCH="x86_64" +DOWNLOAD="https://example.com/orphanpkg-3.0.0.tar.gz" +MD5SUM="44444444444444444444444444444444" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +EOF +out=$(run_mkhint -C orphanpkg < <(printf 'Y\n') 2>&1) +echo "$out" | grep -q "no .info found" \ + && { echo " PASS: no .info reported"; (( PASS++ )); } \ + || { echo " FAIL: 'no .info found' not in output"; echo "$out" | sed 's/^/ /'; (( FAIL++ )); ERRORS+=("T31 no info"); } +assert_not_contains "no orphanpkg section added" "$MOCK_BASE/nvchecker.toml" '\[orphanpkg\]' +``` + +- [ ] **Step 3: Run the full suite** + +Run: `bash tests/mkhint_test.sh` +Expected: all PASS including T29-T31; `Results: N passed, 0 failed` (N = 75: 69 + 6 new assertions). + +If a test fails, debug with superpowers:systematic-debugging. Likely culprits: stdin line count (T29/T31 supply exactly one `Y`/one line — there is no slackrepo prompt because the run returns 0 right after populate), or the `grep -q "Review .*re-run"` pattern not matching the exact message string (the message is `Sections added. Review <path> (fill any stubs), then re-run 'mkhint -C'.`). + +- [ ] **Step 4: Commit** + +```bash +git add tests/mkhint_test.sh +git commit -m "test: add T29-T31 for --check populate missing sections" +``` + +--- + +## Task 4: Document the populate prompt + +**Files:** +- Modify: `CLAUDE.md`, `README.md` + +- [ ] **Step 1: Update CLAUDE.md** + +In the "Key Behaviors" section, find the bullet describing `--check`/`-C`. Append a sentence (or a sub-bullet) stating: when `--check` encounters hint files with no `[pkg]` section in `nvchecker.toml`, it lists them and prompts once to populate the config; on accept it appends sections via `add_nvchecker_section` (github/pypi autodetect, else stub), prints a "review and re-run" message, and stops the run without applying updates. Packages whose `.info` cannot be found in `REPO_DIR` are skipped. + +Add a test-coverage table row group: + +``` +| T29 | `--check` missing section, accept populate — github section appended, run stops, hint unchanged | +| T30 | `--check` missing section, decline populate — nothing added | +| T31 | `--check` missing section, no `.info` in repo — skipped, no section added | +``` + +- [ ] **Step 2: Update README.md** + +In the `--check` documentation section, add a short paragraph: if any scanned hint has no nvchecker source configured, `mkhint --check` offers to populate `nvchecker.toml` for them (auto-detecting github/pypi from the SBo `.info`, otherwise writing a commented stub to fill in). After populating it asks you to review the file and re-run `mkhint -C`. + +- [ ] **Step 3: Commit** + +```bash +git add CLAUDE.md README.md +git commit -m "docs: document --check populate-missing-sections prompt" +``` + +--- + +## Task 5: Final verification + +- [ ] **Step 1: Syntax + full suite** + +Run: `bash -n mkhint && bash tests/mkhint_test.sh` +Expected: clean; `Results: 75 passed, 0 failed`. + +- [ ] **Step 2: Manual smoke — empty toml, decline** + +Run: +```bash +tmpcfg=$(mktemp); printf '[__config__]\noldver="/tmp/o.json"\nnewver="/tmp/n.json"\n' > "$tmpcfg" +echo '{"version":2,"data":{}}' > /tmp/n.json +HOME=$HOME bash -c 'true' # noop, just confirming environment +``` +(The real manual path requires nvchecker/jq installed; the mock suite already covers behaviour. This step is optional if tools are absent — the suite is authoritative.) + +- [ ] **Step 3: Confirm no stray TODO/debug** + +Run: `grep -n "TODO\|XXX\|DEBUG" mkhint` +Expected: only the intentional stub-template `# TODO: configure nvchecker source` inside `add_nvchecker_section`. + +- [ ] **Step 4: Spec compliance review** + +Use superpowers:requesting-code-review (or self-review) against +`docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md`. +Confirm: missing-section detection, batch prompt, `.info` lookup + skip on absent, +`add_nvchecker_section` reuse, `return 0` stop with review message, T29-T31 present and passing. + +--- + +## Self-Review notes (author) + +- **Spec coverage:** §"Detect missing sections" → Task 2 Step 1 + Task 1 helper. §"Offer to populate" → Task 2 Step 2. `.info` lookup + skip → Task 2 Step 2 (find + empty check). Reuse of `add_nvchecker_section` → Task 2 Step 2. `return 0` stop → Task 2 Step 2. Decline fall-through → preserved (no change to outdated path). Tests T29-T31 → Task 3. Docs → Task 4. +- **Placeholder scan:** none. T31 Step 1 explicitly states no fixture edit needed (not a deferred TODO). +- **Name consistency:** `_has_nvchecker_section`, `missing_sections`, `add_nvchecker_section`, `NVCHECKER_CONFIG`, `REPO_DIR` consistent across Tasks 1-3 and matching the existing codebase. +- **set -e:** the one new fallible call (`latest=$(nvchecker_latest ...)`) is wrapped in `if !`. `find` is in a command substitution. `add_nvchecker_section` returns 0. Safe. +- **Assertion count:** T29 = 4 (toml header, source, review msg, hint unchanged), T30 = 1, T31 = 2. 7 new... recount: T29 adds 4 PASS, T30 adds 1, T31 adds 2 → 7. Plan Step 3 says N=75 (69+6). CORRECTED: expected total is 76 (69 + 7). Implementer: assert on the actual printed total, not a hardcoded number — the suite prints `Results: <PASS> passed, <FAIL> failed`; the pass criterion is `0 failed`. diff --git a/docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md b/docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md new file mode 100644 index 0000000..3a8b42a --- /dev/null +++ b/docs/superpowers/specs/2026-06-13-check-populate-missing-sections-design.md @@ -0,0 +1,155 @@ +# `--check` populate missing nvchecker sections — design + +Date: 2026-06-13 + +## Summary + +When `mkhint --check` / `-C` scans hint files, packages that have no `[pkg]` +section in `nvchecker.toml` are currently skipped silently-ish (`skip pkg: no +nvchecker source`). On a fresh/empty `nvchecker.toml` this means *every* hint is +skipped and the command does nothing useful. + +This feature makes `--check` detect those missing-section packages and, after the +scan, offer to populate `nvchecker.toml` by appending sections for them (reusing +the existing `add_nvchecker_section` autodetect logic). If the user accepts, the +sections are written and the run stops with a message telling the user to review +the file (fill any stubs) and re-run `mkhint -C`. + +## Motivation + +`add_nvchecker_section` already exists and is called on `--new`. `--check` should +give the user a path to bootstrap nvchecker config for hints created before this +integration existed, without hand-editing the TOML for every package. + +## Behaviour + +Implemented inside the existing `check_updates` function. + +### 1. Detect missing sections during the classify loop + +The classify loop currently does, per target package: + +```bash +latest=$(nvchecker_latest "$pkg") || { echo "skip ${pkg}: no nvchecker source"; continue; } +``` + +Change so the "no result" case distinguishes two situations: + +- A `[pkg]` section **exists** in `NVCHECKER_CONFIG` but nvchecker produced no + version → genuine "no result", keep the existing skip message + (`skip ${pkg}: no nvchecker result`). +- A `[pkg]` section is **missing** → add `pkg` to a `missing_sections` array and + print `skip ${pkg}: no nvchecker section` (do not classify it as outdated). + +Section presence is tested with the same pattern `add_nvchecker_section` uses, +extracted into a small shared helper: + +```bash +# Return 0 if NVCHECKER_CONFIG has a [pkg] section +_has_nvchecker_section() { + local pkg="$1" + grep -qE "^\[${pkg}\][[:space:]]*$" "$NVCHECKER_CONFIG" +} +``` + +`add_nvchecker_section` is updated to call `_has_nvchecker_section` instead of its +inline `grep` (pure DRY refactor, no behaviour change). + +### 2. Offer to populate, after the classify loop + +After the classify loop completes and before the "nothing outdated" / report +logic, insert: + +```bash +if [[ ${#missing_sections[@]} -gt 0 ]]; then + echo "" + echo "${#missing_sections[@]} package(s) have no nvchecker section: ${missing_sections[*]}" + local answer + read -r -p "Populate ${NVCHECKER_CONFIG} now? [Y/n] " answer + answer="${answer:-Y}" + if [[ "$answer" =~ ^[Yy]$ ]]; then + local mp info + for mp in "${missing_sections[@]}"; do + info=$(find "$REPO_DIR" -mindepth 2 -name "${mp}.info" 2>/dev/null | head -1) + if [[ -z "$info" ]]; then + echo "skip ${mp}: no .info found in $REPO_DIR" + continue + fi + add_nvchecker_section "$mp" "$info" + done + echo "" + echo "Sections added. Review $NVCHECKER_CONFIG (fill any stubs), then re-run 'mkhint -C'." + return 0 + fi +fi +``` + +Key points: + +- Single batch prompt (not per package). Default Yes. +- For each missing package, the `.info` is located in `REPO_DIR` with the same + `find` pattern `list_hint_files` already uses. + - No `.info` found → print `skip ${mp}: no .info found in $REPO_DIR`, do not add + a section. + - `.info` found → call `add_nvchecker_section "$mp" "$info"`, which appends a + github/pypi section if detected, otherwise a commented stub. (Its own + duplicate guard via `_has_nvchecker_section` makes this safe.) +- After populating, **stop the run** (`return 0`) with the review message. The + newly added sections are not queried this run — the user reviews/fills stubs + first, then re-runs. (Decision: simple separation over one-shot convenience.) +- If the user declines, fall through to the normal report path. The + missing-section packages were already excluded during classify, so they simply + don't appear as outdated. + +### Interaction with the outdated set + +A run can have both outdated packages (with sections) and missing-section +packages. If the user accepts populate, the run stops *before* applying any +outdated updates — so populate takes precedence and the user re-runs to pick up +updates afterward. This is acceptable: it keeps each run's effect simple and +predictable. If the user declines populate, outdated updates proceed as today. + +## Affected code + +- `mkhint`: + - New helper `_has_nvchecker_section`. + - `add_nvchecker_section` refactored to use it (no behaviour change). + - `check_updates`: `missing_sections` array, distinguished skip messages, the + populate prompt block. +- `tests/mkhint_test.sh`: T29–T31. +- `CLAUDE.md` / `README.md`: document the populate prompt under `--check`. + +No new dependencies, no new flags, no exit-code changes. + +## Testing + +Mock-based, as existing suite. The mock nvchecker keyfile (`new_ver.json`) only +contains versions for packages we want "found"; a package absent from the keyfile +AND absent from the TOML is a missing-section case. + +| ID | Scenario | +|-----|----------| +| T29 | `-C`, hint with no section, github `.info`, accept populate → github section appended, run stops with review message, hint NOT updated | +| T30 | `-C`, hint with no section, decline populate → no section added, no error (normal skip path) | +| T31 | `-C`, hint with no section, no `.info` in repo, accept populate → `skip ... no .info found`, no section added | + +Test mechanics: + +- T29 uses a package that has a `.info` with a github HOMEPAGE/DOWNLOAD in + `MOCK_REPO` (the existing `ghpkg` fixture) but **no** `[ghpkg]` line in the test + `nvchecker.toml` and **no** entry in `new_ver.json`. After `printf 'Y\n'`, + assert the TOML now contains `[ghpkg]` + `source = "github"`, assert output + contains the review message, assert the hint file VERSION is unchanged. +- T30 uses the same setup but `printf 'n\n'`; assert TOML still has no `[ghpkg]`. +- T31 uses a package name with a hint file but no matching `.info` anywhere in + `MOCK_REPO` (e.g. a hand-written `orphan.hint`); after `printf 'Y\n'`, assert + output contains `no .info found` and TOML has no `[orphan]` section. + +## Self-review notes + +- Reuses `add_nvchecker_section` and the `find` pattern from `list_hint_files` — + no new mechanisms. +- `_has_nvchecker_section` is the only new unit; DRYs an existing grep. +- `set -e` safety: `find ... || head` is in a command substitution (non-fatal); + `add_nvchecker_section` returns 0; `read` is fine. No unguarded fallible calls. +- Scope: single function change plus one helper plus three tests. Single plan. |
