Skip to content

fix(grep): allow hyphens in extension-less file paths - #2202

Open
albatrossflyon-coder wants to merge 2 commits into
dandavison:mainfrom
albatrossflyon-coder:fix/grep-hyphen-in-path-no-extension
Open

fix(grep): allow hyphens in extension-less file paths#2202
albatrossflyon-coder wants to merge 2 commits into
dandavison:mainfrom
albatrossflyon-coder:fix/grep-hyphen-in-path-no-extension

Conversation

@albatrossflyon-coder

Copy link
Copy Markdown
Contributor

Fixes #2144

Root cause

The fallback heuristic regex used when a grep-matched file has no recognizable extension (GREP_LINE_REGEX_ASSUMING_NO_INTERNAL_SEPARATOR_CHARS) forbids :, -, and = anywhere inside the file path, on the assumption that those are always separator characters. Real paths routinely contain hyphens (e.g. foo-bar), which caused the path to be split at the hyphen instead of the real : separator:

$ git grep content
foo-bar:content        # correct raw output
$ git grep content | delta
foo:bar:content          # wrong -- hyphen misparsed as a separator

Fix

Adds a new regex tier (WithoutFileExtension), tried after the extension-based regexes and before the strictest fallback. Its path character class only forbids : (matching what the extension-based regexes already permit), rather than also forbidding -/=. Since the path can never consume a literal colon, the parse stays unambiguous -- the path is forced to end at the real : separator no matter how many hyphens it contains.

This also un-ignores test_parse_grep_n_match_file_name_with_dashes_and_no_extension, a pre-existing test in this file marked #[ignore] // This fails: we can't parse it currently -- same bug class, fixed by the same change. Added a second regression test covering the exact no-line-number repro from #2144.

Testing

  • cargo test --workspace: 416 passed, 7 ignored (were 415/8 before this change) -- zero failures, zero regressions.
  • cargo fmt --check: clean.
  • cargo clippy: currently fails on this repo, but only on pre-existing issues in files this PR doesn't touch (wrapping.rs, git_config/mod.rs, subcommands/diff.rs, utils/process.rs) -- confirmed via git diff --stat that this PR only touches src/handlers/grep.rs.

Fixes dandavison#2144

The fallback heuristic regex used when a grep-matched file has no
recognizable extension (GREP_LINE_REGEX_ASSUMING_NO_INTERNAL_SEPARATOR_CHARS)
forbade ':', '-', and '=' anywhere inside the file path, on the assumption
that those are always separator characters. Real paths routinely contain
hyphens (e.g. foo-bar), which caused the path to be split at the hyphen
instead of the real ':' separator -- 'foo-bar:content' misparsed as
path='foo', producing 'foo:bar:content' in the rendered output.

Adds a new regex tier (WithoutFileExtension), tried after the
extension-based regexes and before the strictest fallback, whose path
class only forbids ':' (matching what the extension-based regexes already
permit) rather than forbidding '-'/'=' as well. Since the middle path
class can never consume a literal colon, the parse is still unambiguous:
the path is forced to end at the real ':' separator regardless of how
many hyphens it contains.

This also un-ignores test_parse_grep_n_match_file_name_with_dashes_and_no_extension,
a pre-existing test in this file marked '#[ignore] // This fails: we
can't parse it currently' -- the same bug class, now fixed by the same
change. Added a second regression test for the exact no-line-number repro
from the issue.

Verified: cargo test --workspace -- 416 passed, 7 ignored (were 415/8
before), zero failures. cargo fmt --check clean. cargo clippy currently
fails on this repo, but only on pre-existing issues in unrelated files
(wrapping.rs, git_config/mod.rs, subcommands/diff.rs, utils/process.rs) --
confirmed via git diff --stat that this PR touches only src/handlers/grep.rs.
…ches

Fixes dandavison#2042

rg --json -l (and plain rg -l/--files-with-matches) ignores --json
entirely and emits a bare path per line, with no separator and no
code/match content at all. Delta's grep-line heuristic regexes assume
every line has a path+separator+code structure, so a bare filename
that happens to contain a hyphen (e.g. 'test-1') gets misparsed as
path='test' + separator '-' + code='1', corrupting the output
('test-1' -> 'test:1').

This is fundamentally different from dandavison#2144/dandavison#2202: there the ambiguity
was resolvable from the string alone once colons were treated as an
unambiguous anchor. Here there is no separator character in the input
at all -- the string is just a path, full stop. No regex heuristic can
correctly infer that from the bare text; it requires knowing that -l
was passed.

To fix this, CallingProcess::OtherGrep now carries a CommandLine
(mirroring GitGrep, which already tracks options this way for the
-h/--no-filename fix in dandavison#2202/dandavison#2194). This makes rg's own flags
visible to the grep handler for the first time. When -l or
--files-with-matches is detected, parse_grep_line now treats the
whole line as a bare path (LineType::FileHeader, previously defined
but never actually constructed anywhere) instead of attempting
separator-based parsing at all.

Verified with a real reproduction: rg --json -l genuinely emits plain
filenames, not JSON (confirmed empirically), so this path is real, not
theoretical. Since the underlying process-detection couldn't be
reproduced live in this environment, verification is via a
deterministic unit test using delta's own FakeParentArgs test harness
(the same mechanism delta's own test suite uses to avoid depending on
live process introspection).

Testing:
- cargo test --workspace: 417 passed, 7 ignored, 0 failed (no
  regressions; two new tests: the -l/CommandLine behavior in
  handlers::grep, and calling-process detection for 'rg -l' in
  utils::process).
- cargo fmt --check: clean.
- cargo clippy: pre-existing repo-wide failures only (git_config/mod.rs,
  subcommands/diff.rs, features/side_by_side.rs, handlers/diff_header.rs,
  handlers/merge_conflict.rs, options/set.rs, wrapping.rs,
  features/hyperlinks.rs, and 4 needless-borrow hits in
  utils/process.rs at lines unrelated to this change) -- confirmed via
  git diff --stat that this PR only touches src/handlers/grep.rs and
  src/utils/process.rs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐛 git grep output incorrect for files with hyphen in path

1 participant