rust/hg-core/src/matchers.rs
changeset 49348 b508cffd3c04
parent 49346 137d6bb71937
child 49350 5e53ecbc308f
equal deleted inserted replaced
49347:75119bbee3d1 49348:b508cffd3c04
   302     fn is_exact(&self) -> bool {
   302     fn is_exact(&self) -> bool {
   303         false
   303         false
   304     }
   304     }
   305 }
   305 }
   306 
   306 
       
   307 /// The union of multiple matchers. Will match if any of the matchers match.
       
   308 pub struct UnionMatcher {
       
   309     matchers: Vec<Box<dyn Matcher + Sync>>,
       
   310 }
       
   311 
       
   312 impl Matcher for UnionMatcher {
       
   313     fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
       
   314         None
       
   315     }
       
   316 
       
   317     fn exact_match(&self, _filename: &HgPath) -> bool {
       
   318         false
       
   319     }
       
   320 
       
   321     fn matches(&self, filename: &HgPath) -> bool {
       
   322         self.matchers.iter().any(|m| m.matches(filename))
       
   323     }
       
   324 
       
   325     fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
       
   326         let mut result = HashSet::new();
       
   327         let mut this = false;
       
   328         for matcher in self.matchers.iter() {
       
   329             let visit = matcher.visit_children_set(directory);
       
   330             match visit {
       
   331                 VisitChildrenSet::Empty => continue,
       
   332                 VisitChildrenSet::This => {
       
   333                     this = true;
       
   334                     // Don't break, we might have an 'all' in here.
       
   335                     continue;
       
   336                 }
       
   337                 VisitChildrenSet::Set(set) => {
       
   338                     result.extend(set);
       
   339                 }
       
   340                 VisitChildrenSet::Recursive => {
       
   341                     return visit;
       
   342                 }
       
   343             }
       
   344         }
       
   345         if this {
       
   346             return VisitChildrenSet::This;
       
   347         }
       
   348         if result.is_empty() {
       
   349             VisitChildrenSet::Empty
       
   350         } else {
       
   351             VisitChildrenSet::Set(result)
       
   352         }
       
   353     }
       
   354 
       
   355     fn matches_everything(&self) -> bool {
       
   356         // TODO Maybe if all are AlwaysMatcher?
       
   357         false
       
   358     }
       
   359 
       
   360     fn is_exact(&self) -> bool {
       
   361         false
       
   362     }
       
   363 }
       
   364 
       
   365 impl UnionMatcher {
       
   366     pub fn new(matchers: Vec<Box<dyn Matcher + Sync>>) -> Self {
       
   367         Self { matchers }
       
   368     }
       
   369 }
       
   370 
   307 /// Returns a function that matches an `HgPath` against the given regex
   371 /// Returns a function that matches an `HgPath` against the given regex
   308 /// pattern.
   372 /// pattern.
   309 ///
   373 ///
   310 /// This can fail when the pattern is invalid or not supported by the
   374 /// This can fail when the pattern is invalid or not supported by the
   311 /// underlying engine (the `regex` crate), for instance anything with
   375 /// underlying engine (the `regex` crate), for instance anything with
   923         assert_eq!(
   987         assert_eq!(
   924             matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
   988             matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
   925             VisitChildrenSet::This
   989             VisitChildrenSet::This
   926         );
   990         );
   927     }
   991     }
   928 }
   992 
       
   993     #[test]
       
   994     fn test_unionmatcher() {
       
   995         // Path + Rootfiles
       
   996         let m1 = IncludeMatcher::new(vec![IgnorePattern::new(
       
   997             PatternSyntax::RelPath,
       
   998             b"dir/subdir",
       
   999             Path::new(""),
       
  1000         )])
       
  1001         .unwrap();
       
  1002         let m2 = IncludeMatcher::new(vec![IgnorePattern::new(
       
  1003             PatternSyntax::RootFiles,
       
  1004             b"dir",
       
  1005             Path::new(""),
       
  1006         )])
       
  1007         .unwrap();
       
  1008         let matcher = UnionMatcher::new(vec![Box::new(m1), Box::new(m2)]);
       
  1009 
       
  1010         let mut set = HashSet::new();
       
  1011         set.insert(HgPathBuf::from_bytes(b"dir"));
       
  1012         assert_eq!(
       
  1013             matcher.visit_children_set(HgPath::new(b"")),
       
  1014             VisitChildrenSet::Set(set)
       
  1015         );
       
  1016         assert_eq!(
       
  1017             matcher.visit_children_set(HgPath::new(b"dir")),
       
  1018             VisitChildrenSet::This
       
  1019         );
       
  1020         assert_eq!(
       
  1021             matcher.visit_children_set(HgPath::new(b"dir/subdir")),
       
  1022             VisitChildrenSet::Recursive
       
  1023         );
       
  1024         assert_eq!(
       
  1025             matcher.visit_children_set(HgPath::new(b"dir/foo")),
       
  1026             VisitChildrenSet::Empty
       
  1027         );
       
  1028         assert_eq!(
       
  1029             matcher.visit_children_set(HgPath::new(b"folder")),
       
  1030             VisitChildrenSet::Empty
       
  1031         );
       
  1032         assert_eq!(
       
  1033             matcher.visit_children_set(HgPath::new(b"folder")),
       
  1034             VisitChildrenSet::Empty
       
  1035         );
       
  1036 
       
  1037         // OPT: These next two could be 'all' instead of 'this'.
       
  1038         assert_eq!(
       
  1039             matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
       
  1040             VisitChildrenSet::This
       
  1041         );
       
  1042         assert_eq!(
       
  1043             matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
       
  1044             VisitChildrenSet::This
       
  1045         );
       
  1046 
       
  1047         // Path + unrelated Path
       
  1048         let m1 = IncludeMatcher::new(vec![IgnorePattern::new(
       
  1049             PatternSyntax::RelPath,
       
  1050             b"dir/subdir",
       
  1051             Path::new(""),
       
  1052         )])
       
  1053         .unwrap();
       
  1054         let m2 = IncludeMatcher::new(vec![IgnorePattern::new(
       
  1055             PatternSyntax::RelPath,
       
  1056             b"folder",
       
  1057             Path::new(""),
       
  1058         )])
       
  1059         .unwrap();
       
  1060         let matcher = UnionMatcher::new(vec![Box::new(m1), Box::new(m2)]);
       
  1061 
       
  1062         let mut set = HashSet::new();
       
  1063         set.insert(HgPathBuf::from_bytes(b"folder"));
       
  1064         set.insert(HgPathBuf::from_bytes(b"dir"));
       
  1065         assert_eq!(
       
  1066             matcher.visit_children_set(HgPath::new(b"")),
       
  1067             VisitChildrenSet::Set(set)
       
  1068         );
       
  1069         let mut set = HashSet::new();
       
  1070         set.insert(HgPathBuf::from_bytes(b"subdir"));
       
  1071         assert_eq!(
       
  1072             matcher.visit_children_set(HgPath::new(b"dir")),
       
  1073             VisitChildrenSet::Set(set)
       
  1074         );
       
  1075 
       
  1076         assert_eq!(
       
  1077             matcher.visit_children_set(HgPath::new(b"dir/subdir")),
       
  1078             VisitChildrenSet::Recursive
       
  1079         );
       
  1080         assert_eq!(
       
  1081             matcher.visit_children_set(HgPath::new(b"dir/foo")),
       
  1082             VisitChildrenSet::Empty
       
  1083         );
       
  1084 
       
  1085         assert_eq!(
       
  1086             matcher.visit_children_set(HgPath::new(b"folder")),
       
  1087             VisitChildrenSet::Recursive
       
  1088         );
       
  1089         // OPT: These next two could be 'all' instead of 'this'.
       
  1090         assert_eq!(
       
  1091             matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
       
  1092             VisitChildrenSet::This
       
  1093         );
       
  1094         assert_eq!(
       
  1095             matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
       
  1096             VisitChildrenSet::This
       
  1097         );
       
  1098 
       
  1099         // Path + subpath
       
  1100         let m1 = IncludeMatcher::new(vec![IgnorePattern::new(
       
  1101             PatternSyntax::RelPath,
       
  1102             b"dir/subdir/x",
       
  1103             Path::new(""),
       
  1104         )])
       
  1105         .unwrap();
       
  1106         let m2 = IncludeMatcher::new(vec![IgnorePattern::new(
       
  1107             PatternSyntax::RelPath,
       
  1108             b"dir/subdir",
       
  1109             Path::new(""),
       
  1110         )])
       
  1111         .unwrap();
       
  1112         let matcher = UnionMatcher::new(vec![Box::new(m1), Box::new(m2)]);
       
  1113 
       
  1114         let mut set = HashSet::new();
       
  1115         set.insert(HgPathBuf::from_bytes(b"dir"));
       
  1116         assert_eq!(
       
  1117             matcher.visit_children_set(HgPath::new(b"")),
       
  1118             VisitChildrenSet::Set(set)
       
  1119         );
       
  1120         let mut set = HashSet::new();
       
  1121         set.insert(HgPathBuf::from_bytes(b"subdir"));
       
  1122         assert_eq!(
       
  1123             matcher.visit_children_set(HgPath::new(b"dir")),
       
  1124             VisitChildrenSet::Set(set)
       
  1125         );
       
  1126 
       
  1127         assert_eq!(
       
  1128             matcher.visit_children_set(HgPath::new(b"dir/subdir")),
       
  1129             VisitChildrenSet::Recursive
       
  1130         );
       
  1131         assert_eq!(
       
  1132             matcher.visit_children_set(HgPath::new(b"dir/foo")),
       
  1133             VisitChildrenSet::Empty
       
  1134         );
       
  1135 
       
  1136         assert_eq!(
       
  1137             matcher.visit_children_set(HgPath::new(b"folder")),
       
  1138             VisitChildrenSet::Empty
       
  1139         );
       
  1140         assert_eq!(
       
  1141             matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
       
  1142             VisitChildrenSet::Recursive
       
  1143         );
       
  1144         // OPT: this should probably be 'all' not 'this'.
       
  1145         assert_eq!(
       
  1146             matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
       
  1147             VisitChildrenSet::This
       
  1148         );
       
  1149     }
       
  1150 }