diff --git a/Cargo.lock b/Cargo.lock index b3aab4f..bc75ae2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,6 +77,7 @@ dependencies = [ "cargo_metadata", "cargo_toml", "grep", + "ignore", "log", "pretty_env_logger", "rayon", @@ -302,6 +303,23 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "ignore" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +dependencies = [ + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + [[package]] name = "indexmap" version = "2.2.6" @@ -329,6 +347,12 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.153" @@ -356,6 +380,12 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "pretty_env_logger" version = "0.5.0" @@ -537,6 +567,16 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "toml" version = "0.8.12" diff --git a/Cargo.toml b/Cargo.toml index 7d96bea..9c3b9db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ argh = "0.1.9" cargo_metadata = "0.18.0" cargo_toml = "0.19.1" grep = "0.3.1" +ignore = "0.4.20" log = "0.4.16" pretty_env_logger = "0.5.0" rayon = "1.5.2" diff --git a/src/main.rs b/src/main.rs index 3cdb362..eb8352b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,6 @@ use rayon::prelude::*; use std::path::Path; use std::str::FromStr; use std::{fs, path::PathBuf}; -use walkdir::WalkDir; #[derive(Clone, Copy)] pub(crate) enum UseCargoMetadata { @@ -62,6 +61,10 @@ struct MacheteArgs { #[argh(switch)] fix: bool, + /// respect ignore files (.gitignore, .ignore, etc.) when searching for files. + #[argh(switch)] + ignore: bool, + /// print version. #[argh(switch)] version: bool, @@ -71,21 +74,26 @@ struct MacheteArgs { paths: Vec, } -fn collect_paths(path: &Path, skip_target_dir: bool) -> Result, walkdir::Error> { +struct CollectPathOptions { + skip_target_dir: bool, + respect_ignore_files: bool, +} + +fn collect_paths(path: &Path, options: CollectPathOptions) -> Result, ignore::Error> { // Find directory entries. - let walker = WalkDir::new(path).into_iter(); + let mut builder = ignore::WalkBuilder::new(path); - let manifest_path_entries = if skip_target_dir { - walker - .filter_entry(|entry| !entry.path().ends_with("target")) - .collect() - } else { - walker.collect::>() - }; + builder.standard_filters(options.respect_ignore_files); + + if options.skip_target_dir { + builder.filter_entry(|entry| !entry.path().ends_with("target")); + } + + let walker = builder.build(); // Keep only errors and `Cargo.toml` files (filter), then map correct paths into owned // `PathBuf`. - manifest_path_entries + walker .into_iter() .filter(|entry| match entry { Ok(entry) => entry.file_name() == "Cargo.toml", @@ -142,7 +150,13 @@ fn run_machete() -> anyhow::Result { let mut walkdir_errors = Vec::new(); for path in args.paths { - let manifest_path_entries = match collect_paths(&path, args.skip_target_dir) { + let manifest_path_entries = match collect_paths( + &path, + CollectPathOptions { + skip_target_dir: args.skip_target_dir, + respect_ignore_files: args.ignore, + }, + ) { Ok(entries) => entries, Err(err) => { walkdir_errors.push(err); @@ -290,13 +304,28 @@ const TOP_LEVEL: &str = concat!(env!("CARGO_MANIFEST_DIR")); fn test_ignore_target() { let entries = collect_paths( &PathBuf::from(TOP_LEVEL).join("./integration-tests/with-target/"), - true, + CollectPathOptions { + skip_target_dir: true, + respect_ignore_files: false, + }, + ); + assert!(entries.unwrap().is_empty()); + + let entries = collect_paths( + &PathBuf::from(TOP_LEVEL).join("./integration-tests/with-target/"), + CollectPathOptions { + skip_target_dir: false, + respect_ignore_files: true, + }, ); assert!(entries.unwrap().is_empty()); let entries = collect_paths( &PathBuf::from(TOP_LEVEL).join("./integration-tests/with-target/"), - false, + CollectPathOptions { + skip_target_dir: false, + respect_ignore_files: false, + }, ); assert!(!entries.unwrap().is_empty()); }