2016-03-11 03:48:44 +02:00
|
|
|
#![allow(dead_code, unused_variables)]
|
2016-02-27 18:07:26 +02:00
|
|
|
|
2016-08-28 07:37:12 +02:00
|
|
|
extern crate crossbeam;
|
2016-02-27 18:07:26 +02:00
|
|
|
extern crate docopt;
|
2016-08-28 07:37:12 +02:00
|
|
|
extern crate env_logger;
|
2016-06-20 22:53:48 +02:00
|
|
|
extern crate grep;
|
2016-09-05 23:36:41 +02:00
|
|
|
#[cfg(windows)]
|
|
|
|
extern crate kernel32;
|
2016-09-04 03:48:23 +02:00
|
|
|
#[macro_use]
|
|
|
|
extern crate lazy_static;
|
2016-09-05 23:36:41 +02:00
|
|
|
extern crate libc;
|
2016-08-28 07:37:12 +02:00
|
|
|
#[macro_use]
|
|
|
|
extern crate log;
|
2016-03-11 03:48:44 +02:00
|
|
|
extern crate memchr;
|
|
|
|
extern crate memmap;
|
2016-08-26 03:44:37 +02:00
|
|
|
extern crate num_cpus;
|
2016-08-29 02:18:34 +02:00
|
|
|
extern crate parking_lot;
|
2016-02-27 18:07:26 +02:00
|
|
|
extern crate regex;
|
2016-03-11 03:48:44 +02:00
|
|
|
extern crate regex_syntax as syntax;
|
2016-02-27 18:07:26 +02:00
|
|
|
extern crate rustc_serialize;
|
2016-09-05 23:36:41 +02:00
|
|
|
extern crate term;
|
2016-08-29 02:18:34 +02:00
|
|
|
extern crate thread_local;
|
2016-08-26 03:44:37 +02:00
|
|
|
extern crate walkdir;
|
2016-09-05 23:36:41 +02:00
|
|
|
#[cfg(windows)]
|
|
|
|
extern crate winapi;
|
2016-02-27 18:07:26 +02:00
|
|
|
|
|
|
|
use std::error::Error;
|
2016-08-29 02:18:34 +02:00
|
|
|
use std::fs::File;
|
2016-09-05 23:36:41 +02:00
|
|
|
use std::io;
|
2016-09-05 16:15:13 +02:00
|
|
|
use std::path::Path;
|
2016-02-27 18:07:26 +02:00
|
|
|
use std::process;
|
|
|
|
use std::result;
|
2016-08-28 07:37:12 +02:00
|
|
|
use std::sync::Arc;
|
|
|
|
use std::thread;
|
2016-02-27 18:07:26 +02:00
|
|
|
|
2016-09-03 05:38:27 +02:00
|
|
|
use crossbeam::sync::chase_lev::{self, Steal, Stealer};
|
2016-09-05 06:52:23 +02:00
|
|
|
use grep::Grep;
|
2016-08-29 02:18:34 +02:00
|
|
|
use parking_lot::Mutex;
|
2016-09-05 16:15:13 +02:00
|
|
|
use walkdir::DirEntry;
|
2016-08-26 03:44:37 +02:00
|
|
|
|
2016-09-05 06:52:23 +02:00
|
|
|
use args::Args;
|
|
|
|
use out::Out;
|
2016-08-28 07:37:12 +02:00
|
|
|
use printer::Printer;
|
2016-09-05 06:52:23 +02:00
|
|
|
use search::InputBuffer;
|
2016-08-27 07:01:06 +02:00
|
|
|
|
2016-08-26 03:44:37 +02:00
|
|
|
macro_rules! errored {
|
|
|
|
($($tt:tt)*) => {
|
|
|
|
return Err(From::from(format!($($tt)*)));
|
|
|
|
}
|
|
|
|
}
|
2016-02-27 18:07:26 +02:00
|
|
|
|
2016-08-26 03:44:37 +02:00
|
|
|
macro_rules! eprintln {
|
|
|
|
($($tt:tt)*) => {{
|
|
|
|
use std::io::Write;
|
|
|
|
let _ = writeln!(&mut ::std::io::stderr(), $($tt)*);
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
|
2016-09-05 06:52:23 +02:00
|
|
|
mod args;
|
2016-08-27 07:01:06 +02:00
|
|
|
mod gitignore;
|
2016-08-26 03:44:37 +02:00
|
|
|
mod glob;
|
2016-08-27 07:01:06 +02:00
|
|
|
mod ignore;
|
2016-09-05 06:52:23 +02:00
|
|
|
mod out;
|
2016-08-28 07:37:12 +02:00
|
|
|
mod printer;
|
|
|
|
mod search;
|
2016-09-05 23:36:41 +02:00
|
|
|
mod sys;
|
2016-09-06 00:22:12 +02:00
|
|
|
mod terminal;
|
2016-09-05 06:52:23 +02:00
|
|
|
mod types;
|
2016-08-28 07:37:12 +02:00
|
|
|
mod walk;
|
2016-03-11 03:48:44 +02:00
|
|
|
|
2016-08-28 07:37:12 +02:00
|
|
|
pub type Result<T> = result::Result<T, Box<Error + Send + Sync>>;
|
|
|
|
|
2016-02-27 18:07:26 +02:00
|
|
|
fn main() {
|
2016-09-05 06:52:23 +02:00
|
|
|
match Args::parse().and_then(run) {
|
|
|
|
Ok(count) if count == 0 => process::exit(1),
|
|
|
|
Ok(count) => process::exit(0),
|
2016-02-27 18:07:26 +02:00
|
|
|
Err(err) => {
|
2016-09-05 23:36:41 +02:00
|
|
|
eprintln!("{}", err);
|
2016-02-27 18:07:26 +02:00
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-05 06:52:23 +02:00
|
|
|
fn run(args: Args) -> Result<u64> {
|
|
|
|
if args.files() {
|
2016-08-29 02:18:34 +02:00
|
|
|
return run_files(args);
|
|
|
|
}
|
2016-09-05 06:52:23 +02:00
|
|
|
if args.type_list() {
|
|
|
|
return run_types(args);
|
|
|
|
}
|
2016-08-29 02:18:34 +02:00
|
|
|
let args = Arc::new(args);
|
2016-09-05 06:52:23 +02:00
|
|
|
let out = Arc::new(Mutex::new(args.out(io::stdout())));
|
2016-08-29 02:18:34 +02:00
|
|
|
let mut workers = vec![];
|
|
|
|
|
2016-09-05 06:52:23 +02:00
|
|
|
let mut workq = {
|
|
|
|
let (workq, stealer) = chase_lev::deque();
|
|
|
|
for _ in 0..args.threads() {
|
2016-08-29 02:18:34 +02:00
|
|
|
let worker = Worker {
|
|
|
|
args: args.clone(),
|
2016-09-04 03:48:23 +02:00
|
|
|
out: out.clone(),
|
2016-09-03 05:38:27 +02:00
|
|
|
chan_work: stealer.clone(),
|
2016-09-05 06:52:23 +02:00
|
|
|
inpbuf: args.input_buffer(),
|
2016-08-29 02:18:34 +02:00
|
|
|
outbuf: Some(vec![]),
|
2016-09-05 06:52:23 +02:00
|
|
|
grep: try!(args.grep()),
|
2016-09-05 16:15:13 +02:00
|
|
|
match_count: 0,
|
2016-08-29 02:18:34 +02:00
|
|
|
};
|
|
|
|
workers.push(thread::spawn(move || worker.run()));
|
2016-08-28 07:37:12 +02:00
|
|
|
}
|
2016-09-05 06:52:23 +02:00
|
|
|
workq
|
2016-08-29 02:18:34 +02:00
|
|
|
};
|
2016-09-05 06:52:23 +02:00
|
|
|
for p in args.paths() {
|
|
|
|
if p == Path::new("-") {
|
|
|
|
workq.push(Work::Stdin)
|
|
|
|
} else {
|
2016-09-05 23:36:41 +02:00
|
|
|
for ent in try!(args.walker(p)) {
|
2016-09-05 16:15:13 +02:00
|
|
|
workq.push(Work::File(ent));
|
2016-09-05 06:52:23 +02:00
|
|
|
}
|
2016-08-05 06:10:58 +02:00
|
|
|
}
|
2016-03-11 03:48:44 +02:00
|
|
|
}
|
2016-08-29 02:18:34 +02:00
|
|
|
for _ in 0..workers.len() {
|
2016-09-05 06:52:23 +02:00
|
|
|
workq.push(Work::Quit);
|
2016-08-28 07:37:12 +02:00
|
|
|
}
|
2016-09-05 06:52:23 +02:00
|
|
|
let mut match_count = 0;
|
2016-08-29 02:18:34 +02:00
|
|
|
for worker in workers {
|
2016-09-05 06:52:23 +02:00
|
|
|
match_count += worker.join().unwrap();
|
2016-08-29 02:18:34 +02:00
|
|
|
}
|
2016-09-05 06:52:23 +02:00
|
|
|
Ok(match_count)
|
2016-08-29 02:18:34 +02:00
|
|
|
}
|
2016-08-26 03:44:37 +02:00
|
|
|
|
2016-09-05 06:52:23 +02:00
|
|
|
fn run_files(args: Args) -> Result<u64> {
|
2016-09-05 23:36:41 +02:00
|
|
|
let mut printer = args.printer(io::BufWriter::new(io::stdout()));
|
2016-09-05 06:52:23 +02:00
|
|
|
let mut file_count = 0;
|
|
|
|
for p in args.paths() {
|
|
|
|
if p == Path::new("-") {
|
|
|
|
printer.path(&Path::new("<stdin>"));
|
|
|
|
file_count += 1;
|
2016-09-04 03:48:23 +02:00
|
|
|
} else {
|
2016-09-05 23:36:41 +02:00
|
|
|
for ent in try!(args.walker(p)) {
|
2016-09-05 16:15:13 +02:00
|
|
|
printer.path(ent.path());
|
2016-09-05 06:52:23 +02:00
|
|
|
file_count += 1;
|
|
|
|
}
|
2016-09-04 03:48:23 +02:00
|
|
|
}
|
|
|
|
}
|
2016-09-05 06:52:23 +02:00
|
|
|
Ok(file_count)
|
|
|
|
}
|
2016-09-04 03:48:23 +02:00
|
|
|
|
2016-09-05 06:52:23 +02:00
|
|
|
fn run_types(args: Args) -> Result<u64> {
|
2016-09-05 23:36:41 +02:00
|
|
|
let mut printer = args.printer(io::BufWriter::new(io::stdout()));
|
2016-09-05 06:52:23 +02:00
|
|
|
let mut ty_count = 0;
|
|
|
|
for def in args.type_defs() {
|
|
|
|
printer.type_def(def);
|
|
|
|
ty_count += 1;
|
2016-09-04 03:48:23 +02:00
|
|
|
}
|
2016-09-05 06:52:23 +02:00
|
|
|
Ok(ty_count)
|
2016-08-27 07:01:06 +02:00
|
|
|
}
|
|
|
|
|
2016-09-05 06:52:23 +02:00
|
|
|
enum Work {
|
|
|
|
Stdin,
|
2016-09-05 16:15:13 +02:00
|
|
|
File(DirEntry),
|
2016-08-29 02:18:34 +02:00
|
|
|
Quit,
|
2016-08-28 07:37:12 +02:00
|
|
|
}
|
2016-08-27 07:01:06 +02:00
|
|
|
|
2016-09-05 16:15:13 +02:00
|
|
|
enum WorkReady {
|
|
|
|
Stdin,
|
|
|
|
File(DirEntry, File),
|
|
|
|
}
|
|
|
|
|
2016-08-28 07:37:12 +02:00
|
|
|
struct Worker {
|
|
|
|
args: Arc<Args>,
|
2016-09-04 03:48:23 +02:00
|
|
|
out: Arc<Mutex<Out<io::Stdout>>>,
|
2016-09-05 06:52:23 +02:00
|
|
|
chan_work: Stealer<Work>,
|
2016-08-29 02:18:34 +02:00
|
|
|
inpbuf: InputBuffer,
|
|
|
|
outbuf: Option<Vec<u8>>,
|
2016-08-28 07:37:12 +02:00
|
|
|
grep: Grep,
|
2016-09-05 16:15:13 +02:00
|
|
|
match_count: u64,
|
2016-08-28 07:37:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Worker {
|
2016-09-05 06:52:23 +02:00
|
|
|
fn run(mut self) -> u64 {
|
2016-09-05 16:15:13 +02:00
|
|
|
self.match_count = 0;
|
2016-08-29 02:18:34 +02:00
|
|
|
loop {
|
2016-09-05 16:15:13 +02:00
|
|
|
let work = match self.chan_work.steal() {
|
2016-09-03 05:38:27 +02:00
|
|
|
Steal::Empty | Steal::Abort => continue,
|
2016-09-05 06:52:23 +02:00
|
|
|
Steal::Data(Work::Quit) => break,
|
2016-09-05 16:15:13 +02:00
|
|
|
Steal::Data(Work::Stdin) => WorkReady::Stdin,
|
|
|
|
Steal::Data(Work::File(ent)) => {
|
|
|
|
match File::open(ent.path()) {
|
|
|
|
Ok(file) => WorkReady::File(ent, file),
|
2016-09-05 06:52:23 +02:00
|
|
|
Err(err) => {
|
2016-09-05 16:15:13 +02:00
|
|
|
eprintln!("{}: {}", ent.path().display(), err);
|
2016-09-05 06:52:23 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-08-29 02:18:34 +02:00
|
|
|
};
|
|
|
|
let mut outbuf = self.outbuf.take().unwrap();
|
|
|
|
outbuf.clear();
|
|
|
|
let mut printer = self.args.printer(outbuf);
|
2016-09-05 16:15:13 +02:00
|
|
|
self.do_work(&mut printer, work);
|
2016-08-29 02:18:34 +02:00
|
|
|
let outbuf = printer.into_inner();
|
|
|
|
if !outbuf.is_empty() {
|
2016-09-04 03:48:23 +02:00
|
|
|
let mut out = self.out.lock();
|
2016-09-05 06:52:23 +02:00
|
|
|
out.write(&outbuf);
|
2016-08-29 02:18:34 +02:00
|
|
|
}
|
|
|
|
self.outbuf = Some(outbuf);
|
2016-08-28 07:37:12 +02:00
|
|
|
}
|
2016-09-05 16:15:13 +02:00
|
|
|
self.match_count
|
|
|
|
}
|
|
|
|
|
2016-09-05 23:36:41 +02:00
|
|
|
fn do_work<W: Send + io::Write>(
|
2016-09-05 16:15:13 +02:00
|
|
|
&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);
|
|
|
|
}
|
|
|
|
}
|
2016-09-05 06:52:23 +02:00
|
|
|
}
|
|
|
|
|
2016-09-05 23:36:41 +02:00
|
|
|
fn search<R: io::Read, W: Send + io::Write>(
|
2016-09-05 06:52:23 +02:00
|
|
|
&mut self,
|
|
|
|
printer: &mut Printer<W>,
|
|
|
|
path: &Path,
|
|
|
|
rdr: R,
|
|
|
|
) -> Result<u64> {
|
|
|
|
self.args.searcher(
|
|
|
|
&mut self.inpbuf,
|
|
|
|
printer,
|
|
|
|
&self.grep,
|
|
|
|
path,
|
|
|
|
rdr,
|
|
|
|
).run().map_err(From::from)
|
2016-09-04 03:48:23 +02:00
|
|
|
}
|
|
|
|
}
|