comparison rust/hg-core/src/matchers.rs @ 50695:1c31b343e514

match: add `filepath:` pattern to match an exact filepath relative to the root It's useful in certain automated workflows to make sure we recurse in directories whose name conflicts with files in other revisions. In addition it makes it possible to avoid building a potentially costly regex, improving performance when the set of files to match explicitly is large. The benchmark below are run in the following configuration : # data-env-vars.name = mozilla-central-2018-08-01-zstd-sparse-revlog # benchmark.name = files # benchmark.variants.rev = tip # benchmark.variants.files = all-list-filepath-sorted # bin-env-vars.hg.flavor = no-rust It also includes timings using the re2 engine (through the `google-re2` module) to show how much can be saved by just using a better regexp engine. Pattern time (seconds) time using re2 ----------------------------------------------------------- just "." 0.4 0.4 list of "filepath:…" 1.3 1.3 list of "path:…" 25.7 3.9 list of patterns 29.7 10.4 As you can see, Without re2, using "filepath:" instead of "path:" is a huge win. With re2, it is still about three times faster to not have to build the regex.
author Raphaël Gomès <rgomes@octobus.net>
date Mon, 12 Jun 2023 16:51:08 +0200
parents e98fd81bb151
children e037af7de2ce
comparison
equal deleted inserted replaced
50686:a41eeb877d07 50695:1c31b343e514
706 } 706 }
707 root.push(HgPathBuf::from_bytes(p).as_ref()); 707 root.push(HgPathBuf::from_bytes(p).as_ref());
708 } 708 }
709 roots.push(root); 709 roots.push(root);
710 } 710 }
711 PatternSyntax::Path | PatternSyntax::RelPath => { 711 PatternSyntax::Path
712 | PatternSyntax::RelPath
713 | PatternSyntax::FilePath => {
712 let pat = HgPath::new(if pattern == b"." { 714 let pat = HgPath::new(if pattern == b"." {
713 &[] as &[u8] 715 &[] as &[u8]
714 } else { 716 } else {
715 pattern 717 pattern
716 }); 718 });
1221 assert_eq!( 1223 assert_eq!(
1222 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")), 1224 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1223 VisitChildrenSet::This 1225 VisitChildrenSet::This
1224 ); 1226 );
1225 1227
1228 // VisitchildrensetFilePath
1229 let matcher = IncludeMatcher::new(vec![IgnorePattern::new(
1230 PatternSyntax::FilePath,
1231 b"dir/z",
1232 Path::new(""),
1233 )])
1234 .unwrap();
1235
1236 let mut set = HashSet::new();
1237 set.insert(HgPathBuf::from_bytes(b"dir"));
1238 assert_eq!(
1239 matcher.visit_children_set(HgPath::new(b"")),
1240 VisitChildrenSet::Set(set)
1241 );
1242 assert_eq!(
1243 matcher.visit_children_set(HgPath::new(b"folder")),
1244 VisitChildrenSet::Empty
1245 );
1246 let mut set = HashSet::new();
1247 set.insert(HgPathBuf::from_bytes(b"z"));
1248 assert_eq!(
1249 matcher.visit_children_set(HgPath::new(b"dir")),
1250 VisitChildrenSet::Set(set)
1251 );
1252 // OPT: these should probably be set().
1253 assert_eq!(
1254 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1255 VisitChildrenSet::Empty
1256 );
1257 assert_eq!(
1258 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1259 VisitChildrenSet::Empty
1260 );
1261
1226 // Test multiple patterns 1262 // Test multiple patterns
1227 let matcher = IncludeMatcher::new(vec![ 1263 let matcher = IncludeMatcher::new(vec![
1228 IgnorePattern::new(PatternSyntax::RelPath, b"foo", Path::new("")), 1264 IgnorePattern::new(PatternSyntax::RelPath, b"foo", Path::new("")),
1229 IgnorePattern::new(PatternSyntax::Glob, b"g*", Path::new("")), 1265 IgnorePattern::new(PatternSyntax::Glob, b"g*", Path::new("")),
1230 ]) 1266 ])