summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Gallant <jamslam@gmail.com>2022-06-14 10:38:32 -0400
committerAndrew Gallant <jamslam@gmail.com>2022-06-14 10:40:37 -0400
commit9f0e88bcb14e02da1b88872435b17d74786640b5 (patch)
tree64db992cebfe68507804cd157c8e3d4a04bb2531
parenteb4b38984622f9b7c05f7e9cfd9bfa3d82cc881f (diff)
ignore: fix gitignore parsing bug for trailing \/
When a glob pattern ended with a \/, and since we permit backslash escapes, the glob parser gave a "dangling escape" error. Which is weird, because the \ is clearly not dangling. The issue is that the layer above the glob parser, the gitignore parser, was stripping the trailing / so that it wouldn't be part of the matching logic. Of course, stripping the trailing / while it is escaped without removing the backslash escape is wrong. So we do that here. Fixes #2236
-rw-r--r--CHANGELOG.md6
-rw-r--r--crates/ignore/src/gitignore.rs11
-rw-r--r--tests/regression.rs8
3 files changed, 19 insertions, 6 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ba427f92..1e11a8ea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,5 @@
-13.0.1
-======
+TBD
+===
Unreleased changes. Release notes have not yet been written.
Bug fixes:
@@ -8,6 +8,8 @@ Bug fixes:
Fix bug when using `-w` with a regex that can match the empty string.
* [BUG #1911](https://github.com/BurntSushi/ripgrep/issues/1911):
Disable mmap searching in all non-64-bit environments.
+* [BUG #2236](https://github.com/BurntSushi/ripgrep/issues/2236):
+ Fix gitignore parsing bug where a trailing `\/` resulted in an error.
13.0.0 (2021-06-12)
diff --git a/crates/ignore/src/gitignore.rs b/crates/ignore/src/gitignore.rs
index 7922651c..3c7ba5e6 100644
--- a/crates/ignore/src/gitignore.rs
+++ b/crates/ignore/src/gitignore.rs
@@ -474,10 +474,13 @@ impl GitignoreBuilder {
}
// If it ends with a slash, then this should only match directories,
// but the slash should otherwise not be used while globbing.
- if let Some((i, c)) = line.char_indices().rev().nth(0) {
- if c == '/' {
- glob.is_only_dir = true;
- line = &line[..i];
+ if line.as_bytes().last() == Some(&b'/') {
+ glob.is_only_dir = true;
+ line = &line[..line.len() - 1];
+ // If the slash was escaped, then remove the escape.
+ // See: https://github.com/BurntSushi/ripgrep/issues/2236
+ if line.as_bytes().last() == Some(&b'\\') {
+ line = &line[..line.len() - 1];
}
}
glob.actual = line.to_string();
diff --git a/tests/regression.rs b/tests/regression.rs
index f777ed1c..e2c56968 100644
--- a/tests/regression.rs
+++ b/tests/regression.rs
@@ -1118,3 +1118,11 @@ pipc () { # [-h] [-U|-u <pkgspec>[,<pkgspec>...]] [<reqs-in>...] [-- <pip-compi
let expected = " [-h] [-U|-u <pkgspec>[,<pkgspec>...]] [<reqs-in>...] [-- <pip-compile-arg>...]\n";
eqnice!(expected, cmd.stdout());
});
+
+// See: https://github.com/BurntSushi/ripgrep/issues/2236
+rgtest!(r2236, |dir: Dir, mut cmd: TestCommand| {
+ dir.create(".ignore", r"foo\/");
+ dir.create_dir("foo");
+ dir.create("foo/bar", "test\n");
+ cmd.args(&["test"]).assert_err();
+});