summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordana <dana@dana.is>2018-01-29 13:10:59 -0600
committerAndrew Gallant <jamslam@gmail.com>2018-01-29 14:10:59 -0500
commit51864c13fc329332b9ebcf2a7e45e7b6aadeedbd (patch)
treec83a0b9e5ccb8b3c9544a89f184bdcd8308c3649
parent35f802166d1c5788e8c833f398d13b9c9e8cb360 (diff)
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
-rw-r--r--ignore/src/gitignore.rs21
-rw-r--r--ignore/src/overrides.rs3
-rw-r--r--ignore/tests/gitignore_matched_path_or_any_parents_tests.rs16
3 files changed, 21 insertions, 19 deletions
diff --git a/ignore/src/gitignore.rs b/ignore/src/gitignore.rs
index e7b0007e..a21afa55 100644
--- a/ignore/src/gitignore.rs
+++ b/ignore/src/gitignore.rs
@@ -416,7 +416,6 @@ impl GitignoreBuilder {
is_only_dir: false,
};
let mut literal_separator = false;
- let has_slash = line.chars().any(|c| c == '/');
let mut is_absolute = false;
if line.starts_with("\\!") || line.starts_with("\\#") {
line = &line[1..];
@@ -447,13 +446,13 @@ impl GitignoreBuilder {
// If there is a literal slash, then we note that so that globbing
// doesn't let wildcards match slashes.
glob.actual = line.to_string();
- if has_slash {
+ if is_absolute || line.chars().any(|c| c == '/') {
literal_separator = true;
}
- // If there was a leading slash, then this is a glob that must
- // match the entire path name. Otherwise, we should let it match
- // anywhere, so use a **/ prefix.
- if !is_absolute {
+ // If there was a slash, then this is a glob that must match the entire
+ // path name. Otherwise, we should let it match anywhere, so use a **/
+ // prefix.
+ if !literal_separator {
// ... but only if we don't already have a **/ prefix.
if !(glob.actual.starts_with("**/") || (glob.actual == "**" && glob.is_only_dir)) {
glob.actual = format!("**/{}", glob.actual);
@@ -617,10 +616,10 @@ mod tests {
ignored!(ig25, ROOT, "Cargo.lock", "./tabwriter-bin/Cargo.lock");
ignored!(ig26, ROOT, "/foo/bar/baz", "./foo/bar/baz");
ignored!(ig27, ROOT, "foo/", "xyz/foo", true);
- ignored!(ig28, ROOT, "src/*.rs", "src/grep/src/main.rs");
- ignored!(ig29, "./src", "/llvm/", "./src/llvm", true);
- ignored!(ig30, ROOT, "node_modules/ ", "node_modules", true);
- ignored!(ig31, ROOT, "**/", "foo/bar", true);
+ ignored!(ig28, "./src", "/llvm/", "./src/llvm", true);
+ ignored!(ig29, ROOT, "node_modules/ ", "node_modules", true);
+ ignored!(ig30, ROOT, "**/", "foo/bar", true);
+ ignored!(ig31, ROOT, "path1/*", "path1/foo");
not_ignored!(ignot1, ROOT, "amonths", "months");
not_ignored!(ignot2, ROOT, "monthsa", "months");
@@ -640,6 +639,8 @@ mod tests {
"./third_party/protobuf/csharp/src/packages/repositories.config");
not_ignored!(ignot15, ROOT, "!/bar", "foo/bar");
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> {
s.to_string().into_bytes()
diff --git a/ignore/src/overrides.rs b/ignore/src/overrides.rs
index 03fd39c4..955dc5ad 100644
--- a/ignore/src/overrides.rs
+++ b/ignore/src/overrides.rs
@@ -202,8 +202,9 @@ mod tests {
#[test]
fn gitignore() {
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("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("wat/foo", false).is_ignore());
assert!(ov.matched("baz", false).is_ignore());
diff --git a/ignore/tests/gitignore_matched_path_or_any_parents_tests.rs b/ignore/tests/gitignore_matched_path_or_any_parents_tests.rs
index c76ee2d1..4de7cf3a 100644
--- a/ignore/tests/gitignore_matched_path_or_any_parents_tests.rs
+++ b/ignore/tests/gitignore_matched_path_or_any_parents_tests.rs
@@ -212,16 +212,16 @@ fn test_dirs_in_deep() {
assert!(m("ROOT/parent_dir/dir_deep_01/child_dir/file", false).is_ignore());
// 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/file", false).is_ignore());
- assert!(m("ROOT/parent_dir/dir_deep_02/child_dir", true).is_ignore());
- assert!(m("ROOT/parent_dir/dir_deep_02/child_dir/file", false).is_ignore());
+ assert!(m("ROOT/parent_dir/dir_deep_02", true).is_none());
+ assert!(m("ROOT/parent_dir/dir_deep_02/file", false).is_none());
+ 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_none());
// 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/file", false).is_ignore());
- assert!(m("ROOT/parent_dir/dir_deep_03/child_dir", true).is_ignore());
- assert!(m("ROOT/parent_dir/dir_deep_03/child_dir/file", false).is_ignore());
+ assert!(m("ROOT/parent_dir/dir_deep_03", true).is_none());
+ assert!(m("ROOT/parent_dir/dir_deep_03/file", false).is_none());
+ 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_none());
// 10
assert!(m("ROOT/parent_dir/dir_deep_10", true).is_none());