mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-08-17 21:23:48 -07:00
globset: fix bug where trailing .
in file name was incorrectly handled
I'm not sure why I did this, but I think I was trying to imitate the contract of [`std::path::Path::file_name`]: > Returns None if the path terminates in `..`. But the status quo clearly did not implement this. And as a result, if you have a glob that ends in a `.`, it was instead treated as the empty string (which only matches the empty string). We fix this by implementing the semantic from the standard library correctly. Fixes #2990 [`std::path::Path::file_name`]: https://doc.rust-lang.org/std/path/struct.Path.html#method.file_name
This commit is contained in:
@@ -23,6 +23,8 @@ Bug fixes:
|
||||
Ignore a UTF-8 BOM marker at the start of `.gitignore` (and similar files).
|
||||
* [BUG #2944](https://github.com/BurntSushi/ripgrep/pull/2944):
|
||||
Fix a bug where the "bytes searched" in `--stats` output could be incorrect.
|
||||
* [BUG #2990](https://github.com/BurntSushi/ripgrep/issues/2990):
|
||||
Fix a bug where ripgrep would mishandle globs that ended with a `.`.
|
||||
|
||||
Feature enhancements:
|
||||
|
||||
|
@@ -4,21 +4,25 @@ use bstr::{ByteSlice, ByteVec};
|
||||
|
||||
/// The final component of the path, if it is a normal file.
|
||||
///
|
||||
/// If the path terminates in `.`, `..`, or consists solely of a root of
|
||||
/// prefix, file_name will return None.
|
||||
/// If the path terminates in `..`, or consists solely of a root of prefix,
|
||||
/// file_name will return `None`.
|
||||
pub(crate) fn file_name<'a>(path: &Cow<'a, [u8]>) -> Option<Cow<'a, [u8]>> {
|
||||
if path.last_byte().map_or(true, |b| b == b'.') {
|
||||
if path.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let last_slash = path.rfind_byte(b'/').map(|i| i + 1).unwrap_or(0);
|
||||
Some(match *path {
|
||||
let got = match *path {
|
||||
Cow::Borrowed(path) => Cow::Borrowed(&path[last_slash..]),
|
||||
Cow::Owned(ref path) => {
|
||||
let mut path = path.clone();
|
||||
path.drain_bytes(..last_slash);
|
||||
Cow::Owned(path)
|
||||
}
|
||||
})
|
||||
};
|
||||
if got == &b".."[..] {
|
||||
return None;
|
||||
}
|
||||
Some(got)
|
||||
}
|
||||
|
||||
/// Return a file extension given a path's file name.
|
||||
|
@@ -1461,3 +1461,18 @@ rgtest!(r2944_incorrect_bytes_searched, |dir: Dir, mut cmd: TestCommand| {
|
||||
let got = cmd.args(&["--stats", "-m2", "foo", "."]).stdout();
|
||||
assert!(got.contains("10 bytes searched\n"));
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/2990
|
||||
rgtest!(r2990_trip_over_trailing_dot, |dir: Dir, _cmd: TestCommand| {
|
||||
dir.create_dir("asdf");
|
||||
dir.create_dir("asdf.");
|
||||
dir.create("asdf/foo", "");
|
||||
dir.create("asdf./foo", "");
|
||||
|
||||
let got = dir.command().args(&["--files", "-g", "!asdf/"]).stdout();
|
||||
eqnice!("asdf./foo\n", got);
|
||||
|
||||
// This used to ignore the glob given and included `asdf./foo` in output.
|
||||
let got = dir.command().args(&["--files", "-g", "!asdf./"]).stdout();
|
||||
eqnice!("asdf/foo\n", got);
|
||||
});
|
||||
|
Reference in New Issue
Block a user