fix(grep): use portable --null in system grep fallback (BSD/macOS)#2405
Conversation
45de9a5 to
1c97cea
Compare
|
Hi! Just rebased this onto the latest Good news: the fix still applies cleanly. The
No rush at all, but whenever you have a spare moment I'd really appreciate a look — it's a small, self-contained change. Thanks so much for maintaining rtk! @aeppling, and cc @KuSh since it touches the fallback path from #2333. |
The system-grep fallback (used when ripgrep is not installed) passed -rnHZ, relying on -Z for the NUL filename separator the match parser requires. -Z only means --null on GNU grep; on BSD/macOS grep it is an alias for --decompress (zgrep mode), so output is plain file:line:content with no NUL. parse_match_line() then matches zero filenames and every result collapses into "N matches in 0 files" with all lines hidden behind [+N more]. Use the long option --null instead, which both GNU and BSD grep define as "print a zero-byte after the file name". Related to rtk-ai#2310 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1c97cea to
ad464a2
Compare
Problem
On macOS/BSD systems without ripgrep installed,
rtk grepprintsN matches in 0 files:followed by[+N more]— the match count is right, but zero matched lines are shown, with exit code 0. Reported in #2310 (see also #2387).Repro on a default macOS install (no
rgon PATH):Root cause
When
rgis unavailable, the fallback runsgrep -rnHZ <pattern> <path>, relying on-Zto NUL-separate the filename — which is whatparse_match_line()hard-requires (^([^\x00]+)\x00(\d+):(.*)$, introduced for #1436).-Zonly means--nullon GNU grep. On BSD/macOS grep,-Zis an alias for--decompress(zgrep mode), so output is plainfile:line:contentwith no NUL byte. Every line then fails to parse:total_matchescounts raw lines (correct count), butby_filestays empty → "0 files", and all content is suppressed into[+N more]. The bug is invisible on Linux and silently breaks every default macOS install without ripgrep.Fix
Use the long option
--null, which GNU and BSD grep both define as "print a zero-byte after the file name" (verified against both man pages). The fallback flags are extracted into aGREP_FALLBACK_FLAGSconstant so tests can assert portability.Tests
test_grep_fallback_uses_portable_null_flag— regression guard: asserts--nullis used,-Zis not, and flags stay un-bundled (so a future-rnHZ-style bundle can't sneak-Zback in).test_grep_fallback_output_is_nul_separated_and_parseable— runs the real system grep with the fallback flags against a fixture and asserts the output contains NUL and parses viaparse_match_line(). Skips gracefully if grep is absent.Verified locally on macOS (BSD grep, Apple Silicon):
cargo fmt --all && cargo clippy --all-targets && cargo test --all→ clippy clean, 2154 tests pass, including both new tests against the actual BSD grep this bug ships on.Related to #2310: that report says non-recursive
rtk grepbreaks while-rworks, which suggests the reporter may have a partial-rgenvironment — but the "N matches in 0 files + hidden lines" symptom is produced exactly and only by NUL-less underlying output, and this fixes the macOS no-ripgrep case of it.🤖 Generated with Claude Code