use std::path::{Path, PathBuf};
use globset::{Glob, GlobSet, GlobSetBuilder};
use ignore::WalkBuilder;
use sdivi_config::Config;
pub fn collect_files(config: &Config, repo_root: &Path) -> Vec<PathBuf> {
let exclude = build_exclude_set(&config.core.exclude);
let mut files: Vec<PathBuf> = WalkBuilder::new(repo_root)
.hidden(false)
.git_ignore(true)
.git_global(false)
.git_exclude(false)
.build()
.filter_map(|entry| entry.ok())
.filter(|entry| entry.file_type().map(|ft| ft.is_file()).unwrap_or(false))
.map(|entry| entry.into_path())
.filter(|path| !is_excluded(path, repo_root, exclude.as_ref()))
.collect();
files.sort();
files
}
fn is_excluded(path: &Path, repo_root: &Path, exclude: Option<&GlobSet>) -> bool {
let Some(gs) = exclude else { return false };
let relative = path.strip_prefix(repo_root).unwrap_or(path);
gs.is_match(relative)
}
fn build_exclude_set(patterns: &[String]) -> Option<GlobSet> {
if patterns.is_empty() {
return None;
}
let mut builder = GlobSetBuilder::new();
for pattern in patterns {
if let Ok(glob) = Glob::new(pattern) {
builder.add(glob);
}
}
builder.build().ok()
}