Skip to content

ignore: fix dangling backslash error for escaped trailing space with extra spaces - #3515

Open
HarnageaGabriel wants to merge 1 commit into
BurntSushi:masterfrom
HarnageaGabriel:fix/issue-3477-gitignore-trailing-space
Open

ignore: fix dangling backslash error for escaped trailing space with extra spaces#3515
HarnageaGabriel wants to merge 1 commit into
BurntSushi:masterfrom
HarnageaGabriel:fix/issue-3477-gitignore-trailing-space

Conversation

@HarnageaGabriel

Copy link
Copy Markdown

Fixes #3477.

Problem

Git's gitignore trailing-whitespace handling only strips unescaped trailing spaces. An escaped trailing space (\ at the end of a pattern) is preserved even if followed by additional plain trailing spaces, e.g. a line consisting of foo + backslash + three spaces still keeps one escaped space after trimming (matches git check-ignore's behavior of foo\ -> matches foo ).

ripgrep's GitignoreBuilder::add_line only special-cased a line ending in exactly one \ (backslash immediately followed by a single space):

if !line.ends_with("\ ") {
    line = line.trim_right();
}

When there are extra unescaped spaces after the escaped one, the line no longer ends with \ (it ends with plain spaces), so it falls through to an unconditional trim_right(), which strips the escaped space too and leaves a dangling backslash — causing a parse error instead of ripgrep silently ignoring the pattern like git does.

Repro (from the issue)

$ printf 'foo\   \n' > .gitignore   # foo, backslash, three spaces
$ rg hi
rg: ./.gitignore: line 1: error parsing glob 'foo\': dangling '\'

Real git accepts this and ignores a file named foo (with trailing space).

Fix

Added trim_trailing_unescaped_spaces, a small byte-safe port of git's own trim_trailing_spaces() (dir.c): scan the line, treat \ + next byte as a consumed escaped pair (resetting any pending trailing-space run), track the start of a run of plain trailing spaces, and truncate at that point at the end of the scan (preserving a dangling backslash — with nothing to escape — as-is, matching git's early-return behavior for that case). This replaces the old ends_with("\ ") special case.

Verified against the reporter's exact repro plus manual testing with a real rg build: foo is now ignored while foo (no trailing space) and foo (extra unescaped trailing spaces) are not, matching git check-ignore output.

Testing

  • Added three regression tests in crates/ignore/src/gitignore.rs: the reporter's exact multi-space repro, a plain-trailing-space-only regression check, and the pre-existing single escaped-space case.
  • cargo test -p ignore: 191 passed.
  • cargo test --workspace: all passing except two pre-existing, unrelated Windows-only symlink-privilege test failures (misc::symlink_nofollow, regression::r1389_bad_symlinks_no_biscuit) caused by the local environment lacking the symlink-creation privilege — unrelated to this change.
  • Manual end-to-end repro with a built rg binary confirms git-matching behavior.

Note: a previous attempt at this fix (#3485) was opened and later closed by its own author; this is a fresh implementation using git's actual trimming algorithm as the reference rather than a heuristic patch.

…extra spaces

Git's gitignore trailing-whitespace trimming only strips unescaped
trailing spaces, preserving one escaped space (backslash+space) even
when followed by further plain trailing spaces. ripgrep's previous
check only handled a line ending in exactly one "\ " and otherwise
did a blind trim_right(), which stripped the escaped space too,
leaving a dangling backslash and a parse error.

Add trim_trailing_unescaped_spaces(), a byte-safe port of git's
trim_trailing_spaces() (dir.c), and use it in GitignoreBuilder::add_line.

Fixes BurntSushi#3477
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.

Escaped trailing space in .gitignore causes dangling \ error (differs from git)

1 participant