From 7d0eb75e3c1c3fb60cb873f772c13bf35ff14f64 Mon Sep 17 00:00:00 2001 From: Dinko Korunic Date: Thu, 14 Nov 2024 16:46:52 +0100 Subject: [PATCH] Update deps. Add path argument normalization and directory check. --- Cargo.toml | 7 ++++--- src/args.rs | 43 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 81d4e05..d35b9c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "findlargedir" -version = "0.8.0" +version = "0.9.0" authors = ["Dinko Korunic "] categories = ["command-line-utilities"] description = "find all blackhole directories with a huge amount of filesystem entries in a flat structure" @@ -15,17 +15,18 @@ rayon = "1.10.0" tempfile = "3.14.0" anyhow = "1.0.93" human_format = "1.1.0" -clap = { version = "4.5.20", features = ["derive", "unicode", "wrap_help"] } +clap = { version = "4.5.21", features = ["derive", "unicode", "wrap_help"] } rm_rf = "0.6.2" ansi_term = "0.12.1" fs-err = "3.0.0" -indicatif = { version = "0.17.8", features = ["rayon"] } +indicatif = { version = "0.17.9", features = ["rayon"] } cfg-if = "1.0" fdlimit = "0.3.0" ahash = "0.8.11" anstyle = "1.0.10" signal-hook = "0.3.17" ignore = "0.4.23" +normpath = "1.3.0" [target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dependencies] tikv-jemallocator = "0.6.0" diff --git a/src/args.rs b/src/args.rs index 06c1569..e2cbc21 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::thread; use anstyle::AnsiColor; @@ -6,6 +6,7 @@ use anyhow::{anyhow, Error}; use clap::builder::{styling::Styles, ValueParser}; use clap::Parser; use clap::ValueHint; +use normpath::PathExt; const STYLES: Styles = Styles::styled() .header(AnsiColor::Yellow.on_default()) @@ -41,7 +42,8 @@ pub struct Args { pub blacklist_threshold: u64, /// Number of threads to use when calibrating and scanning - #[clap(short = 'x', long, value_parser = ValueParser::new(parse_threads), default_value_t = thread::available_parallelism().map(| n | n.get()).unwrap_or(2))] + #[clap(short = 'x', long, value_parser = ValueParser::new(parse_threads), default_value_t = thread::available_parallelism().map(| n | n.get()).unwrap_or(2) + )] pub threads: usize, /// Seconds between status updates, set to 0 to disable @@ -61,7 +63,8 @@ pub struct Args { pub skip_path: Vec, /// Paths to check for large directories - #[clap(required = true, value_parser, value_hint = ValueHint::AnyPath)] + #[clap(required = true, value_parser = ValueParser::new(parse_paths), value_hint = ValueHint::AnyPath + )] pub path: Vec, } @@ -77,3 +80,37 @@ fn parse_threads(x: &str) -> Result { Err(e) => Err(Error::from(e)), } } + +/// Parses a string into a `PathBuf`, checking if the path is a directory and exists. +/// +/// # Arguments +/// +/// * `x` - A string slice to be parsed into a `PathBuf`. +/// +/// # Returns +/// +/// * `Result` - An `Ok` variant containing a normalized `PathBuf` if the path is an existing directory, +/// or an `Err` variant with an error message if the path does not exist or is not a directory. +fn parse_paths(x: &str) -> Result { + let p = Path::new(x); + + if directory_exists(p) { + Ok(p.normalize()?.into_path_buf()) + } else { + Err(anyhow!("'{}' is not an existing directory", x)) + } +} + +/// Checks if the given path is a directory and exists. +/// +/// # Arguments +/// +/// * `x` - A reference to the path to check. +/// +/// # Returns +/// +/// * `bool` - `true` if the path is an existing directory, `false` otherwise. +#[inline] +fn directory_exists(x: &Path) -> bool { + x.is_dir() && x.normalize().is_ok() +}