TODOs and some cleanup/refactoring.

This commit is contained in:
Andrew Gallant 2016-09-05 10:15:13 -04:00
parent 812cdb13c6
commit d8d7560fd0
5 changed files with 70 additions and 53 deletions

View File

@ -118,14 +118,8 @@ impl Gitignore {
/// of the directory containing this gitignore) is stripped. If there is /// of the directory containing this gitignore) is stripped. If there is
/// no common suffix/prefix overlap, then path is assumed to reside in the /// no common suffix/prefix overlap, then path is assumed to reside in the
/// same directory as this gitignore file. /// same directory as this gitignore file.
///
/// If the given path has a `./` prefix then it is stripped before
/// matching.
pub fn matched<P: AsRef<Path>>(&self, path: P, is_dir: bool) -> Match { pub fn matched<P: AsRef<Path>>(&self, path: P, is_dir: bool) -> Match {
let mut path = path.as_ref(); let mut path = path.as_ref();
if let Ok(p) = path.strip_prefix("./") {
path = p;
}
if let Ok(p) = path.strip_prefix(&self.root) { if let Ok(p) = path.strip_prefix(&self.root) {
path = p; path = p;
} }

View File

@ -13,6 +13,19 @@ that rigamorole when I wrote this. In particular, it could be fast/good enough
to make its way into `glob` proper. to make its way into `glob` proper.
*/ */
// TODO(burntsushi): I'm pretty dismayed by the performance of regex sets
// here. For example, we do a first pass single-regex-of-all-globs filter
// before actually running the regex set. This turns out to be faster,
// especially in fresh checkouts of repos that don't have a lot of ignored
// files. It's not clear how hard it is to make the regex set faster.
//
// An alternative avenue is to stop doing "regex all the things." (Which, to
// be fair, is pretty fast---I just expected it to be faster.) We could do
// something clever using assumptions along the lines of "oh, most ignore
// patterns are either literals or are for ignoring file extensions." (Look
// at the .gitignore for the chromium repo---just about every pattern satisfies
// that assumption.)
use std::error::Error as StdError; use std::error::Error as StdError;
use std::fmt; use std::fmt;
use std::iter; use std::iter;

View File

@ -22,7 +22,7 @@ extern crate walkdir;
use std::error::Error; use std::error::Error;
use std::fs::File; use std::fs::File;
use std::io::{self, Write}; use std::io::{self, Write};
use std::path::{Path, PathBuf}; use std::path::Path;
use std::process; use std::process;
use std::result; use std::result;
use std::sync::Arc; use std::sync::Arc;
@ -31,6 +31,7 @@ use std::thread;
use crossbeam::sync::chase_lev::{self, Steal, Stealer}; use crossbeam::sync::chase_lev::{self, Steal, Stealer};
use grep::Grep; use grep::Grep;
use parking_lot::Mutex; use parking_lot::Mutex;
use walkdir::DirEntry;
use args::Args; use args::Args;
use out::Out; use out::Out;
@ -94,6 +95,7 @@ fn run(args: Args) -> Result<u64> {
inpbuf: args.input_buffer(), inpbuf: args.input_buffer(),
outbuf: Some(vec![]), outbuf: Some(vec![]),
grep: try!(args.grep()), grep: try!(args.grep()),
match_count: 0,
}; };
workers.push(thread::spawn(move || worker.run())); workers.push(thread::spawn(move || worker.run()));
} }
@ -103,8 +105,8 @@ fn run(args: Args) -> Result<u64> {
if p == Path::new("-") { if p == Path::new("-") {
workq.push(Work::Stdin) workq.push(Work::Stdin)
} else { } else {
for path in args.walker(p) { for ent in args.walker(p) {
workq.push(Work::File(path)); workq.push(Work::File(ent));
} }
} }
} }
@ -126,8 +128,8 @@ fn run_files(args: Args) -> Result<u64> {
printer.path(&Path::new("<stdin>")); printer.path(&Path::new("<stdin>"));
file_count += 1; file_count += 1;
} else { } else {
for path in args.walker(p) { for ent in args.walker(p) {
printer.path(path); printer.path(ent.path());
file_count += 1; file_count += 1;
} }
} }
@ -146,11 +148,16 @@ fn run_types(args: Args) -> Result<u64> {
} }
enum Work { enum Work {
File(PathBuf),
Stdin, Stdin,
File(DirEntry),
Quit, Quit,
} }
enum WorkReady {
Stdin,
File(DirEntry, File),
}
struct Worker { struct Worker {
args: Arc<Args>, args: Arc<Args>,
out: Arc<Mutex<Out<io::Stdout>>>, out: Arc<Mutex<Out<io::Stdout>>>,
@ -158,51 +165,31 @@ struct Worker {
inpbuf: InputBuffer, inpbuf: InputBuffer,
outbuf: Option<Vec<u8>>, outbuf: Option<Vec<u8>>,
grep: Grep, grep: Grep,
match_count: u64,
} }
impl Worker { impl Worker {
fn run(mut self) -> u64 { fn run(mut self) -> u64 {
let mut match_count = 0; self.match_count = 0;
loop { loop {
let (path, file) = match self.chan_work.steal() { let work = match self.chan_work.steal() {
Steal::Empty | Steal::Abort => continue, Steal::Empty | Steal::Abort => continue,
Steal::Data(Work::Quit) => break, Steal::Data(Work::Quit) => break,
Steal::Data(Work::File(path)) => { Steal::Data(Work::Stdin) => WorkReady::Stdin,
match File::open(&path) { Steal::Data(Work::File(ent)) => {
Ok(file) => (path, Some(file)), match File::open(ent.path()) {
Ok(file) => WorkReady::File(ent, file),
Err(err) => { Err(err) => {
eprintln!("{}: {}", path.display(), err); eprintln!("{}: {}", ent.path().display(), err);
continue; continue;
} }
} }
} }
Steal::Data(Work::Stdin) => {
(Path::new("<stdin>").to_path_buf(), None)
}
}; };
let mut outbuf = self.outbuf.take().unwrap(); let mut outbuf = self.outbuf.take().unwrap();
outbuf.clear(); outbuf.clear();
let mut printer = self.args.printer(outbuf); let mut printer = self.args.printer(outbuf);
{ self.do_work(&mut printer, work);
let result = match file {
None => {
let stdin = io::stdin();
let stdin = stdin.lock();
self.search(&mut printer, &path, stdin)
}
Some(file) => {
self.search(&mut printer, &path, file)
}
};
match result {
Ok(count) => {
match_count += count;
}
Err(err) => {
eprintln!("{}", err);
}
}
}
let outbuf = printer.into_inner(); let outbuf = printer.into_inner();
if !outbuf.is_empty() { if !outbuf.is_empty() {
let mut out = self.out.lock(); let mut out = self.out.lock();
@ -210,7 +197,36 @@ impl Worker {
} }
self.outbuf = Some(outbuf); self.outbuf = Some(outbuf);
} }
match_count self.match_count
}
fn do_work<W: io::Write>(
&mut self,
printer: &mut Printer<W>,
work: WorkReady,
) {
let result = match work {
WorkReady::Stdin => {
let stdin = io::stdin();
let stdin = stdin.lock();
self.search(printer, &Path::new("<stdin>"), stdin)
}
WorkReady::File(ent, file) => {
let mut path = ent.path();
if let Ok(p) = path.strip_prefix("./") {
path = p;
}
self.search(printer, path, file)
}
};
match result {
Ok(count) => {
self.match_count += count;
}
Err(err) => {
eprintln!("{}", err);
}
}
} }
fn search<R: io::Read, W: io::Write>( fn search<R: io::Read, W: io::Write>(

View File

@ -739,7 +739,7 @@ fn main() {
mut map: F, mut map: F,
) -> (u64, String) { ) -> (u64, String) {
let mut inp = InputBuffer::with_capacity(1); let mut inp = InputBuffer::with_capacity(1);
let mut pp = Printer::new(vec![]); let mut pp = Printer::new(vec![]).with_filename(true);
let grep = GrepBuilder::new(pat).build().unwrap(); let grep = GrepBuilder::new(pat).build().unwrap();
let count = { let count = {
let searcher = Searcher::new( let searcher = Searcher::new(
@ -755,7 +755,7 @@ fn main() {
mut map: F, mut map: F,
) -> (u64, String) { ) -> (u64, String) {
let mut inp = InputBuffer::with_capacity(4096); let mut inp = InputBuffer::with_capacity(4096);
let mut pp = Printer::new(vec![]); let mut pp = Printer::new(vec![]).with_filename(true);
let grep = GrepBuilder::new(pat).build().unwrap(); let grep = GrepBuilder::new(pat).build().unwrap();
let count = { let count = {
let searcher = Searcher::new( let searcher = Searcher::new(

View File

@ -4,8 +4,6 @@ crate that can efficiently skip and ignore files and directories specified in
a user's ignore patterns. a user's ignore patterns.
*/ */
use std::path::PathBuf;
use walkdir::{self, DirEntry, WalkDir, WalkDirIterator}; use walkdir::{self, DirEntry, WalkDir, WalkDirIterator};
use ignore::Ignore; use ignore::Ignore;
@ -41,9 +39,9 @@ impl Iter {
} }
impl Iterator for Iter { impl Iterator for Iter {
type Item = PathBuf; type Item = DirEntry;
fn next(&mut self) -> Option<PathBuf> { fn next(&mut self) -> Option<DirEntry> {
while let Some(ev) = self.it.next() { while let Some(ev) = self.it.next() {
match ev { match ev {
Err(err) => { Err(err) => {
@ -76,11 +74,7 @@ impl Iterator for Iter {
if !ent.file_type().is_file() { if !ent.file_type().is_file() {
continue; continue;
} }
let mut path = ent.path(); return Some(ent);
if let Ok(p) = path.strip_prefix("./") {
path = p;
}
return Some(path.to_path_buf());
} }
} }
} }