##// END OF EJS Templates
rust: add IntersectionMatcher...
Raphaël Gomès -
r50245:5e53ecbc default
parent child Browse files
Show More
@@ -368,6 +368,87 b' impl UnionMatcher {'
368 }
368 }
369 }
369 }
370
370
371 pub struct IntersectionMatcher {
372 m1: Box<dyn Matcher + Sync>,
373 m2: Box<dyn Matcher + Sync>,
374 files: Option<HashSet<HgPathBuf>>,
375 }
376
377 impl Matcher for IntersectionMatcher {
378 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
379 self.files.as_ref()
380 }
381
382 fn exact_match(&self, filename: &HgPath) -> bool {
383 self.files.as_ref().map_or(false, |f| f.contains(filename))
384 }
385
386 fn matches(&self, filename: &HgPath) -> bool {
387 self.m1.matches(filename) && self.m2.matches(filename)
388 }
389
390 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
391 let m1_set = self.m1.visit_children_set(directory);
392 if m1_set == VisitChildrenSet::Empty {
393 return VisitChildrenSet::Empty;
394 }
395 let m2_set = self.m2.visit_children_set(directory);
396 if m2_set == VisitChildrenSet::Empty {
397 return VisitChildrenSet::Empty;
398 }
399
400 if m1_set == VisitChildrenSet::Recursive {
401 return m2_set;
402 } else if m2_set == VisitChildrenSet::Recursive {
403 return m1_set;
404 }
405
406 match (&m1_set, &m2_set) {
407 (VisitChildrenSet::Recursive, _) => m2_set,
408 (_, VisitChildrenSet::Recursive) => m1_set,
409 (VisitChildrenSet::This, _) | (_, VisitChildrenSet::This) => {
410 VisitChildrenSet::This
411 }
412 (VisitChildrenSet::Set(m1), VisitChildrenSet::Set(m2)) => {
413 let set: HashSet<_> = m1.intersection(&m2).cloned().collect();
414 if set.is_empty() {
415 VisitChildrenSet::Empty
416 } else {
417 VisitChildrenSet::Set(set)
418 }
419 }
420 _ => unreachable!(),
421 }
422 }
423
424 fn matches_everything(&self) -> bool {
425 self.m1.matches_everything() && self.m2.matches_everything()
426 }
427
428 fn is_exact(&self) -> bool {
429 self.m1.is_exact() || self.m2.is_exact()
430 }
431 }
432
433 impl IntersectionMatcher {
434 pub fn new(
435 mut m1: Box<dyn Matcher + Sync>,
436 mut m2: Box<dyn Matcher + Sync>,
437 ) -> Self {
438 let files = if m1.is_exact() || m2.is_exact() {
439 if !m1.is_exact() {
440 std::mem::swap(&mut m1, &mut m2);
441 }
442 m1.file_set().map(|m1_files| {
443 m1_files.iter().cloned().filter(|f| m2.matches(f)).collect()
444 })
445 } else {
446 None
447 };
448 Self { m1, m2, files }
449 }
450 }
451
371 /// Returns a function that matches an `HgPath` against the given regex
452 /// Returns a function that matches an `HgPath` against the given regex
372 /// pattern.
453 /// pattern.
373 ///
454 ///
@@ -1147,4 +1228,215 b' mod tests {'
1147 VisitChildrenSet::This
1228 VisitChildrenSet::This
1148 );
1229 );
1149 }
1230 }
1231
1232 #[test]
1233 fn test_intersectionmatcher() {
1234 // Include path + Include rootfiles
1235 let m1 = Box::new(
1236 IncludeMatcher::new(vec![IgnorePattern::new(
1237 PatternSyntax::RelPath,
1238 b"dir/subdir",
1239 Path::new(""),
1240 )])
1241 .unwrap(),
1242 );
1243 let m2 = Box::new(
1244 IncludeMatcher::new(vec![IgnorePattern::new(
1245 PatternSyntax::RootFiles,
1246 b"dir",
1247 Path::new(""),
1248 )])
1249 .unwrap(),
1250 );
1251 let matcher = IntersectionMatcher::new(m1, m2);
1252
1253 let mut set = HashSet::new();
1254 set.insert(HgPathBuf::from_bytes(b"dir"));
1255 assert_eq!(
1256 matcher.visit_children_set(HgPath::new(b"")),
1257 VisitChildrenSet::Set(set)
1258 );
1259 assert_eq!(
1260 matcher.visit_children_set(HgPath::new(b"dir")),
1261 VisitChildrenSet::This
1262 );
1263 assert_eq!(
1264 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1265 VisitChildrenSet::Empty
1266 );
1267 assert_eq!(
1268 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1269 VisitChildrenSet::Empty
1270 );
1271 assert_eq!(
1272 matcher.visit_children_set(HgPath::new(b"folder")),
1273 VisitChildrenSet::Empty
1274 );
1275 assert_eq!(
1276 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1277 VisitChildrenSet::Empty
1278 );
1279 assert_eq!(
1280 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1281 VisitChildrenSet::Empty
1282 );
1283
1284 // Non intersecting paths
1285 let m1 = Box::new(
1286 IncludeMatcher::new(vec![IgnorePattern::new(
1287 PatternSyntax::RelPath,
1288 b"dir/subdir",
1289 Path::new(""),
1290 )])
1291 .unwrap(),
1292 );
1293 let m2 = Box::new(
1294 IncludeMatcher::new(vec![IgnorePattern::new(
1295 PatternSyntax::RelPath,
1296 b"folder",
1297 Path::new(""),
1298 )])
1299 .unwrap(),
1300 );
1301 let matcher = IntersectionMatcher::new(m1, m2);
1302
1303 assert_eq!(
1304 matcher.visit_children_set(HgPath::new(b"")),
1305 VisitChildrenSet::Empty
1306 );
1307 assert_eq!(
1308 matcher.visit_children_set(HgPath::new(b"dir")),
1309 VisitChildrenSet::Empty
1310 );
1311 assert_eq!(
1312 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1313 VisitChildrenSet::Empty
1314 );
1315 assert_eq!(
1316 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1317 VisitChildrenSet::Empty
1318 );
1319 assert_eq!(
1320 matcher.visit_children_set(HgPath::new(b"folder")),
1321 VisitChildrenSet::Empty
1322 );
1323 assert_eq!(
1324 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1325 VisitChildrenSet::Empty
1326 );
1327 assert_eq!(
1328 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1329 VisitChildrenSet::Empty
1330 );
1331
1332 // Nested paths
1333 let m1 = Box::new(
1334 IncludeMatcher::new(vec![IgnorePattern::new(
1335 PatternSyntax::RelPath,
1336 b"dir/subdir/x",
1337 Path::new(""),
1338 )])
1339 .unwrap(),
1340 );
1341 let m2 = Box::new(
1342 IncludeMatcher::new(vec![IgnorePattern::new(
1343 PatternSyntax::RelPath,
1344 b"dir/subdir",
1345 Path::new(""),
1346 )])
1347 .unwrap(),
1348 );
1349 let matcher = IntersectionMatcher::new(m1, m2);
1350
1351 let mut set = HashSet::new();
1352 set.insert(HgPathBuf::from_bytes(b"dir"));
1353 assert_eq!(
1354 matcher.visit_children_set(HgPath::new(b"")),
1355 VisitChildrenSet::Set(set)
1356 );
1357
1358 let mut set = HashSet::new();
1359 set.insert(HgPathBuf::from_bytes(b"subdir"));
1360 assert_eq!(
1361 matcher.visit_children_set(HgPath::new(b"dir")),
1362 VisitChildrenSet::Set(set)
1363 );
1364 let mut set = HashSet::new();
1365 set.insert(HgPathBuf::from_bytes(b"x"));
1366 assert_eq!(
1367 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1368 VisitChildrenSet::Set(set)
1369 );
1370 assert_eq!(
1371 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1372 VisitChildrenSet::Empty
1373 );
1374 assert_eq!(
1375 matcher.visit_children_set(HgPath::new(b"folder")),
1376 VisitChildrenSet::Empty
1377 );
1378 assert_eq!(
1379 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1380 VisitChildrenSet::Empty
1381 );
1382 // OPT: this should probably be 'all' not 'this'.
1383 assert_eq!(
1384 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1385 VisitChildrenSet::This
1386 );
1387
1388 // Diverging paths
1389 let m1 = Box::new(
1390 IncludeMatcher::new(vec![IgnorePattern::new(
1391 PatternSyntax::RelPath,
1392 b"dir/subdir/x",
1393 Path::new(""),
1394 )])
1395 .unwrap(),
1396 );
1397 let m2 = Box::new(
1398 IncludeMatcher::new(vec![IgnorePattern::new(
1399 PatternSyntax::RelPath,
1400 b"dir/subdir/z",
1401 Path::new(""),
1402 )])
1403 .unwrap(),
1404 );
1405 let matcher = IntersectionMatcher::new(m1, m2);
1406
1407 // OPT: these next two could probably be Empty as well.
1408 let mut set = HashSet::new();
1409 set.insert(HgPathBuf::from_bytes(b"dir"));
1410 assert_eq!(
1411 matcher.visit_children_set(HgPath::new(b"")),
1412 VisitChildrenSet::Set(set)
1413 );
1414 // OPT: these next two could probably be Empty as well.
1415 let mut set = HashSet::new();
1416 set.insert(HgPathBuf::from_bytes(b"subdir"));
1417 assert_eq!(
1418 matcher.visit_children_set(HgPath::new(b"dir")),
1419 VisitChildrenSet::Set(set)
1420 );
1421 assert_eq!(
1422 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1423 VisitChildrenSet::Empty
1424 );
1425 assert_eq!(
1426 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1427 VisitChildrenSet::Empty
1428 );
1429 assert_eq!(
1430 matcher.visit_children_set(HgPath::new(b"folder")),
1431 VisitChildrenSet::Empty
1432 );
1433 assert_eq!(
1434 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1435 VisitChildrenSet::Empty
1436 );
1437 assert_eq!(
1438 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1439 VisitChildrenSet::Empty
1440 );
1441 }
1150 }
1442 }
General Comments 0
You need to be logged in to leave comments. Login now