ignore: fix problem with searching whitelisted hidden files

... specifically, when the whitelist comes from a _parent_ gitignore
file.

Our handling of parent gitignores is pretty ham-fisted and has been a
source of some unfortunate bugs. The problem is that we need to strip
the parent path from the path we're searching in order to correctly
apply the globs. But getting this stripping correct seems to be a subtle
affair.

Fixes #3173
This commit is contained in:
Andrew Gallant
2025-10-08 21:09:21 -04:00
parent bb88a1ac45
commit 0407e104f6
3 changed files with 37 additions and 10 deletions

View File

@@ -37,6 +37,8 @@ Bug fixes:
Ensure hyphens in flag names are escaped in the roff text for the man page. Ensure hyphens in flag names are escaped in the roff text for the man page.
* [BUG #3155](https://github.com/BurntSushi/ripgrep/issues/3155): * [BUG #3155](https://github.com/BurntSushi/ripgrep/issues/3155):
Statically compile PCRE2 into macOS release artifacts on `aarch64`. Statically compile PCRE2 into macOS release artifacts on `aarch64`.
* [BUG #3173](https://github.com/BurntSushi/ripgrep/issues/3173):
Fix ancestor ignore filter bug when searching whitelisted hidden files.
Feature enhancements: Feature enhancements:

View File

@@ -467,16 +467,20 @@ impl Ignore {
.take_while(|ig| !ig.0.is_absolute_parent) .take_while(|ig| !ig.0.is_absolute_parent)
.last() .last()
.map_or(path, |ig| { .map_or(path, |ig| {
strip_if_is_prefix( // This is a weird special case when ripgrep users
"/", // search with just a `.`, as some tools do
strip_if_is_prefix( // automatically (like consult). In this case, if
strip_if_is_prefix( // we don't bail out now, the code below will strip
"./", // a leading `.` from `path`, which might mangle
ig.0.dir.as_path(), // a hidden file name!
), if ig.0.dir.as_path() == Path::new(".") {
path, return path;
), }
) let without_dot_slash =
strip_if_is_prefix("./", ig.0.dir.as_path());
let relative_base =
strip_if_is_prefix(without_dot_slash, path);
strip_if_is_prefix("/", relative_base)
}), }),
); );

View File

@@ -1586,3 +1586,24 @@ YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\n \
eqnice!("test\n", got); eqnice!("test\n", got);
} }
); );
// See: https://github.com/BurntSushi/ripgrep/issues/3173
rgtest!(r3173_hidden_whitelist_only_dot, |dir: Dir, _: TestCommand| {
dir.create_dir("subdir");
dir.create("subdir/.foo.txt", "text");
dir.create(".ignore", "!.foo.txt");
let cmd = || dir.command();
eqnice!(cmd().args(&["--files"]).stdout(), "subdir/.foo.txt\n");
eqnice!(cmd().args(&["--files", "."]).stdout(), "./subdir/.foo.txt\n");
eqnice!(cmd().args(&["--files", "./"]).stdout(), "./subdir/.foo.txt\n");
let cmd = || {
let mut cmd = dir.command();
cmd.current_dir(dir.path().join("subdir"));
cmd
};
eqnice!(cmd().args(&["--files"]).stdout(), ".foo.txt\n");
eqnice!(cmd().args(&["--files", "."]).stdout(), "./.foo.txt\n");
eqnice!(cmd().args(&["--files", "./"]).stdout(), "./.foo.txt\n");
});