Show More
@@ -214,10 +214,33 lazy_static! { | |||
|
214 | 214 | static ref FLAG_RE: Regex = Regex::new(r"^\(\?[aiLmsux]+\)").unwrap(); |
|
215 | 215 | } |
|
216 | 216 | |
|
217 | /// Extra path components to match at the end of the pattern | |
|
218 | #[derive(Clone, Copy)] | |
|
219 | pub enum GlobSuffix { | |
|
220 | /// `Empty` means the pattern only matches files, not directories, | |
|
221 | /// so the path needs to match exactly. | |
|
222 | Empty, | |
|
223 | /// `MoreComponents` means the pattern matches directories as well, | |
|
224 | /// so any path that has the pattern as a prefix, should match. | |
|
225 | MoreComponents, | |
|
226 | } | |
|
227 | ||
|
228 | impl GlobSuffix { | |
|
229 | fn to_re(self) -> &'static [u8] { | |
|
230 | match self { | |
|
231 | Self::Empty => b"$", | |
|
232 | Self::MoreComponents => b"(?:/|$)", | |
|
233 | } | |
|
234 | } | |
|
235 | } | |
|
236 | ||
|
217 | 237 | /// Builds the regex that corresponds to the given pattern. |
|
218 | 238 | /// If within a `syntax: regexp` context, returns the pattern, |
|
219 | 239 | /// otherwise, returns the corresponding regex. |
|
220 | fn _build_single_regex(entry: &IgnorePattern, glob_suffix: &[u8]) -> Vec<u8> { | |
|
240 | fn _build_single_regex( | |
|
241 | entry: &IgnorePattern, | |
|
242 | glob_suffix: GlobSuffix, | |
|
243 | ) -> Vec<u8> { | |
|
221 | 244 | let IgnorePattern { |
|
222 | 245 | syntax, pattern, .. |
|
223 | 246 | } = entry; |
@@ -264,7 +287,11 fn _build_single_regex(entry: &IgnorePat | |||
|
264 | 287 | if pattern == b"." { |
|
265 | 288 | return vec![]; |
|
266 | 289 | } |
|
267 | [escape_pattern(pattern).as_slice(), b"(?:/|$)"].concat() | |
|
290 | [ | |
|
291 | escape_pattern(pattern).as_slice(), | |
|
292 | GlobSuffix::MoreComponents.to_re(), | |
|
293 | ] | |
|
294 | .concat() | |
|
268 | 295 | } |
|
269 | 296 | PatternSyntax::RootFilesIn => { |
|
270 | 297 | let mut res = if pattern == b"." { |
@@ -281,13 +308,13 fn _build_single_regex(entry: &IgnorePat | |||
|
281 | 308 | PatternSyntax::RelGlob => { |
|
282 | 309 | let glob_re = glob_to_re(pattern); |
|
283 | 310 | if let Some(rest) = glob_re.drop_prefix(b"[^/]*") { |
|
284 | [b".*", rest, glob_suffix].concat() | |
|
311 | [b".*", rest, glob_suffix.to_re()].concat() | |
|
285 | 312 | } else { |
|
286 | [b"(?:.*/)?", glob_re.as_slice(), glob_suffix].concat() | |
|
313 | [b"(?:.*/)?", glob_re.as_slice(), glob_suffix.to_re()].concat() | |
|
287 | 314 | } |
|
288 | 315 | } |
|
289 | 316 | PatternSyntax::Glob | PatternSyntax::RootGlob => { |
|
290 | [glob_to_re(pattern).as_slice(), glob_suffix].concat() | |
|
317 | [glob_to_re(pattern).as_slice(), glob_suffix.to_re()].concat() | |
|
291 | 318 | } |
|
292 | 319 | PatternSyntax::Include |
|
293 | 320 | | PatternSyntax::SubInclude |
@@ -345,7 +372,7 pub fn normalize_path_bytes(bytes: &[u8] | |||
|
345 | 372 | /// that don't need to be transformed into a regex. |
|
346 | 373 | pub fn build_single_regex( |
|
347 | 374 | entry: &IgnorePattern, |
|
348 |
glob_suffix: |
|
|
375 | glob_suffix: GlobSuffix, | |
|
349 | 376 | ) -> Result<Option<Vec<u8>>, PatternError> { |
|
350 | 377 | let IgnorePattern { |
|
351 | 378 | pattern, syntax, .. |
@@ -800,7 +827,7 mod tests { | |||
|
800 | 827 | b"rust/target/", |
|
801 | 828 | Path::new("") |
|
802 | 829 | ), |
|
803 | b"(?:/|$)" | |
|
830 | GlobSuffix::MoreComponents | |
|
804 | 831 | ) |
|
805 | 832 | .unwrap(), |
|
806 | 833 | Some(br"(?:.*/)?rust/target(?:/|$)".to_vec()), |
@@ -812,7 +839,7 mod tests { | |||
|
812 | 839 | br"rust/target/\d+", |
|
813 | 840 | Path::new("") |
|
814 | 841 | ), |
|
815 | b"(?:/|$)" | |
|
842 | GlobSuffix::MoreComponents | |
|
816 | 843 | ) |
|
817 | 844 | .unwrap(), |
|
818 | 845 | Some(br"rust/target/\d+".to_vec()), |
@@ -828,7 +855,7 mod tests { | |||
|
828 | 855 | b"", |
|
829 | 856 | Path::new("") |
|
830 | 857 | ), |
|
831 | b"(?:/|$)" | |
|
858 | GlobSuffix::MoreComponents | |
|
832 | 859 | ) |
|
833 | 860 | .unwrap(), |
|
834 | 861 | None, |
@@ -840,7 +867,7 mod tests { | |||
|
840 | 867 | b"whatever", |
|
841 | 868 | Path::new("") |
|
842 | 869 | ), |
|
843 | b"(?:/|$)" | |
|
870 | GlobSuffix::MoreComponents | |
|
844 | 871 | ) |
|
845 | 872 | .unwrap(), |
|
846 | 873 | None, |
@@ -852,7 +879,7 mod tests { | |||
|
852 | 879 | b"*.o", |
|
853 | 880 | Path::new("") |
|
854 | 881 | ), |
|
855 | b"(?:/|$)" | |
|
882 | GlobSuffix::MoreComponents | |
|
856 | 883 | ) |
|
857 | 884 | .unwrap(), |
|
858 | 885 | Some(br"[^/]*\.o(?:/|$)".to_vec()), |
@@ -868,7 +895,7 mod tests { | |||
|
868 | 895 | b"^ba{2}r", |
|
869 | 896 | Path::new("") |
|
870 | 897 | ), |
|
871 | b"(?:/|$)" | |
|
898 | GlobSuffix::MoreComponents | |
|
872 | 899 | ) |
|
873 | 900 | .unwrap(), |
|
874 | 901 | Some(b"^ba{2}r".to_vec()), |
@@ -880,7 +907,7 mod tests { | |||
|
880 | 907 | b"ba{2}r", |
|
881 | 908 | Path::new("") |
|
882 | 909 | ), |
|
883 | b"(?:/|$)" | |
|
910 | GlobSuffix::MoreComponents | |
|
884 | 911 | ) |
|
885 | 912 | .unwrap(), |
|
886 | 913 | Some(b".*ba{2}r".to_vec()), |
@@ -892,7 +919,7 mod tests { | |||
|
892 | 919 | b"(?ia)ba{2}r", |
|
893 | 920 | Path::new("") |
|
894 | 921 | ), |
|
895 | b"(?:/|$)" | |
|
922 | GlobSuffix::MoreComponents | |
|
896 | 923 | ) |
|
897 | 924 | .unwrap(), |
|
898 | 925 | Some(b"(?ia:.*ba{2}r)".to_vec()), |
@@ -904,7 +931,7 mod tests { | |||
|
904 | 931 | b"(?ia)^ba{2}r", |
|
905 | 932 | Path::new("") |
|
906 | 933 | ), |
|
907 | b"(?:/|$)" | |
|
934 | GlobSuffix::MoreComponents | |
|
908 | 935 | ) |
|
909 | 936 | .unwrap(), |
|
910 | 937 | Some(b"(?ia:^ba{2}r)".to_vec()), |
@@ -14,8 +14,8 use crate::{ | |||
|
14 | 14 | dirstate::dirs_multiset::{DirsChildrenMultiset, DirsMultiset}, |
|
15 | 15 | filepatterns::{ |
|
16 | 16 | build_single_regex, filter_subincludes, get_patterns_from_file, |
|
17 |
IgnorePattern, PatternError, PatternFileWarning, |
|
|
18 | PatternSyntax, | |
|
17 | GlobSuffix, IgnorePattern, PatternError, PatternFileWarning, | |
|
18 | PatternResult, PatternSyntax, | |
|
19 | 19 | }, |
|
20 | 20 | utils::{ |
|
21 | 21 | files::{dir_ancestors, find_dirs}, |
@@ -328,7 +328,8 impl<'a> PatternMatcher<'a> { | |||
|
328 | 328 | let prefix = ignore_patterns.iter().all(|k| { |
|
329 | 329 | matches!(k.syntax, PatternSyntax::Path | PatternSyntax::RelPath) |
|
330 | 330 | }); |
|
331 |
let (patterns, match_fn) = |
|
|
331 | let (patterns, match_fn) = | |
|
332 | build_match(ignore_patterns, GlobSuffix::Empty)?; | |
|
332 | 333 | |
|
333 | 334 | Ok(Self { |
|
334 | 335 | patterns, |
@@ -807,7 +808,7 fn re_matcher(pattern: &[u8]) -> Pattern | |||
|
807 | 808 | /// said regex formed by the given ignore patterns. |
|
808 | 809 | fn build_regex_match<'a>( |
|
809 | 810 | ignore_patterns: &[IgnorePattern], |
|
810 |
glob_suffix: |
|
|
811 | glob_suffix: GlobSuffix, | |
|
811 | 812 | ) -> PatternResult<(Vec<u8>, IgnoreFnType<'a>)> { |
|
812 | 813 | let mut regexps = vec![]; |
|
813 | 814 | let mut exact_set = HashSet::new(); |
@@ -927,7 +928,7 fn roots_dirs_and_parents( | |||
|
927 | 928 | /// should be matched. |
|
928 | 929 | fn build_match<'a>( |
|
929 | 930 | ignore_patterns: Vec<IgnorePattern>, |
|
930 |
glob_suffix: |
|
|
931 | glob_suffix: GlobSuffix, | |
|
931 | 932 | ) -> PatternResult<(Vec<u8>, IgnoreFnType<'a>)> { |
|
932 | 933 | let mut match_funcs: Vec<IgnoreFnType<'a>> = vec![]; |
|
933 | 934 | // For debugging and printing |
@@ -1067,7 +1068,8 impl<'a> IncludeMatcher<'a> { | |||
|
1067 | 1068 | let prefix = ignore_patterns.iter().all(|k| { |
|
1068 | 1069 | matches!(k.syntax, PatternSyntax::Path | PatternSyntax::RelPath) |
|
1069 | 1070 | }); |
|
1070 |
let (patterns, match_fn) = |
|
|
1071 | let (patterns, match_fn) = | |
|
1072 | build_match(ignore_patterns, GlobSuffix::MoreComponents)?; | |
|
1071 | 1073 | |
|
1072 | 1074 | Ok(Self { |
|
1073 | 1075 | patterns, |
General Comments 0
You need to be logged in to leave comments.
Login now