use std::path::{Path, PathBuf};
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Components {
Include,
SkipWhenWalking,
}
pub fn collect(paths: &[PathBuf], components: Components) -> Result<Vec<PathBuf>, String> {
let (mut explicit, mut walked) = (Vec::new(), Vec::new());
if paths.is_empty() {
walk(Path::new("."), &mut walked)?;
}
for root in paths {
if root.is_file() {
explicit.push(root.clone());
} else if root.is_dir() {
walk(root, &mut walked)?;
} else {
return Err(format!("no such file or directory: {}", root.display()));
}
}
let mut files = explicit;
files.extend(walked.into_iter().filter(|f| match components {
Components::Include => true,
Components::SkipWhenWalking => rux_runtime::is_entry_point(f) != Some(false),
}));
files.sort();
files.dedup();
Ok(files)
}
fn walk(dir: &Path, out: &mut Vec<PathBuf>) -> Result<(), String> {
let entries = std::fs::read_dir(dir).map_err(|e| format!("reading {}: {e}", dir.display()))?;
for entry in entries.flatten() {
let path = entry.path();
let name = entry.file_name();
let name = name.to_string_lossy();
if name.starts_with('.') || name == "target" || name == "node_modules" {
continue;
}
if path.is_dir() {
walk(&path, out)?;
} else if path.extension().is_some_and(|e| e == "rux") {
out.push(path);
}
}
Ok(())
}