mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-05-19 09:40:22 -07:00
ignore: fix handling of / in patterns
This commit makes handling of patterns containing a `/` match actual git behaviour and the specification written in `man gitignore`. Fixes #761
This commit is contained in:
parent
35f802166d
commit
51864c13fc
@ -416,7 +416,6 @@ impl GitignoreBuilder {
|
|||||||
is_only_dir: false,
|
is_only_dir: false,
|
||||||
};
|
};
|
||||||
let mut literal_separator = false;
|
let mut literal_separator = false;
|
||||||
let has_slash = line.chars().any(|c| c == '/');
|
|
||||||
let mut is_absolute = false;
|
let mut is_absolute = false;
|
||||||
if line.starts_with("\\!") || line.starts_with("\\#") {
|
if line.starts_with("\\!") || line.starts_with("\\#") {
|
||||||
line = &line[1..];
|
line = &line[1..];
|
||||||
@ -447,13 +446,13 @@ impl GitignoreBuilder {
|
|||||||
// If there is a literal slash, then we note that so that globbing
|
// If there is a literal slash, then we note that so that globbing
|
||||||
// doesn't let wildcards match slashes.
|
// doesn't let wildcards match slashes.
|
||||||
glob.actual = line.to_string();
|
glob.actual = line.to_string();
|
||||||
if has_slash {
|
if is_absolute || line.chars().any(|c| c == '/') {
|
||||||
literal_separator = true;
|
literal_separator = true;
|
||||||
}
|
}
|
||||||
// If there was a leading slash, then this is a glob that must
|
// If there was a slash, then this is a glob that must match the entire
|
||||||
// match the entire path name. Otherwise, we should let it match
|
// path name. Otherwise, we should let it match anywhere, so use a **/
|
||||||
// anywhere, so use a **/ prefix.
|
// prefix.
|
||||||
if !is_absolute {
|
if !literal_separator {
|
||||||
// ... but only if we don't already have a **/ prefix.
|
// ... but only if we don't already have a **/ prefix.
|
||||||
if !(glob.actual.starts_with("**/") || (glob.actual == "**" && glob.is_only_dir)) {
|
if !(glob.actual.starts_with("**/") || (glob.actual == "**" && glob.is_only_dir)) {
|
||||||
glob.actual = format!("**/{}", glob.actual);
|
glob.actual = format!("**/{}", glob.actual);
|
||||||
@ -617,10 +616,10 @@ mod tests {
|
|||||||
ignored!(ig25, ROOT, "Cargo.lock", "./tabwriter-bin/Cargo.lock");
|
ignored!(ig25, ROOT, "Cargo.lock", "./tabwriter-bin/Cargo.lock");
|
||||||
ignored!(ig26, ROOT, "/foo/bar/baz", "./foo/bar/baz");
|
ignored!(ig26, ROOT, "/foo/bar/baz", "./foo/bar/baz");
|
||||||
ignored!(ig27, ROOT, "foo/", "xyz/foo", true);
|
ignored!(ig27, ROOT, "foo/", "xyz/foo", true);
|
||||||
ignored!(ig28, ROOT, "src/*.rs", "src/grep/src/main.rs");
|
ignored!(ig28, "./src", "/llvm/", "./src/llvm", true);
|
||||||
ignored!(ig29, "./src", "/llvm/", "./src/llvm", true);
|
ignored!(ig29, ROOT, "node_modules/ ", "node_modules", true);
|
||||||
ignored!(ig30, ROOT, "node_modules/ ", "node_modules", true);
|
ignored!(ig30, ROOT, "**/", "foo/bar", true);
|
||||||
ignored!(ig31, ROOT, "**/", "foo/bar", true);
|
ignored!(ig31, ROOT, "path1/*", "path1/foo");
|
||||||
|
|
||||||
not_ignored!(ignot1, ROOT, "amonths", "months");
|
not_ignored!(ignot1, ROOT, "amonths", "months");
|
||||||
not_ignored!(ignot2, ROOT, "monthsa", "months");
|
not_ignored!(ignot2, ROOT, "monthsa", "months");
|
||||||
@ -640,6 +639,8 @@ mod tests {
|
|||||||
"./third_party/protobuf/csharp/src/packages/repositories.config");
|
"./third_party/protobuf/csharp/src/packages/repositories.config");
|
||||||
not_ignored!(ignot15, ROOT, "!/bar", "foo/bar");
|
not_ignored!(ignot15, ROOT, "!/bar", "foo/bar");
|
||||||
not_ignored!(ignot16, ROOT, "*\n!**/", "foo", true);
|
not_ignored!(ignot16, ROOT, "*\n!**/", "foo", true);
|
||||||
|
not_ignored!(ignot17, ROOT, "src/*.rs", "src/grep/src/main.rs");
|
||||||
|
not_ignored!(ignot18, ROOT, "path1/*", "path2/path1/foo");
|
||||||
|
|
||||||
fn bytes(s: &str) -> Vec<u8> {
|
fn bytes(s: &str) -> Vec<u8> {
|
||||||
s.to_string().into_bytes()
|
s.to_string().into_bytes()
|
||||||
|
@ -202,8 +202,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn gitignore() {
|
fn gitignore() {
|
||||||
let ov = ov(&["/foo", "bar/*.rs", "baz/**"]);
|
let ov = ov(&["/foo", "bar/*.rs", "baz/**"]);
|
||||||
|
assert!(ov.matched("bar/lib.rs", false).is_whitelist());
|
||||||
assert!(ov.matched("bar/wat/lib.rs", false).is_ignore());
|
assert!(ov.matched("bar/wat/lib.rs", false).is_ignore());
|
||||||
assert!(ov.matched("wat/bar/lib.rs", false).is_whitelist());
|
assert!(ov.matched("wat/bar/lib.rs", false).is_ignore());
|
||||||
assert!(ov.matched("foo", false).is_whitelist());
|
assert!(ov.matched("foo", false).is_whitelist());
|
||||||
assert!(ov.matched("wat/foo", false).is_ignore());
|
assert!(ov.matched("wat/foo", false).is_ignore());
|
||||||
assert!(ov.matched("baz", false).is_ignore());
|
assert!(ov.matched("baz", false).is_ignore());
|
||||||
|
@ -212,16 +212,16 @@ fn test_dirs_in_deep() {
|
|||||||
assert!(m("ROOT/parent_dir/dir_deep_01/child_dir/file", false).is_ignore());
|
assert!(m("ROOT/parent_dir/dir_deep_01/child_dir/file", false).is_ignore());
|
||||||
|
|
||||||
// 02
|
// 02
|
||||||
assert!(m("ROOT/parent_dir/dir_deep_02", true).is_none()); // dir itself doesn't match
|
assert!(m("ROOT/parent_dir/dir_deep_02", true).is_none());
|
||||||
assert!(m("ROOT/parent_dir/dir_deep_02/file", false).is_ignore());
|
assert!(m("ROOT/parent_dir/dir_deep_02/file", false).is_none());
|
||||||
assert!(m("ROOT/parent_dir/dir_deep_02/child_dir", true).is_ignore());
|
assert!(m("ROOT/parent_dir/dir_deep_02/child_dir", true).is_none());
|
||||||
assert!(m("ROOT/parent_dir/dir_deep_02/child_dir/file", false).is_ignore());
|
assert!(m("ROOT/parent_dir/dir_deep_02/child_dir/file", false).is_none());
|
||||||
|
|
||||||
// 03
|
// 03
|
||||||
assert!(m("ROOT/parent_dir/dir_deep_03", true).is_none()); // dir itself doesn't match
|
assert!(m("ROOT/parent_dir/dir_deep_03", true).is_none());
|
||||||
assert!(m("ROOT/parent_dir/dir_deep_03/file", false).is_ignore());
|
assert!(m("ROOT/parent_dir/dir_deep_03/file", false).is_none());
|
||||||
assert!(m("ROOT/parent_dir/dir_deep_03/child_dir", true).is_ignore());
|
assert!(m("ROOT/parent_dir/dir_deep_03/child_dir", true).is_none());
|
||||||
assert!(m("ROOT/parent_dir/dir_deep_03/child_dir/file", false).is_ignore());
|
assert!(m("ROOT/parent_dir/dir_deep_03/child_dir/file", false).is_none());
|
||||||
|
|
||||||
// 10
|
// 10
|
||||||
assert!(m("ROOT/parent_dir/dir_deep_10", true).is_none());
|
assert!(m("ROOT/parent_dir/dir_deep_10", true).is_none());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user