diff options
author | wngr <oliver@wngr.de> | 2019-09-11 20:36:12 +0200 |
---|---|---|
committer | David Peter <sharkdp@users.noreply.github.com> | 2019-09-20 23:28:01 +0200 |
commit | da731abb2b42b05e540f90d3b403c51b955b75d2 (patch) | |
tree | 29b1acf8c133f07f965d4fa8bae4f1e70acaefa6 | |
parent | a35d58d543e3e836aabdd748cc76a3290e2088e1 (diff) |
Add verbose flag and hide error messages behind it. Add additional output warning, if there were I/O errors while walking the tree.
-rw-r--r-- | src/main.rs | 42 | ||||
-rw-r--r-- | src/walk/mod.rs | 34 |
2 files changed, 55 insertions, 21 deletions
diff --git a/src/main.rs b/src/main.rs index 9dc48d2..48badfd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,12 +14,39 @@ use humansize::{file_size_opts, FileSize}; use walk::Walk; -fn print_result(size: u64) { +fn print_result(size: u64, errors: &[walk::Err], verbose: bool) { + let tainted = errors.iter().any(|x| { + if let walk::Err::NoMetadataForPath(_) = x { + true + } else { + false + } + }); println!( "{} ({} bytes)", size.file_size(file_size_opts::DECIMAL).unwrap(), size ); + if verbose { + for err in errors { + match err { + walk::Err::NoMetadataForPath(path) => { + eprintln!( + "diskus: could not retrieve metadata for path '{}'", + path.to_string_lossy() + ); + } + walk::Err::CouldNotReadDir(path) => { + eprintln!( + "diskus: could not read contents of directory '{}'", + path.to_string_lossy() + ); + } + } + } + } else if tainted { + println!("Warning, results may be tainted. Try running with --verbose."); + } } fn main() { @@ -42,6 +69,13 @@ fn main() { .value_name("N") .takes_value(true) .help("Set the number of threads (default: 3 x num cores)"), + ) + .arg( + Arg::with_name("verbose") + .long("verbose") + .short("v") + .takes_value(false) + .help("Emits verbose output"), ); let matches = app.get_matches(); @@ -61,7 +95,9 @@ fn main() { .map(|paths| paths.map(PathBuf::from).collect()) .unwrap_or_else(|| vec![PathBuf::from(".")]); + let verbose = matches.is_present("verbose"); + let walk = Walk::new(&paths, num_threads); - let size = walk.run(); - print_result(size); + let (size, errors) = walk.run(); + print_result(size, &errors, verbose); } diff --git a/src/walk/mod.rs b/src/walk/mod.rs index 7fc3256..87e4bcb 100644 --- a/src/walk/mod.rs +++ b/src/walk/mod.rs @@ -21,11 +21,14 @@ mod unix; #[cfg(not(target_os = "windows"))] pub use self::unix::*; -enum Message { - SizeEntry(Option<UniqueID>, u64), +pub enum Err { NoMetadataForPath(PathBuf), CouldNotReadDir(PathBuf), } +enum Message { + SizeEntry(Option<UniqueID>, u64), + Error { err: Err }, +} fn walk(tx: channel::Sender<Message>, entries: &[PathBuf]) { entries.into_par_iter().for_each_with(tx, |tx_ref, entry| { @@ -48,7 +51,9 @@ fn walk(tx: channel::Sender<Message>, entries: &[PathBuf]) { } Err(_) => { tx_ref - .send(Message::CouldNotReadDir(entry.clone())) + .send(Message::Error { + err: Err::CouldNotReadDir(entry.clone()), + }) .unwrap(); } } @@ -57,7 +62,9 @@ fn walk(tx: channel::Sender<Message>, entries: &[PathBuf]) { }; } else { tx_ref - .send(Message::NoMetadataForPath(entry.clone())) + .send(Message::Error { + err: Err::NoMetadataForPath(entry.clone()), + }) .unwrap(); }; }); @@ -76,12 +83,13 @@ impl<'a> Walk<'a> { } } - pub fn run(&self) -> u64 { + pub fn run(&self) -> (u64, Vec<Err>) { let (tx, rx) = channel::unbounded(); let receiver_thread = thread::spawn(move || { let mut total = 0; let mut ids = HashSet::new(); + let mut error_messages: Vec<Err> = Vec::new(); for msg in rx { match msg { Message::SizeEntry(unique_id, size) => { @@ -94,22 +102,12 @@ impl<'a> Walk<'a> { total += size; } } - Message::NoMetadataForPath(path) => { - eprintln!( - "diskus: could not retrieve metadata for path '{}'", - path.to_string_lossy() - ); - } - Message::CouldNotReadDir(path) => { - eprintln!( - "diskus: could not read contents of directory '{}'", - path.to_string_lossy() - ); + Message::Error { err } => { + error_messages.push(err); } } } - - total + (total, error_messages) }); let pool = rayon::ThreadPoolBuilder::new() |