use {
crate::*,
anyhow::{
Context,
Result,
},
gix::{
self as git,
Repository,
},
std::path::Path,
};
pub struct GitIgnorer {
repo: Repository,
}
impl GitIgnorer {
pub(crate) fn new(root_path: &Path) -> Result<Self> {
let repo = git::discover(root_path)?;
Ok(Self { repo })
}
}
impl Ignorer for GitIgnorer {
fn excludes(
&mut self,
paths: &Path,
) -> Result<bool> {
self.excludes_all_paths(&[paths])
}
}
impl GitIgnorer {
fn excludes_all_paths(
&mut self,
paths: &[&Path],
) -> Result<bool> {
let worktree = self.repo.worktree().context("a worktree should exist")?;
let mut cache = time!(Debug, worktree.excludes(None)?);
for path in paths {
let Some(work_dir) = self.repo.workdir() else {
return Ok(false);
};
let Ok(relative_path) = path.strip_prefix(work_dir) else {
return Ok(false);
};
if relative_path.as_os_str().is_empty() {
return Ok(true);
}
if path.is_dir() {
return Ok(false);
}
let platform = cache.at_path(relative_path, Some(gix::index::entry::Mode::FILE))?;
if !platform.is_excluded() {
return Ok(false);
}
}
Ok(true)
}
}