Subject: ripgrep: .gitignore logic is not followed Package: ripgrep Version: 14.1.1-1+b4 Severity: normal Tags: patch upstream
ripgrep does not follow .gitignore logic despite documentation claiming the contrary. https://github.com/BurntSushi/ripgrep/pull/2933 fixes it. -- System Information: Debian Release: 13.0 APT prefers testing APT policy: (500, 'testing') Architecture: amd64 (x86_64) Kernel: Linux 6.12.30-amd64 (SMP w/24 CPU threads; PREEMPT) Locale: LANG=en_AU.UTF-8, LC_CTYPE=en_AU.UTF-8 (charmap=UTF-8), LANGUAGE=en_AU:en Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages ripgrep depends on: ii libc6 2.41-8 ii libgcc-s1 14.2.0-19 ii libpcre2-8-0 10.45-1 ripgrep recommends no packages. ripgrep suggests no packages. -- no debconf information *** /home/user/code/ripgrep/2933.patch >From 431ab25450c10b64128afb15e988752a48368f90 Mon Sep 17 00:00:00 2001 From: ChristopherYoung <joundan...@icloud.com> Date: Fri, 15 Nov 2024 18:40:27 +0800 Subject: [PATCH] ignore: fix filtering searching subdir or .ignore in parent dir The previous code deleted too many parts of the path when constructing the absolute path, resulting in a shortened final path. This patch creates the correct absolute path by only removing the necessary parts. Fixes #2836 --- crates/ignore/src/dir.rs | 40 +++++++++++++++++++++++++--------------- tests/regression.rs | 19 +++++++++++++++++++ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/crates/ignore/src/dir.rs b/crates/ignore/src/dir.rs index b302943ab..d6a82e86e 100644 --- a/crates/ignore/src/dir.rs +++ b/crates/ignore/src/dir.rs @@ -461,21 +461,31 @@ impl Ignore { // off of `path`. Overall, this seems a little ham-fisted, but // it does fix a nasty bug. It should do fine until we overhaul // this crate. - let dirpath = self.0.dir.as_path(); - let path_prefix = match strip_prefix("./", dirpath) { - None => dirpath, - Some(stripped_dot_slash) => stripped_dot_slash, - }; - let path = match strip_prefix(path_prefix, path) { - None => abs_parent_path.join(path), - Some(p) => { - let p = match strip_prefix("/", p) { - None => p, - Some(p) => p, - }; - abs_parent_path.join(p) - } - }; + + fn strip_if_is_prefix<'a, P: AsRef<Path> + ?Sized>( + prefix: &'a P, + path: &'a Path, + ) -> &'a Path { + strip_prefix(prefix, path).map_or(path, |p| p) + } + + let path = abs_parent_path.join( + self.parents() + .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, + ), + ) + }), + ); for ig in self.parents().skip_while(|ig| !ig.0.is_absolute_parent) diff --git a/tests/regression.rs b/tests/regression.rs index e28af4a31..78a645260 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -965,6 +965,15 @@ rgtest!(f1757, |dir: Dir, _: TestCommand| { eqnice!("rust/source.rs\n", dir.command().args(args).stdout()); let args = &["--files-with-matches", "needle", "./rust"]; eqnice!("./rust/source.rs\n", dir.command().args(args).stdout()); + + dir.create_dir("rust1/target/onemore"); + dir.create(".ignore", "rust1/target/onemore"); + dir.create("rust1/source.rs", "needle"); + dir.create("rust1/target/onemore/rustdoc-output.html", "needle"); + let args = &["--files-with-matches", "needle", "rust1"]; + eqnice!("rust1/source.rs\n", dir.command().args(args).stdout()); + let args = &["--files-with-matches", "needle", "./rust1"]; + eqnice!("./rust1/source.rs\n", dir.command().args(args).stdout()); }); // See: https://github.com/BurntSushi/ripgrep/issues/1765 @@ -1217,3 +1226,13 @@ rgtest!(r2658_null_data_line_regexp, |dir: Dir, mut cmd: TestCommand| { let got = cmd.args(&["--null-data", "--line-regexp", r"bar"]).stdout(); eqnice!("haystack:bar\0", got); }); + +rgtest!(f2836, |dir: Dir, mut cmd: TestCommand| { + dir.create_dir("testdir/sub/sub2"); + dir.create(".ignore", "/testdir/sub/sub2/"); + dir.create("testdir/sub/sub2/testfile", "needle"); + + let args = &["--files-with-matches", "needle"]; + cmd.current_dir(dir.path().join("testdir")); + cmd.args(args).assert_err(); +});