Fix inconsistent handling of gitignore patterns like foo*bar #1093
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
(This is kind of related to #762, but not exactly. The issue was present before that was merged. I don't think anyone's ever complained, though, because there's no test for it.)
In the
ignore
crate, there's a check for a literal/
ingitignore
patterns. If there is one,literal_separator
is set totrue
, preventing*
from matching slashes; if there's not,*
is allowed to match slashes.Whether the
*
matches slashes doesn't really matter either way for patterns like*foo
andfoo*
, but it's pretty important forfoo*bar
. In that case (withoutliteral_separator
), thegitignore
matcher will return a successful match for bothfoobazbar
andfoo/baz/bar
.Git itself does not seem to treat
gitignore
patterns like this (tested 2.17.1 and 2.19.1).You can run the following in the root of the ripgrep repo to demonstrate this:
The
rg
command lists almost all of the Rust source files in the repo, becauses*.rs
withoutliteral_separator
matchessrc/whatever.rs
. Thegit
command lists only Rust source files that actually start with ans
.With this change, both commands produce the same output.
I think
ignore
's current behaviour is the result of attempting to account for the apparent distinction being made by these two bullet points in thegitignore
documentation:Someone obviously felt the need to split these two scenarios out here, suggesting there's a difference, but whatever that might be isn't really communicated at all.
The first point kind of suggests, with the 'match against the pathname' bit, that it should be matched against the full relative path, but that's actually the opposite of how it behaves, which is evidenced in the
ignore
crate by the way it (correctly) treats patterns without a slash as having**/
prepended to them.Both points also use the phrase 'treats ... as a shell glob', and the second one clarifies that, in a shell glob,
*
doesn't match/
.So, despite their weird attempt at a distinction, i'm not sure that the existing behaviour is actually supported by the documentation. Or at least the alternative isn't not supported...?
Does that make sense, or is this another case where you'd like to see the up-stream documentation made more explicit before changing things? (I should probably send them another e-mail about this either way, but i haven't yet.)