Skip to content

Commit

Permalink
Add ignore flag
Browse files Browse the repository at this point in the history
Add the ignore flag which make cargo-machete respect .ignore and
.gitignore files when searching for files.
  • Loading branch information
mickvangelderen committed Nov 5, 2023
1 parent 881ee93 commit 04063c9
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 19 deletions.
19 changes: 18 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ argh = "0.1.9"
cargo_metadata = "0.18.0"
cargo_toml = "0.16.2"
grep = "0.2.8"
ignore = "0.4.20"
log = "0.4.16"
pretty_env_logger = "0.5.0"
rayon = "1.5.2"
serde = "1.0.136"
toml_edit = "0.20.0"
walkdir = "2.3.2"

# Uncomment this for profiling.
#[profile.release]
Expand Down
44 changes: 32 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand All @@ -71,21 +74,28 @@ struct MacheteArgs {
paths: Vec<PathBuf>,
}

fn collect_paths(path: &Path, skip_target_dir: bool) -> Result<Vec<PathBuf>, walkdir::Error> {
fn collect_paths(
path: &Path,
skip_target_dir: bool,
respect_ignore_files: bool,
) -> Result<Vec<PathBuf>, 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::<Vec<_>>()
};
builder.git_exclude(respect_ignore_files);
builder.git_global(respect_ignore_files);
builder.git_ignore(respect_ignore_files);
builder.ignore(respect_ignore_files);

if 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",
Expand Down Expand Up @@ -142,7 +152,7 @@ fn run_machete() -> anyhow::Result<bool> {
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, args.skip_target_dir, args.ignore) {
Ok(entries) => entries,
Err(err) => {
walkdir_errors.push(err);
Expand Down Expand Up @@ -288,15 +298,25 @@ const TOP_LEVEL: &str = concat!(env!("CARGO_MANIFEST_DIR"));

#[test]
fn test_ignore_target() {
pretty_env_logger::init();
let entries = collect_paths(
&PathBuf::from(TOP_LEVEL).join("./integration-tests/with-target/"),
true,
false,
);
assert!(entries.unwrap().is_empty());

let entries = collect_paths(
&PathBuf::from(TOP_LEVEL).join("./integration-tests/with-target/"),
false,
true,
);
assert!(entries.unwrap().is_empty());

let entries = collect_paths(
&PathBuf::from(TOP_LEVEL).join("./integration-tests/with-target/"),
false,
false,
);
assert!(!entries.unwrap().is_empty());
}
22 changes: 17 additions & 5 deletions src/search_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use std::{
error::{self, Error},
path::{Path, PathBuf},
};
use walkdir::WalkDir;

use crate::UseCargoMetadata;
#[cfg(test)]
Expand Down Expand Up @@ -146,10 +145,23 @@ fn collect_paths(dir_path: &Path, analysis: &PackageAnalysis) -> Vec<PathBuf> {
trace!("adding src/ since paths was empty");
}

// Unfortunately WalkBuilder does not implement `std::iter::FromIterator`.
let walk_builder = {
let mut roots = root_paths.into_iter().map(|p| dir_path.join(p));
let builder = ignore::WalkBuilder::new(
roots
.next()
.unwrap_or_else(|| unreachable!("root_paths should contain at least one entry")),
);
roots.fold(builder, |mut builder, root| {
builder.add(root);
builder
})
};

// Collect all final paths for the crate first.
let paths: Vec<PathBuf> = root_paths
.iter()
.flat_map(|root| WalkDir::new(dir_path.join(root)).into_iter())
let paths = walk_builder
.build()
.filter_map(|result| {
let dir_entry = match result {
Ok(dir_entry) => dir_entry,
Expand All @@ -158,7 +170,7 @@ fn collect_paths(dir_path: &Path, analysis: &PackageAnalysis) -> Vec<PathBuf> {
return None;
}
};
if !dir_entry.file_type().is_file() {
if !dir_entry.file_type()?.is_file() {
return None;
}
if dir_entry
Expand Down

0 comments on commit 04063c9

Please sign in to comment.