diff --git a/Cargo.lock b/Cargo.lock index 05ee017..6058b96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,30 +3,53 @@ version = 3 [[package]] -name = "ansi_term" -version = "0.11.0" +name = "anstream" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", ] [[package]] -name = "atty" -version = "0.2.14" +name = "anstyle" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ - "hermit-abi", - "libc", - "winapi", + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys", ] [[package]] -name = "bitflags" -version = "1.2.1" +name = "anstyle-wincon" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] [[package]] name = "blake2" @@ -41,19 +64,37 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ - "ansi_term", - "atty", - "bitflags", + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", - "vec_map", ] +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -115,19 +156,10 @@ dependencies = [ ] [[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "libc" -version = "0.2.98" +name = "is_terminal_polyfill" +version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" [[package]] name = "opaque-debug" @@ -197,9 +229,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" @@ -218,15 +250,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.26" @@ -253,12 +276,6 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" -[[package]] -name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - [[package]] name = "unicode-xid" version = "0.2.2" @@ -266,10 +283,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] -name = "vec_map" -version = "0.8.2" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "version_check" @@ -317,3 +334,76 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/Cargo.toml b/Cargo.toml index 96c5522..c1d8f66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" [dependencies] blake2 = "0.9.1" -clap = "2.33.0" +clap = { version = "4.5.4", features = ["cargo"] } digest = "0.9.0" generic-array = "0.14.4" rayon = "1.10.0" diff --git a/src/main.rs b/src/main.rs index 23c6ecf..ed80ebd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,15 @@ use blake2::Blake2b; -use clap::{value_t, App, Arg, OsValues}; +//use clap::{value_t, App, Arg, OsValues}; +use clap::{arg, command, value_parser, Arg}; use digest::Digest; use generic_array::{ArrayLength, GenericArray}; use rayon::prelude::*; use std::collections::HashMap; + use std::fs::File; use std::io::{self, Write}; use std::path::{Path, PathBuf}; +use std::str::FromStr; use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use std::sync::Arc; use std::vec::Vec; @@ -110,7 +113,11 @@ where Ok(r) } -fn run(dirs: OsValues, options: &Options) -> Result<(), Error> { +fn run(dirs: I, options: &Options) -> Result<(), Error> + where + I: IntoIterator, + J: AsRef, +{ let num_hashes = Arc::new(AtomicUsize::new(0)); let num_duplicates = Arc::new(AtomicUsize::new(0)); let num_groups = Arc::new(AtomicUsize::new(0)); @@ -191,70 +198,68 @@ fn run(dirs: OsValues, options: &Options) -> Result<(), Error> { } fn main() { - let matches = App::new("rdupes") - .version(env!("CARGO_PKG_VERSION")) + let matches = command!() .arg( - Arg::with_name("recursive") - .short("r") - .takes_value(false) - .help("recurse into directories"), + arg!(recursive: -r "recurse into directories") + //.action(ArgAction::SetTrue) + // Arg::new("recursive") + // .short('r') + // .action(ArgAction::SetTrue) + // .help("recurse into directories"), ) .arg( - Arg::with_name("follow") - .short("f") - .takes_value(false) - .help("follow symlinks"), + arg!(follow: -f --follow "follow symlinks") + //.action(ArgAction::SetTrue) + // Arg::new("follow") + // .short('f') + // .action(ArgAction::SetTrue) + // .help("follow symlinks"), ) .arg( - Arg::with_name("min-size") - .long("min-size") - .takes_value(true) - .help("minimum size of files (in bytes) to find duplicates for"), + arg!(--"min-size" "minimum size of files (in bytes) to find duplicates for") + .value_parser(value_parser!(u64)) + // Arg::new("min-size") + // .long("min-size") + // .num_args(1) + // .help("minimum size of files (in bytes) to find duplicates for"), ) .arg( - Arg::with_name("max-depth") - .long("max-depth") - .takes_value(true) - .help("maximum depth to recurse (0 is no recursion). implies -r."), + arg!(--"max-depth" "maximum depth to recurse (0 is no recursion). implies -r.") + .value_parser(value_parser!(u64)) + // Arg::new("max-depth") + // .long("max-depth") + // .num_args(1) + // .help("maximum depth to recurse (0 is no recursion). implies -r."), ) .arg( - Arg::with_name("sort-opts") - .long("sort-by") - .takes_value(true) - .help("properties to sort by, comma-separated. depth,mtime,path"), + arg!(--"sort-by" "properties to sort by, comma-separated. depth,mtime,path") + .value_parser(SortKeys::from_str) + // Arg::new("sort-opts") + // .long("sort-by") + // .num_args(1) + // .help("properties to sort by, comma-separated. depth,mtime,path"), ) .arg( - Arg::with_name("prefer-within") - .long("prefer-within") - .takes_value(true) - .help("prefer files within this path"), + arg!(--"prefer-within" "prefer files within this path") + .value_parser(value_parser!(PathBuf)) + // Arg::new("prefer-within") + // .long("prefer-within") + // .takes_value(true) + // .help("prefer files within this path"), ) - .arg(Arg::with_name("directory").required(true).multiple(true)) + .arg(Arg::new("directory").required(true).num_args(1..).value_parser(value_parser!(PathBuf))) .get_matches(); - let dirs = matches.values_of_os("directory").unwrap(); - let recurse = matches.is_present("recursive") || matches.is_present("max-depth"); - let follow_symlinks = matches.is_present("follow"); - let min_size = if matches.is_present("min-size") { - value_t!(matches.value_of("min-size"), u64).unwrap_or_else(|e| e.exit()) - } else { - 1 - }; - let max_depth = if matches.is_present("max-depth") { - Some(value_t!(matches.value_of("max-depth"), u64).unwrap_or_else(|e| e.exit())) - } else { - None - }; - let prefer_location = if matches.is_present("prefer-within") { - let p = value_t!(matches, "prefer-within", PathBuf).unwrap_or_else(|e| e.exit()); + let dirs: Vec<&PathBuf> = matches.get_many("directory").unwrap().collect(); + let recurse = matches.get_flag("recursive") || matches.contains_id("max-depth"); + let follow_symlinks = matches.get_flag("follow"); + let min_size: u64 = matches.get_one("min-size").copied().unwrap_or(1); + let max_depth = matches.get_one::("max-depth").copied(); + let prefer_location = if let Some(p) = matches.get_one::("prefer-within") { Some(p.canonicalize().expect("could not canonicalize path")) } else { None }; - let sort_by = if matches.is_present("sort-opts") { - value_t!(matches, "sort-opts", SortKeys).unwrap_or_else(|e| e.exit()) - } else { - SortKeys::default() - }; + let sort_by = matches.get_one::("sort-opts").cloned().unwrap_or_else(|| SortKeys::default()); let sort_options = SortOptions { prefer_location, sort_by,