use ignore::WalkBuilder;
use std::path::{Path, PathBuf};
use std::sync::Mutex;
#[must_use]
pub fn collect_files(root: &Path, file_type: Option<&str>) -> Vec<PathBuf> {
let files = Mutex::new(Vec::new());
let mut builder = WalkBuilder::new(root);
builder.hidden(true).git_ignore(true).git_global(true);
if let Some(ft) = file_type {
let mut types_builder = ignore::types::TypesBuilder::new();
types_builder.add_defaults();
types_builder.select(ft);
if let Ok(types) = types_builder.build() {
builder.types(types);
}
}
builder.build_parallel().run(|| {
Box::new(|entry| {
let Ok(entry) = entry else {
return ignore::WalkState::Continue;
};
if !entry.file_type().is_some_and(|ft| ft.is_file()) {
return ignore::WalkState::Continue;
}
if let Some(name) = entry.path().file_name().and_then(|n| n.to_str())
&& matches!(
name,
"Cargo.lock"
| "package-lock.json"
| "yarn.lock"
| "pnpm-lock.yaml"
| "poetry.lock"
| "Gemfile.lock"
| "go.sum"
)
{
return ignore::WalkState::Continue;
}
if let Ok(mut files) = files.lock() {
files.push(entry.into_path());
}
ignore::WalkState::Continue
})
});
let mut files = files.into_inner().unwrap_or_default();
files.sort();
files
}