diff --git a/Cargo.lock b/Cargo.lock index 787567b..fe10e26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,12 +22,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "clap" version = "4.0.15" @@ -65,6 +77,79 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "crossbeam" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" +dependencies = [ + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + [[package]] name = "eyre" version = "0.6.8" @@ -96,6 +181,16 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +[[package]] +name = "jwalk" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172752e853a067cbce46427de8470ddf308af7fd8ceaf9b682ef31a5021b6bb9" +dependencies = [ + "crossbeam", + "rayon", +] + [[package]] name = "libc" version = "0.2.135" @@ -108,6 +203,25 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.15.0" @@ -162,6 +276,30 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rayon" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "regex" version = "1.6.0" @@ -188,6 +326,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "strsim" version = "0.10.0" @@ -226,6 +370,7 @@ version = "0.1.0" dependencies = [ "clap", "eyre", + "jwalk", "regex", "walkdir", ] diff --git a/Cargo.toml b/Cargo.toml index 9ce16ae..1c0bc2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,7 @@ edition = "2021" [dependencies] clap = { version = "4.0.15", features = ["derive"] } eyre = "0.6.8" +jwalk = "0.6.0" regex = "1.6.0" walkdir = "2.3.2" + diff --git a/src/main.rs b/src/main.rs index ec09ace..9cc4a74 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use clap::Parser; #[derive(clap::Parser, Clone)] struct Args { #[arg(long)] - root_dir: String, + root_dir: Vec, #[arg(long)] pattern: Option, @@ -18,26 +18,38 @@ fn main() -> eyre::Result<()> { let args = Args::parse(); // Choose dir - let root_dir = args.root_dir; - let mut projects: Vec = vec![]; - let pattern = regex::Regex::new(match args.pattern { - Some(p) => Box::leak(p.into_boxed_str()), - None => ".*\\.git$", - })?; + let pattern = Box::leak(args.pattern.unwrap_or(".git".into()).into_boxed_str()); // Look for dir .git if found add path to map - for entry in walkdir::WalkDir::new(root_dir) - .follow_links(true) - .into_iter() - .filter_map(|e| e.ok()) - { - if let Ok(metadata) = entry.metadata() { - if metadata.is_dir() { - let name = entry.file_name().to_string_lossy(); - if pattern.is_match(&name) { - projects.push(entry.into_path()) + for root_dir in args.root_dir { + println!("searching: {}", root_dir); + for entry in jwalk::WalkDir::new(root_dir) + .skip_hidden(false) + .follow_links(false) + .process_read_dir(|_, _, _, children| { + children.retain(|dir_entry_result| { + dir_entry_result + .as_ref() + .map(|dir_entry| { + let metadata = match dir_entry.metadata() { + Ok(m) => m, + Err(_) => return false, + }; + return metadata.is_dir(); + }) + .unwrap_or(false) + }); + }) + { + match entry { + Err(_) => {} + Ok(entry) => { + let name = entry.file_name().to_string_lossy(); + if name.ends_with(&*pattern) { + projects.push(entry.path()) + } } } }