From 34aa508e5fb656d970319ba4775da4a7e3dbed52 Mon Sep 17 00:00:00 2001 From: "andy.boot" Date: Wed, 3 Jan 2024 23:07:06 +0000 Subject: [PATCH] feat: better error messages Provide "No such file or directory" error if file is not found. Should reduce confusion from the generic other error --- src/dir_walker.rs | 113 +++++++++++++++++++++++++++----------------- src/main.rs | 8 ++++ src/progress.rs | 2 + tests/test_flags.rs | 2 +- 4 files changed, 80 insertions(+), 45 deletions(-) diff --git a/src/dir_walker.rs b/src/dir_walker.rs index 2863751a..3541cc5b 100644 --- a/src/dir_walker.rs +++ b/src/dir_walker.rs @@ -126,55 +126,80 @@ fn ignore_file(entry: &DirEntry, walk_data: &WalkData) -> bool { fn walk(dir: PathBuf, walk_data: &WalkData, depth: usize) -> Option { let prog_data = &walk_data.progress_data; - let mut children = vec![]; - - if let Ok(entries) = fs::read_dir(&dir) { - children = entries - .into_iter() - .par_bridge() - .filter_map(|entry| { - if let Ok(ref entry) = entry { - // uncommenting the below line gives simpler code but - // rayon doesn't parallelize as well giving a 3X performance drop - // hence we unravel the recursion a bit - - // return walk(entry.path(), walk_data, depth) - - if !ignore_file(entry, walk_data) { - if let Ok(data) = entry.file_type() { - if data.is_dir() || (walk_data.follow_links && data.is_symlink()) { - return walk(entry.path(), walk_data, depth + 1); - } - let node = build_node( - entry.path(), - vec![], - walk_data.filter_regex, - walk_data.invert_filter_regex, - walk_data.use_apparent_size, - data.is_symlink(), - data.is_file(), - walk_data.by_filecount, - depth, - ); - - prog_data.num_files.fetch_add(1, ORDERING); - if let Some(ref file) = node { - prog_data.total_file_size.fetch_add(file.size, ORDERING); + let children = if dir.is_dir() { + let read_dir = fs::read_dir(&dir); + match read_dir { + Ok(entries) => { + entries + .into_iter() + .par_bridge() + .filter_map(|entry| { + if let Ok(ref entry) = entry { + // uncommenting the below line gives simpler code but + // rayon doesn't parallelize as well giving a 3X performance drop + // hence we unravel the recursion a bit + + // return walk(entry.path(), walk_data, depth) + + if !ignore_file(entry, walk_data) { + if let Ok(data) = entry.file_type() { + if data.is_dir() + || (walk_data.follow_links && data.is_symlink()) + { + return walk(entry.path(), walk_data, depth + 1); + } + + let node = build_node( + entry.path(), + vec![], + walk_data.filter_regex, + walk_data.invert_filter_regex, + walk_data.use_apparent_size, + data.is_symlink(), + data.is_file(), + walk_data.by_filecount, + depth, + ); + + prog_data.num_files.fetch_add(1, ORDERING); + if let Some(ref file) = node { + prog_data.total_file_size.fetch_add(file.size, ORDERING); + } + + return node; + } } - - return node; + } else { + prog_data.no_permissions.store(true, ORDERING) } + None + }) + .collect() + } + Err(failed) => { + match failed.kind() { + std::io::ErrorKind::PermissionDenied => { + prog_data.no_permissions.store(true, ORDERING) + } + std::io::ErrorKind::NotFound => { + // TODO: consider turning this in to a array of the files that were not found + prog_data.no_file.store(true, ORDERING) + } + _ => { + println!("{:?}", failed); + prog_data.unknown_error.store(true, ORDERING) } - } else { - prog_data.no_permissions.store(true, ORDERING) } - None - }) - .collect(); - } else if !dir.is_file() { - walk_data.progress_data.no_permissions.store(true, ORDERING) - } + vec![] + } + } + } else { + if !dir.is_file() { + prog_data.no_file.store(true, ORDERING) + } + vec![] + }; build_node( dir, children, diff --git a/src/main.rs b/src/main.rs index 52c0a0cb..496ba02d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -217,11 +217,19 @@ fn main() { }; let failed_permissions = indicator.data.no_permissions.load(ORDERING); + let no_file = indicator.data.no_file.load(ORDERING); + let unknown_error = indicator.data.unknown_error.load(ORDERING); indicator.stop(); // Must have stopped indicator before we print to stderr + if no_file { + eprintln!("No such file or directory"); + } if failed_permissions { eprintln!("Did not have permissions for all directories"); } + if unknown_error { + eprintln!("Unknown Error reading files"); + } if let Some(root_node) = tree { let idd = InitialDisplayData { diff --git a/src/progress.rs b/src/progress.rs index 15f77224..4f3b2ba8 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -56,6 +56,8 @@ pub struct PAtomicInfo { pub state: AtomicU8, pub current_path: ThreadStringWrapper, pub no_permissions: AtomicBool, + pub no_file: AtomicBool, + pub unknown_error: AtomicBool, } impl PAtomicInfo { diff --git a/tests/test_flags.rs b/tests/test_flags.rs index 199ac0e9..3251692a 100644 --- a/tests/test_flags.rs +++ b/tests/test_flags.rs @@ -92,7 +92,7 @@ pub fn test_with_bad_param() { let mut cmd = Command::cargo_bin("dust").unwrap(); let result = cmd.arg("bad_place").unwrap(); let stderr = str::from_utf8(&result.stderr).unwrap(); - assert!(stderr.contains("Did not have permissions for all directories")); + assert!(stderr.contains("No such file or directory")); } #[test]