summaryrefslogtreecommitdiffstats
path: root/src/glob.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/glob.rs')
-rw-r--r--src/glob.rs37
1 files changed, 36 insertions, 1 deletions
diff --git a/src/glob.rs b/src/glob.rs
index e7da9322..bb033d69 100644
--- a/src/glob.rs
+++ b/src/glob.rs
@@ -124,6 +124,8 @@ pub struct Set {
base_prefixes_map: Vec<usize>,
base_suffixes: Vec<Vec<u8>>,
base_suffixes_map: Vec<usize>,
+ base_regexes: RegexSet,
+ base_regexes_map: Vec<usize>,
regexes: RegexSet,
regexes_map: Vec<usize>,
}
@@ -195,7 +197,14 @@ impl Set {
}
}
}
- into.extend(self.regexes.matches(path_bytes));
+ if let Some(ref basename) = basename {
+ for i in self.base_regexes.matches(&**basename) {
+ into.push(self.base_regexes_map[i]);
+ }
+ }
+ for i in self.regexes.matches(path_bytes) {
+ into.push(self.regexes_map[i]);
+ }
into.sort();
}
@@ -207,6 +216,7 @@ impl Set {
let (mut base_prefixes, mut base_prefixes_map) = (vec![], vec![]);
let (mut base_suffixes, mut base_suffixes_map) = (vec![], vec![]);
let (mut regexes, mut regexes_map) = (vec![], vec![]);
+ let (mut base_regexes, mut base_regexes_map) = (vec![], vec![]);
for (i, &(ref p, ref o)) in pats.iter().enumerate() {
if let Some(ext) = p.ext() {
exts.entry(ext).or_insert(vec![]).push(i);
@@ -221,6 +231,10 @@ impl Set {
} else if let Some(literal) = p.base_literal_suffix() {
base_suffixes.push(literal.into_bytes());
base_suffixes_map.push(i);
+ } else if p.is_only_basename() {
+ let part = format!("(?:{})", p.to_regex_with(o));
+ base_regexes.push(part);
+ base_regexes_map.push(i);
} else {
let part = format!("(?:{})", p.to_regex_with(o));
regexes.push(part);
@@ -236,6 +250,8 @@ impl Set {
base_prefixes_map: base_prefixes_map,
base_suffixes: base_suffixes,
base_suffixes_map: base_suffixes_map,
+ base_regexes: try!(RegexSet::new(base_regexes)),
+ base_regexes_map: base_regexes_map,
regexes: try!(RegexSet::new(regexes)),
regexes_map: regexes_map,
})
@@ -402,6 +418,25 @@ impl Pattern {
Some(lit)
}
+ /// Returns true if and only if this pattern only inspects the basename
+ /// of a path.
+ pub fn is_only_basename(&self) -> bool {
+ match self.tokens.get(0) {
+ Some(&Token::RecursivePrefix) => {}
+ _ => return false,
+ }
+ for t in &self.tokens[1..] {
+ match *t {
+ Token::Literal(c) if c == '/' || c == '\\' => return false,
+ Token::RecursivePrefix
+ | Token::RecursiveSuffix
+ | Token::RecursiveZeroOrMore => return false,
+ _ => {}
+ }
+ }
+ true
+ }
+
/// Returns the pattern as a literal if and only if the pattern must match
/// an entire path exactly.
///