-
I'm trying to determine the correct way to check whether a path is ignored. I came up with this program: // Tell whether a given path is gitignored or not
use anyhow::Context;
use git_repository as git;
use git_repository::prelude::*;
use std::path::Path;
fn main() -> anyhow::Result<()> {
let file_path = std::env::args_os().nth(1).context("Expected a path to test")?;
let file_path = Path::new(&file_path).canonicalize()?;
if !file_path.try_exists()? {
eprintln!("file not found");
return Ok(());
}
let is_dir = file_path.is_dir();
let dir_path = if is_dir {
file_path.clone()
} else {
// discovering fails if not provided a directory so we take the parent
file_path.parent().context("No parent")?.to_path_buf()
};
let Ok(repo) = git::discover(&dir_path) else {
println!("{:?} isn't ignored because it's not in a git repository", &file_path);
return Ok(());
};
let work_dir = repo.work_dir().context("No work dir in this git repository")?; // should not happen ?
let worktree = repo.worktree().context("No worktree")?;
let index = worktree.index()?;
// there doesn't seem to be any public API for looking at "excludes" without caching
// so we create a cache
let mut cache = worktree.excludes(&index, None)?;
// cache.at_path panics if not provided a path relative
// to the work directory, so we compute the relative path
let relative_path = file_path
.strip_prefix(&work_dir)
.context("Path can't be made relative to the workdir")?;
// cache.at_path panics if the relative path is empty, so
// we must check it
if relative_path.as_os_str().is_empty() {
println!("{:?} isn't ignored because it's the repo root", &file_path);
return Ok(());
};
let platform = cache.at_path(&relative_path, Some(is_dir), |oid, buf| {
repo.objects.find_blob(oid, buf)
})?;
let is_ignored = platform.is_excluded();
if is_ignored {
println!("{:?} is ignored", &file_path);
} else {
println!("{:?} is not ignored", &file_path);
}
Ok(())
} It works but I feel like I'm not on the right path. Can you tell what I missed and how this program could be better written ? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Thanks for letting me know. Indeed, it's not exactly easy to use this API right now and it's still young. Despite that, it does what it says on the label and I consider the There is An alternative implementation can be found in the test-tools library which doesn't use ref-specs either as it's really only interested in single files. Maybe from these two examples you can find the intersection that suits you best, that's where it is at right now. I would expect this to become more polished through the first half of the next year as more worktree support will be added then. I hope this helps. |
Beta Was this translation helpful? Give feedback.
-
Thanks, I'll have a deeper look at those implementations. I don't understand when to use I'm introducing this in bacon: https://github.com/Canop/bacon/pull/98/files#diff-4f5d0cd8a6c77ae49bdd9f0742b1e8906d3908133ca14d5971c56910ec0ecfda Here's my uneducated opinion, based on this fast experience, on what should be improved here:
|
Beta Was this translation helpful? Give feedback.
Thanks for letting me know.
Indeed, it's not exactly easy to use this API right now and it's still young. Despite that, it does what it says on the label and I consider the
ignore
file handling as correct as I could make it. It definitely lacks documentation about its expectations and when it would panic if they are not met.There is
gix exclude query <path-spec>
and its implementation which should serve as authoritative example. All paths provided for use against theindex
should be considered path specs, and with that there is an API to handle the typical conversions.An alternative implementation can be found in the test-tools library which doesn't use ref-specs either as it's really o…