mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-11-23 21:54:45 +02:00
Refactor and test glob sets.
This commit goes a long way toward refactoring glob sets so that the code is easier to maintain going forward. In particular, it makes the literal optimizations that glob sets used a lot more structured and much easier to extend. Tests have also been modified to include glob sets. There's still a bit of polish work left to do before a release. This also fixes the immediate issue where large gitignore files were causing ripgrep to slow way down. While we don't technically fix it for good, we're a lot better about reducing the number of regexes we compile. In particular, if a gitignore file contains thousands of patterns that can't be matched more simply using literals, then ripgrep will slow down again. We could fix this for good by avoiding RegexSet if the number of regexes grows too large. Fixes #134.
This commit is contained in:
31
src/types.rs
31
src/types.rs
@@ -11,7 +11,7 @@ use std::path::Path;
|
||||
use regex;
|
||||
|
||||
use gitignore::{Match, Pattern};
|
||||
use globset::{self, MatchOptions};
|
||||
use globset::{self, PatternBuilder, Set, SetBuilder};
|
||||
|
||||
const TYPE_EXTENSIONS: &'static [(&'static str, &'static [&'static str])] = &[
|
||||
("asm", &["*.asm", "*.s", "*.S"]),
|
||||
@@ -161,8 +161,8 @@ impl FileTypeDef {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Types {
|
||||
defs: Vec<FileTypeDef>,
|
||||
selected: Option<globset::SetYesNo>,
|
||||
negated: Option<globset::SetYesNo>,
|
||||
selected: Option<Set>,
|
||||
negated: Option<Set>,
|
||||
has_selected: bool,
|
||||
unmatched_pat: Pattern,
|
||||
}
|
||||
@@ -175,8 +175,8 @@ impl Types {
|
||||
/// If has_selected is true, then at least one file type was selected.
|
||||
/// Therefore, any non-matches should be ignored.
|
||||
fn new(
|
||||
selected: Option<globset::SetYesNo>,
|
||||
negated: Option<globset::SetYesNo>,
|
||||
selected: Option<Set>,
|
||||
negated: Option<Set>,
|
||||
has_selected: bool,
|
||||
defs: Vec<FileTypeDef>,
|
||||
) -> Types {
|
||||
@@ -265,14 +265,11 @@ impl TypesBuilder {
|
||||
/// Build the current set of file type definitions *and* selections into
|
||||
/// a file type matcher.
|
||||
pub fn build(&self) -> Result<Types, Error> {
|
||||
let opts = MatchOptions {
|
||||
require_literal_separator: true, ..MatchOptions::default()
|
||||
};
|
||||
let selected_globs =
|
||||
if self.selected.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let mut bset = globset::SetBuilder::new();
|
||||
let mut bset = SetBuilder::new();
|
||||
for name in &self.selected {
|
||||
let globs = match self.types.get(name) {
|
||||
Some(globs) => globs,
|
||||
@@ -282,16 +279,19 @@ impl TypesBuilder {
|
||||
}
|
||||
};
|
||||
for glob in globs {
|
||||
try!(bset.add_with(glob, &opts));
|
||||
let pat = try!(
|
||||
PatternBuilder::new(glob)
|
||||
.literal_separator(true).build());
|
||||
bset.add(pat);
|
||||
}
|
||||
}
|
||||
Some(try!(bset.build_yesno()))
|
||||
Some(try!(bset.build()))
|
||||
};
|
||||
let negated_globs =
|
||||
if self.negated.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let mut bset = globset::SetBuilder::new();
|
||||
let mut bset = SetBuilder::new();
|
||||
for name in &self.negated {
|
||||
let globs = match self.types.get(name) {
|
||||
Some(globs) => globs,
|
||||
@@ -301,10 +301,13 @@ impl TypesBuilder {
|
||||
}
|
||||
};
|
||||
for glob in globs {
|
||||
try!(bset.add_with(glob, &opts));
|
||||
let pat = try!(
|
||||
PatternBuilder::new(glob)
|
||||
.literal_separator(true).build());
|
||||
bset.add(pat);
|
||||
}
|
||||
}
|
||||
Some(try!(bset.build_yesno()))
|
||||
Some(try!(bset.build()))
|
||||
};
|
||||
Ok(Types::new(
|
||||
selected_globs,
|
||||
|
||||
Reference in New Issue
Block a user