fix(complete): use type -P so the CLI-presence guard ignores shell functions - #760
Conversation
…functions `type -p` returns exit status 0 for a shell function (it just prints nothing), so the generated bash completion guard passed even when the usage CLI was not installed. Environments that define a `usage` shell function — oh-my-bash does — therefore fell through the guard and failed later with an unrelated error. `type -P` forces a PATH search. The same file already used `type -P` for command path resolution; only the guards were missed.
📝 WalkthroughWalkthroughCompletion scripts now require an executable ChangesCompletion executable lookup
Estimated code review effort: 2 (Simple) | ~15 minutes Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryUpdates generated Bash and Fish completions to distinguish external executables from shell functions.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains. Important Files Changed
Reviews (2): Last reviewed commit: "fix(complete): stop shell functions from..." | Re-trigger Greptile |
|
Thanks for digging into this. The Bash Local behavior testing on this PR found two remaining gaps:
The existing checks all pass locally—10 completion unit tests, 4 shell completion integration tests, and 3 completion-init integration tests—but none exercises these collision cases. I’d add function-only and function-shadowing-executable behavioral tests for the changed Bash/Fish paths. For historical context, AI-assisted — Tool: Codex; model: unavailable; version: unavailable. |
Follow-up to the `type -P` guard fix, covering two collision cases the guard alone does not: - `complete_fish_init()` still probed with `type -q`, which succeeds on a shell function just like `type -p` did. Use `type -P`. - The guard only proves an executable exists, not that a bare `usage` would reach it. A shell function shadowing a real executable still intercepted `usage --usage-spec`, so the spec file was filled with the function`s output. The shipped completions now call `command usage`. Left caller-provided `--usage-cmd` strings alone (nu prefixes them with `^`, so blanket rewriting would break). Adds behavioral tests for both cases on the bash and fish paths.
Dismissed because a newer commit was pushed; Greptile will re-review the current head.
|
Thanks — both gaps confirmed and fixed in 097e6fc. ① ② Function shadowing an executable — I reproduced this locally before fixing: with a real ③ Tests — six behavioral tests added to Also useful context on that revert history: I verified Verified locally: completion unit tests, clippy, fmt. The bash integration tests don't run on my Windows box (pre-existing path-quoting issue that also breaks the existing |
|
can you actually test fish too? |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
cli/tests/shell_completions_integration.rs (1)
1403-1713: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider extracting shared boilerplate for the new collision tests.
All six new tests repeat the same pattern: create a labeled temp dir, write a shell test script, spawn the interpreter, capture stdout/stderr, then remove the temp dir. The two guard-rejection tests (bash at Lines 1415-1427, fish at Lines 1577-1589) also duplicate the same
generate completion <shell> testcli --usage-bin usage_guard_probe --usage-cmd "command usage_guard_probe --usage-spec"invocation.Extract a small helper, for example
fn run_shell_test_script(shell: &str, temp_dir: &Path, script: &str) -> Output, to reduce duplication and make future collision tests easier to add.This is not required before merge; the tests are correct as written.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cli/tests/shell_completions_integration.rs` around lines 1403 - 1713, Extract shared test helpers for the repeated shell-test setup and completion-generation flow in the six collision tests. Add a helper such as run_shell_test_script to create the script, invoke the selected interpreter, and return its Output, and reuse a second helper for the common guard completion generation used by the bash and fish guard tests. Update the affected tests to use these helpers while preserving their existing assertions and cleanup behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@cli/tests/shell_completions_integration.rs`:
- Around line 1403-1713: Extract shared test helpers for the repeated shell-test
setup and completion-generation flow in the six collision tests. Add a helper
such as run_shell_test_script to create the script, invoke the selected
interpreter, and return its Output, and reuse a second helper for the common
guard completion generation used by the bash and fish guard tests. Update the
affected tests to use these helpers while preserving their existing assertions
and cleanup behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Central YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: b8b969a9-f0a3-45ac-9b84-7d7961cca567
⛔ Files ignored due to path filters (1)
lib/src/complete/snapshots/usage__complete__fish__tests__complete_fish_init.snapis excluded by!**/*.snap
📒 Files selected for processing (6)
cli/assets/completions/_usagecli/assets/completions/usage.bashcli/assets/completions/usage.fishcli/tests/shell_completions_integration.rslib/src/complete/fish.rsmise.toml
🚧 Files skipped from review as they are similar to previous changes (3)
- cli/assets/completions/usage.fish
- lib/src/complete/fish.rs
- cli/assets/completions/usage.bash
|
Yes — ran it for real this time, in a Linux container with fish 3.6.0 installed. Full Raw flag semantics on fish 3.6.0, function named
Same shape as bash, so both call sites were affected — To confirm the new tests actually discriminate, I reverted each fix in isolation and re-ran under fish: per-bin guard (function only, no CLI) init guard self-completion, function shadowing a real executable So all three fixes are load-bearing and each new test fails without its fix. |
Problem
The generated bash completion opens with a guard that is supposed to bail out when the
usageCLI isn't installed:But
type -preturns exit status 0 for a shell function — it only suppresses the path output. So in any environment that defines a shell function namedusage, the guard passes even with no CLI on$PATH, and the completion fails further down with an unrelated error.Measured on GNU bash 5.2.21(1)-release and 5.3.15(1)-release:
type -p usagetype -P usageusageshell function defined, no CLI on$PATHRepro:
command -vis not an alternative — it finds functions too.Sourcing the current
cli/assets/completions/usage.bashwith ausagefunction defined and no CLI:With this patch it does what it was meant to do:
Fix
type -p→type -Pin the two bash guards:lib/src/complete/bash.rs— the leading guard incomplete_bash()lib/src/complete/bash.rs— the guard insidecomplete_bash_init()'s usage-shebang branch. Same defect: a function makes the branch taken, and thecommand usage ...on the next line bypasses the function, so it fails on the missing external command.Note that
complete_bash_init()already usedtype -Pfor command path resolution:So this is restoring consistency rather than introducing a new convention — the guards were simply missed.
I also changed the equivalent guard in
lib/src/complete/fish.rs, since fish draws the same-p(prints nothing for functions and builtins) /-P, --force-path($PATHonly, implies-f) distinction. Caveat: I could not run fish to measure its exit status directly — this one is by analogy with the bash behaviour above, so please push back if fish differs.Snapshots and the checked-in
cli/assets/completions/{usage.bash,usage.fish}are regenerated; the generated files were verified byte-identical to fresh generator output.Deliberately not changed
lib/src/complete/zsh.rs) — zsh'stype -piswhence -p, which already forces a$PATHsearch and ignores functions, aliases and builtins. It is correct as written; switching it to-Pwould break it.complete_fish_init()'stype -q—-qalso matches functions, so it likely has the same class of issue, but the replacement (type -qP?command -q?) deserves someone with a fish setup to verify. Happy to follow up separately.which) and powershell (Get-Command) use native lookups and are unaffected.Downstream
mise's
completions/mise.bashis generated by this code, and its line 3 is currentlyif ! type -p usage &> /dev/null; then. jdx/mise discussion #5358 reports exactly this symptom — an oh-my-bashusageshell function colliding with the completion — and is resolved by this fix once mise picks up the next usage release.Verification
cargo test -p usage-lib --all-features complete::— 10 passed, no pending.snap.newcargo clippy --all --all-features -- -D warnings— cleancargo fmt --all -- --check— cleanusage g completion {bash,fish,zsh} usage --usage-cmd "usage --usage-spec"diffed against the checked-in assets — identical (zsh unchanged)usageshell function defined and no CLI on$PATH; the guard now errors and returns 1 (transcript above)Summary by CodeRabbit
usagecommands.usageexecutable.