ignore: fix global gitignore bug that arises with absolute paths#3189
Merged
BurntSushi merged 1 commit intomasterfrom Oct 15, 2025
Merged
ignore: fix global gitignore bug that arises with absolute paths#3189BurntSushi merged 1 commit intomasterfrom
BurntSushi merged 1 commit intomasterfrom
Conversation
1213ae9 to
099fac0
Compare
The `ignore` crate currently handles two different kinds of "global" gitignore files: gitignores from `~/.gitconfig`'s `core.excludesFile` and gitignores passed in via `WalkBuilder::add_ignore` (corresponding to ripgrep's `--ignore-file` flag). In contrast to any other kind of gitignore file, these gitignore files should have their patterns interpreted relative to the current working directory. (Arguably there are other choices we could make here, e.g., based on the paths given. But the `ignore` infrastructure can't handle that, and it's not clearly correct to me.) Normally, a gitignore file has its patterns interpreted relative to where the gitignore file is. This relative interpretation matters for patterns like `/foo`, which are anchored to _some_ directory. Previously, we would generally get the global gitignores correct because it's most common to use ripgrep without providing a path. Thus, it searches the current working directory. In this case, no stripping of the paths is needed in order for the gitignore patterns to be applied directly. But if one provides an absolute path (or something else) to ripgrep to search, the paths aren't stripped correctly. Indeed, in the core, I had just given up and not provided a "root" path to these global gitignores. So it had no hope of getting this correct. We fix this assigning the CWD to the `Gitignore` values created from global gitignore files. This was a painful thing to do because we'd ideally: 1. Call `std::env::current_dir()` at most once for each traversal. 2. Provide a way to avoid the library calling `std::env::current_dir()` at all. (Since this is global process state and folks might want to set it to different values for $reasons.) The `ignore` crate's internals are a total mess. But I think I've addressed the above 2 points in a semver compatible manner. Fixes #3179
099fac0 to
12b81e5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
The
ignorecrate currently handles two different kinds of "global"gitignore files: gitignores from
~/.gitconfig'score.excludesFileand gitignores passed in via
WalkBuilder::add_ignore(corresponding toripgrep's
--ignore-fileflag).In contrast to any other kind of gitignore file, these gitignore files
should have their patterns interpreted relative to the current working
directory. (Arguably there are other choices we could make here, e.g.,
based on the paths given. But the
ignoreinfrastructure can't handlethat, and it's not clearly correct to me.) Normally, a gitignore file
has its patterns interpreted relative to where the gitignore file is.
This relative interpretation matters for patterns like
/foo, which areanchored to some directory.
Previously, we would generally get the global gitignores correct because
it's most common to use ripgrep without providing a path. Thus, it
searches the current working directory. In this case, no stripping of
the paths is needed in order for the gitignore patterns to be applied
directly.
But if one provides an absolute path (or something else) to ripgrep to
search, the paths aren't stripped correctly. Indeed, in the core, I had
just given up and not provided a "root" path to these global gitignores.
So it had no hope of getting this correct.
We fix this assigning the CWD to the
Gitignorevalues created fromglobal gitignore files. This was a painful thing to do because we'd
ideally:
std::env::current_dir()at most once for each traversal.std::env::current_dir()at all. (Since this is global process state and folks might want to
set it to different values for $reasons.)
The
ignorecrate's internals are a total mess. But I think I'veaddressed the above 2 points in a semver compatible manner.
Fixes #3179