diff --git a/CHANGELOG.md b/CHANGELOG.md index 075b997..23efcad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,8 @@ Bug fixes: Ensure hyphens in flag names are escaped in the roff text for the man page. * [BUG #3155](https://github.com/BurntSushi/ripgrep/issues/3155): 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: diff --git a/crates/ignore/src/dir.rs b/crates/ignore/src/dir.rs index be4a9a3..8c1434a 100644 --- a/crates/ignore/src/dir.rs +++ b/crates/ignore/src/dir.rs @@ -467,16 +467,20 @@ impl Ignore { .take_while(|ig| !ig.0.is_absolute_parent) .last() .map_or(path, |ig| { - strip_if_is_prefix( - "/", - strip_if_is_prefix( - strip_if_is_prefix( - "./", - ig.0.dir.as_path(), - ), - path, - ), - ) + // This is a weird special case when ripgrep users + // search with just a `.`, as some tools do + // automatically (like consult). In this case, if + // we don't bail out now, the code below will strip + // a leading `.` from `path`, which might mangle + // a hidden file name! + if ig.0.dir.as_path() == Path::new(".") { + 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) }), ); diff --git a/tests/regression.rs b/tests/regression.rs index 8dd1ba7..7f9818f 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -1586,3 +1586,24 @@ YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\n \ 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"); +});