| @@ -15,6 +15,139 @@ fn no_pathspecs_match_everything() -> crate::Result { · 14 unmodified lines |
| 15 | }) | 15 | }) |
| 16 | .expect("matches"); | 16 | .expect("matches"); |
| 17 | assert_eq!(m.pattern.prefix_directory(), "", "there is no prefix as none was given"); | 17 | assert_eq!(m.pattern.prefix_directory(), "", "there is no prefix as none was given"); |
| | 18 | assert_eq!( |
| | 19 | m.sequence_number, 0, |
| | 20 | "this is actually a fake pattern, as we have to match even though there isn't anything" |
| | 21 | ); |
| | 22 | |
| | 23 | assert!(search.can_match_relative_path("anything".into(), None)); |
| | 24 | |
| | 25 | Ok(()) |
| | 26 | } |
| | 27 | |
| | 28 | #[test] |
| | 29 | fn simplified_search_respects_must_be_dir() -> crate::Result { |
| | 30 | let mut search = gix_pathspec::Search::from_specs(pathspecs(&["a/be/"]), None, Path::new(""))?; |
| | 31 | search |
| | 32 | .pattern_matching_relative_path("a/be/file".into(), Some(false), &mut |_, _, _, _| { |
| | 33 | unreachable!("must not be called") |
| | 34 | }) |
| | 35 | .expect("matches as this is a prefix match"); |
| | 36 | assert!( |
| | 37 | !search.can_match_relative_path("any".into(), Some(false)), |
| | 38 | "not our directory: a, and must be dir" |
| | 39 | ); |
| | 40 | assert!( |
| | 41 | !search.can_match_relative_path("any".into(), Some(true)), |
| | 42 | "not our directory: a" |
| | 43 | ); |
| | 44 | assert!( |
| | 45 | !search.can_match_relative_path("any".into(), None), |
| | 46 | "not our directory: a, and must be dir, still completely out of scope" |
| | 47 | ); |
| | 48 | assert!( |
| | 49 | !search.can_match_relative_path("a/bei".into(), None), |
| | 50 | "not our directory: a/be" |
| | 51 | ); |
| | 52 | assert!(!search.can_match_relative_path("a".into(), Some(false)), "must be dir"); |
| | 53 | assert!(search.can_match_relative_path("a".into(), Some(true))); |
| | 54 | assert!( |
| | 55 | search.can_match_relative_path("a".into(), None), |
| | 56 | "now dir or not doesn't matter" |
| | 57 | ); |
| | 58 | assert!(search.can_match_relative_path("a/be".into(), Some(true))); |
| | 59 | assert!( |
| | 60 | search.can_match_relative_path("a/be".into(), None), |
| | 61 | "dir doesn't matter anymore" |
| | 62 | ); |
| | 63 | assert!( |
| | 64 | !search.can_match_relative_path("a/be".into(), Some(false)), |
| | 65 | "files can't match as prefix" |
| | 66 | ); |
| | 67 | assert!( |
| | 68 | search.can_match_relative_path("a/be/file".into(), Some(false)), |
| | 69 | "files can match if they are part of the suffix" |
| | 70 | ); |
| | 71 | |
| | 72 | assert!( |
| | 73 | !search.can_match_relative_path("a/b".into(), Some(false)), |
| | 74 | "can't match a/be" |
| | 75 | ); |
| | 76 | assert!( |
| | 77 | !search.can_match_relative_path("a/b".into(), None), |
| | 78 | "still can't match a/be" |
| | 79 | ); |
| | 80 | assert!( |
| | 81 | search |
| | 82 | .pattern_matching_relative_path("a/b".into(), None, &mut |_, _, _, _| unreachable!("must not be called")) |
| | 83 | .is_none(), |
| | 84 | "no match if it's not the whole pattern that matches" |
| | 85 | ); |
| | 86 | assert!( |
| | 87 | !search.can_match_relative_path("a/b".into(), Some(true)), |
| | 88 | "can't match a/be, which must be directory" |
| | 89 | ); |
| | 90 | |
| | 91 | Ok(()) |
| | 92 | } |
| | 93 | |
| | 94 | #[test] |
| | 95 | fn simplified_search_respects_ignore_case() -> crate::Result { |
| | 96 | let search = gix_pathspec::Search::from_specs(pathspecs(&[":(icase)foo/**/bar"]), None, Path::new(""))?; |
| | 97 | assert!(search.can_match_relative_path("Foo".into(), None)); |
| | 98 | assert!(search.can_match_relative_path("foo".into(), Some(true))); |
| | 99 | assert!(search.can_match_relative_path("FOO/".into(), Some(true))); |
| | 100 | |
| | 101 | Ok(()) |
| | 102 | } |
| | 103 | |
| | 104 | #[test] |
| | 105 | fn simplified_search_respects_all_excluded() -> crate::Result { |
| | 106 | let search = gix_pathspec::Search::from_specs( |
| | 107 | pathspecs(&[":(exclude)a/file", ":(exclude)b/file"]), |
| | 108 | None, |
| | 109 | Path::new(""), |
| | 110 | )?; |
| | 111 | assert!(!search.can_match_relative_path("b".into(), None)); |
| | 112 | assert!(!search.can_match_relative_path("a".into(), None)); |
| | 113 | assert!(search.can_match_relative_path("c".into(), None)); |
| | 114 | assert!(search.can_match_relative_path("c/".into(), None)); |
| | 115 | |
| | 116 | Ok(()) |
| | 117 | } |
| | 118 | |
| | 119 | #[test] |
| | 120 | fn simplified_search_wildcards() -> crate::Result { |
| | 121 | let search = gix_pathspec::Search::from_specs(pathspecs(&["**/a*"]), None, Path::new(""))?; |
| | 122 | assert!( |
| | 123 | search.can_match_relative_path("a".into(), None), |
| | 124 | "it can't determine it, so assume match" |
| | 125 | ); |
| | 126 | assert!(search.can_match_relative_path("a/a".into(), Some(false))); |
| | 127 | assert!(search.can_match_relative_path("a/a.o".into(), Some(false))); |
| | 128 | assert!( |
| | 129 | search.can_match_relative_path("b-unrelated".into(), None), |
| | 130 | "this is also assumed to be a match, prefer false-positives over false-negatives" |
| | 131 | ); |
| | 132 | Ok(()) |
| | 133 | } |
| | 134 | |
| | 135 | #[test] |
| | 136 | fn simplified_search_handles_nil() -> crate::Result { |
| | 137 | let search = gix_pathspec::Search::from_specs(pathspecs(&[":"]), None, Path::new(""))?; |
| | 138 | assert!(search.can_match_relative_path("a".into(), None), "everything matches"); |
| | 139 | assert!(search.can_match_relative_path("a".into(), Some(false))); |
| | 140 | assert!(search.can_match_relative_path("a".into(), Some(true))); |
| | 141 | assert!(search.can_match_relative_path("a/b".into(), Some(true))); |
| | 142 | |
| | 143 | let search = gix_pathspec::Search::from_specs(pathspecs(&[":(exclude)"]), None, Path::new(""))?; |
| | 144 | assert!( |
| | 145 | !search.can_match_relative_path("a".into(), None), |
| | 146 | "everything does not match" |
| | 147 | ); |
| | 148 | assert!(!search.can_match_relative_path("a".into(), Some(false))); |
| | 149 | assert!(!search.can_match_relative_path("a".into(), Some(true))); |
| | 150 | assert!(!search.can_match_relative_path("a/b".into(), Some(true))); |
| 18 | | 151 | |
| 19 | Ok(()) | 152 | Ok(()) |
| 20 | } | 153 | } |
| @@ -28,6 +161,15 @@ fn init_with_exclude() -> crate::Result { · 7 unmodified lines |
| 28 | "re-orded so that excluded are first" | 161 | "re-orded so that excluded are first" |
| 29 | ); | 162 | ); |
| 30 | assert_eq!(search.common_prefix(), "tests"); | 163 | assert_eq!(search.common_prefix(), "tests"); |
| | 164 | assert!( |
| | 165 | search.can_match_relative_path("tests".into(), Some(true)), |
| | 166 | "prefix matches" |
| | 167 | ); |
| | 168 | assert!( |
| | 169 | !search.can_match_relative_path("test".into(), Some(true)), |
| | 170 | "prefix can not be shorter" |
| | 171 | ); |
| | 172 | assert!(!search.can_match_relative_path("outside-of-tests".into(), None)); |
| 31 | Ok(()) | 173 | Ok(()) |
| 32 | } | 174 | } |
| 33 | | 175 | |
| @@ -47,6 +189,7 @@ fn no_pathspecs_respect_prefix() -> crate::Result { · 13 unmodified lines |
| 47 | .is_none(), | 189 | .is_none(), |
| 48 | "not the right prefix" | 190 | "not the right prefix" |
| 49 | ); | 191 | ); |
| | 192 | assert!(!search.can_match_relative_path("hello".into(), None)); |
| 50 | let m = search | 193 | let m = search |
| 51 | .pattern_matching_relative_path("a/b".into(), None, &mut |_, _, _, _| unreachable!("must not be called")) | 194 | .pattern_matching_relative_path("a/b".into(), None, &mut |_, _, _, _| unreachable!("must not be called")) |
| 52 | .expect("match"); | 195 | .expect("match"); |
| @@ -55,12 +198,16 @@ fn no_pathspecs_respect_prefix() -> crate::Result { · 2 unmodified lines |
| 55 | "a", | 198 | "a", |
| 56 | "the prefix directory matched verbatim" | 199 | "the prefix directory matched verbatim" |
| 57 | ); | 200 | ); |
| | 201 | assert!(search.can_match_relative_path("a/".into(), Some(true))); |
| | 202 | assert!(search.can_match_relative_path("a".into(), Some(true))); |
| | 203 | assert!(!search.can_match_relative_path("a".into(), Some(false))); |
| | 204 | assert!(search.can_match_relative_path("a".into(), None), "simple prefix search"); |
| 58 | | 205 | |
| 59 | Ok(()) | 206 | Ok(()) |
| 60 | } | 207 | } |
| 61 | | 208 | |
| 62 | #[test] | 209 | #[test] |
| 63 | fn prefixes_are_always_case_insensitive() -> crate::Result { | 210 | fn prefixes_are_always_case_sensitive() -> crate::Result { |
| 64 | let path = gix_testtools::scripted_fixture_read_only("match_baseline_files.sh")?.join("paths"); | 211 | let path = gix_testtools::scripted_fixture_read_only("match_baseline_files.sh")?.join("paths"); |
| 65 | let items = baseline::parse_paths(path)?; | 212 | let items = baseline::parse_paths(path)?; |
| 66 | | 213 | |
| @@ -108,6 +255,22 @@ fn prefixes_are_always_case_insensitive() -> crate::Result { · 41 unmodified lines |
| 108 | .collect(); | 255 | .collect(); |
| 109 | assert_eq!(actual, expected, "{spec} {prefix}"); | 256 | assert_eq!(actual, expected, "{spec} {prefix}"); |
| 110 | } | 257 | } |
| | 258 | |
| | 259 | let search = gix_pathspec::Search::from_specs( |
| | 260 | gix_pathspec::parse(":(icase)bar".as_bytes(), Default::default()), |
| | 261 | Some(Path::new("FOO")), |
| | 262 | Path::new(""), |
| | 263 | )?; |
| | 264 | assert!( |
| | 265 | !search.can_match_relative_path("foo".into(), Some(true)), |
| | 266 | "icase does not apply to the prefix" |
| | 267 | ); |
| | 268 | assert!(search.can_match_relative_path("FOO".into(), Some(true))); |
| | 269 | assert!( |
| | 270 | !search.can_match_relative_path("FOO/ba".into(), Some(true)), |
| | 271 | "a full match is needed" |
| | 272 | ); |
| | 273 | assert!(search.can_match_relative_path("FOO/bar".into(), Some(true))); |
| 111 | Ok(()) | 274 | Ok(()) |
| 112 | } | 275 | } |
| 113 | | 276 | |