claux 20260730.0.1

Terminal AI coding assistant with tool execution
use std::path::{Component, Path};

pub(super) fn is_excluded(
    path: &Path,
    base: &Path,
    include_hidden: bool,
    include_build_dirs: bool,
) -> bool {
    let relative = path.strip_prefix(base).unwrap_or(path);

    relative.components().any(|component| {
        let Component::Normal(name) = component else {
            return false;
        };
        let name = name.to_string_lossy();
        (!include_hidden && name.starts_with('.')) || (!include_build_dirs && name == "target")
    })
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn excludes_hidden_and_target_components_by_default() {
        let base = Path::new("/project");

        assert!(is_excluded(
            Path::new("/project/.github/workflows/ci.yml"),
            base,
            false,
            false
        ));
        assert!(is_excluded(
            Path::new("/project/crate/target/debug/app"),
            base,
            false,
            false
        ));
        assert!(!is_excluded(
            Path::new("/project/src/targeted.rs"),
            base,
            false,
            false
        ));
    }

    #[test]
    fn flags_allow_hidden_and_target_components() {
        let base = Path::new("/project");

        assert!(!is_excluded(
            Path::new("/project/.github/workflows/ci.yml"),
            base,
            true,
            false
        ));
        assert!(!is_excluded(
            Path::new("/project/target/debug/app"),
            base,
            false,
            true
        ));
    }

    #[test]
    fn explicitly_selected_base_is_not_excluded() {
        assert!(!is_excluded(
            Path::new("/project/.github/workflows/ci.yml"),
            Path::new("/project/.github"),
            false,
            false
        ));
        assert!(!is_excluded(
            Path::new("/project/target/debug/app"),
            Path::new("/project/target"),
            false,
            false
        ));
    }
}