diff --git a/Cargo.lock b/Cargo.lock index f1932c89..a59b6416 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "ripgrep" -version = "0.2.1" +version = "0.2.2" dependencies = [ "deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.6.86 (registry+https://github.com/rust-lang/crates.io-index)", @@ -17,6 +17,7 @@ dependencies = [ "regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 7c4937ce..1b702790 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ num_cpus = "1" regex = "0.1.77" rustc-serialize = "0.3" term = "0.4" +thread_local = "0.2.7" walkdir = "0.1" [target.'cfg(windows)'.dependencies] diff --git a/src/gitignore.rs b/src/gitignore.rs index 4c7e8203..9daeb3cb 100644 --- a/src/gitignore.rs +++ b/src/gitignore.rs @@ -27,9 +27,11 @@ use std::fmt; use std::fs::File; use std::io::{self, BufRead}; use std::path::{Path, PathBuf}; +use std::sync::Arc; use globset::{self, Candidate, GlobBuilder, GlobSet, GlobSetBuilder}; use regex; +use thread_local::ThreadLocal; use pathutil::{is_file_name, strip_prefix}; @@ -87,6 +89,7 @@ pub struct Gitignore { patterns: Vec, num_ignores: u64, num_whitelist: u64, + matches: Arc>>>, } impl Gitignore { @@ -133,27 +136,21 @@ impl Gitignore { /// Like matched, but takes a path that has already been stripped. pub fn matched_stripped(&self, path: &Path, is_dir: bool) -> Match { - thread_local! { - static MATCHES: RefCell> = { - RefCell::new(vec![]) + let _matches = self.matches.get_default(); + let mut matches = _matches.borrow_mut(); + let candidate = Candidate::new(path); + self.set.matches_candidate_into(&candidate, &mut *matches); + for &i in matches.iter().rev() { + let pat = &self.patterns[i]; + if !pat.only_dir || is_dir { + return if pat.whitelist { + Match::Whitelist(pat) + } else { + Match::Ignored(pat) + }; } - }; - MATCHES.with(|matches| { - let mut matches = matches.borrow_mut(); - let candidate = Candidate::new(path); - self.set.matches_candidate_into(&candidate, &mut *matches); - for &i in matches.iter().rev() { - let pat = &self.patterns[i]; - if !pat.only_dir || is_dir { - return if pat.whitelist { - Match::Whitelist(pat) - } else { - Match::Ignored(pat) - }; - } - } - Match::None - }) + } + Match::None } /// Returns the total number of ignore patterns. @@ -256,6 +253,7 @@ impl GitignoreBuilder { patterns: self.patterns, num_ignores: nignores as u64, num_whitelist: nwhitelist as u64, + matches: Arc::new(ThreadLocal::default()), }) } diff --git a/src/main.rs b/src/main.rs index c70a3c52..7a6ac021 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ extern crate num_cpus; extern crate regex; extern crate rustc_serialize; extern crate term; +extern crate thread_local; extern crate walkdir; #[cfg(windows)] extern crate winapi;