2144 path: &'a HgPath, |
2144 path: &'a HgPath, |
2145 matching: &'a Tree, |
2145 matching: &'a Tree, |
2146 visit_children_set: &'a VisitChildrenSet, |
2146 visit_children_set: &'a VisitChildrenSet, |
2147 } |
2147 } |
2148 |
2148 |
2149 fn holds(matching: &Tree, vcs: &VisitChildrenSet) -> bool { |
2149 fn holds( |
|
2150 matching: &Tree, |
|
2151 not_matching: &Tree, |
|
2152 vcs: &VisitChildrenSet, |
|
2153 ) -> bool { |
2150 match vcs { |
2154 match vcs { |
2151 VisitChildrenSet::Empty => matching.is_empty(), |
2155 VisitChildrenSet::Empty => matching.is_empty(), |
2152 VisitChildrenSet::This => { |
2156 VisitChildrenSet::This => { |
2153 // `This` does not come with any obligations. |
2157 // `This` does not come with any obligations. |
2154 true |
2158 true |
2155 } |
2159 } |
2156 VisitChildrenSet::Recursive => { |
2160 VisitChildrenSet::Recursive => { |
2157 // `Recursive` does not come with any correctness |
2161 // `Recursive` requires that *everything* in the |
2158 // obligations. |
2162 // subtree matches. This |
2159 // It instructs the caller to stop calling |
2163 // requirement is relied on for example in |
2160 // `visit_children_set` for all |
2164 // DifferenceMatcher implementation. |
2161 // descendants, so may have negative performance |
2165 not_matching.is_empty() |
2162 // implications, but we're not testing against that |
|
2163 // here. |
|
2164 true |
|
2165 } |
2166 } |
2166 VisitChildrenSet::Set(allowed_children) => { |
2167 VisitChildrenSet::Set(allowed_children) => { |
2167 // `allowed_children` does not distinguish between |
2168 // `allowed_children` does not distinguish between |
2168 // files and directories: if it's not included, it |
2169 // files and directories: if it's not included, it |
2169 // must not be matched. |
2170 // must not be matched. |
2221 |
2223 |
2222 fn is_empty(&self) -> bool { |
2224 fn is_empty(&self) -> bool { |
2223 self.files.is_empty() && self.dirs.is_empty() |
2225 self.files.is_empty() && self.dirs.is_empty() |
2224 } |
2226 } |
2225 |
2227 |
|
2228 fn make( |
|
2229 files: BTreeSet<HgPathBuf>, |
|
2230 dirs: BTreeMap<HgPathBuf, Tree>, |
|
2231 ) -> Self { |
|
2232 Self { |
|
2233 files, |
|
2234 dirs: dirs |
|
2235 .into_iter() |
|
2236 .filter(|(_k, v)| (!(v.is_empty()))) |
|
2237 .collect(), |
|
2238 } |
|
2239 } |
|
2240 |
2226 fn filter_and_check<M: Matcher + Debug>( |
2241 fn filter_and_check<M: Matcher + Debug>( |
2227 &self, |
2242 &self, |
2228 m: &M, |
2243 m: &M, |
2229 path: &HgPath, |
2244 path: &HgPath, |
2230 ) -> Self { |
2245 ) -> (Self, Self) { |
2231 let files: BTreeSet<HgPathBuf> = self |
2246 let (files1, files2): (BTreeSet<HgPathBuf>, BTreeSet<HgPathBuf>) = |
2232 .files |
2247 self.files |
2233 .iter() |
2248 .iter() |
2234 .filter(|v| m.matches(&path.join(v))) |
2249 .map(|v| v.to_owned()) |
2235 .map(|f| f.to_owned()) |
2250 .partition(|v| m.matches(&path.join(v))); |
2236 .collect(); |
2251 let (dirs1, dirs2): ( |
2237 let dirs: BTreeMap<HgPathBuf, Tree> = self |
2252 BTreeMap<HgPathBuf, Tree>, |
|
2253 BTreeMap<HgPathBuf, Tree>, |
|
2254 ) = self |
2238 .dirs |
2255 .dirs |
2239 .iter() |
2256 .iter() |
2240 .filter_map(|(k, v)| { |
2257 .map(|(k, v)| { |
2241 let path = path.join(k); |
2258 let path = path.join(k); |
2242 let v = v.filter_and_check(m, &path); |
2259 let (t1, t2) = v.filter_and_check(m, &path); |
2243 if v.is_empty() { |
2260 ((k.clone(), t1), (k.clone(), t2)) |
2244 None |
|
2245 } else { |
|
2246 Some((k.to_owned(), v)) |
|
2247 } |
|
2248 }) |
2261 }) |
2249 .collect(); |
2262 .unzip(); |
2250 let matching = Self { files, dirs }; |
2263 let matching = Self::make(files1, dirs1); |
|
2264 let not_matching = Self::make(files2, dirs2); |
2251 let vcs = m.visit_children_set(path); |
2265 let vcs = m.visit_children_set(path); |
2252 invariants::visit_children_set::check(m, path, &matching, &vcs); |
2266 invariants::visit_children_set::check( |
2253 matching |
2267 m, |
|
2268 path, |
|
2269 &matching, |
|
2270 ¬_matching, |
|
2271 &vcs, |
|
2272 ); |
|
2273 (matching, not_matching) |
2254 } |
2274 } |
2255 |
2275 |
2256 fn check_matcher<M: Matcher + Debug>( |
2276 fn check_matcher<M: Matcher + Debug>( |
2257 &self, |
2277 &self, |
2258 m: &M, |
2278 m: &M, |
2259 expect_count: usize, |
2279 expect_count: usize, |
2260 ) { |
2280 ) { |
2261 let res = self.filter_and_check(m, &HgPathBuf::new()); |
2281 let res = self.filter_and_check(m, &HgPathBuf::new()); |
2262 if expect_count != res.len() { |
2282 if expect_count != res.0.len() { |
2263 eprintln!( |
2283 eprintln!( |
2264 "warning: expected {} matches, got {} for {:#?}", |
2284 "warning: expected {} matches, got {} for {:#?}", |
2265 expect_count, |
2285 expect_count, |
2266 res.len(), |
2286 res.0.len(), |
2267 m |
2287 m |
2268 ); |
2288 ); |
2269 } |
2289 } |
2270 } |
2290 } |
2271 } |
2291 } |