use std::io;use anyhow::{bail, Context};use git_repository as git;use git_repository::prelude::FindExt;use crate::OutputFormat;pub mod query { use std::ffi::OsString; use crate::OutputFormat; pub struct Options { pub format: OutputFormat, pub overrides: Vec<OsString>, pub show_ignore_patterns: bool, }}pub fn query( repo: git::Repository, pathspecs: impl Iterator<Item = git::path::Spec>, mut out: impl io::Write, query::Options { overrides, format, show_ignore_patterns, }: query::Options,) -> anyhow::Result<()> { if format != OutputFormat::Human { bail!("JSON output isn't implemented yet"); } let worktree = repo .worktree() .with_context(|| "Cannot check excludes without a current worktree")?; let index = worktree.index()?; let mut cache = worktree.excludes( &index.state, Some(git::attrs::MatchGroup::<git::attrs::Ignore>::from_overrides(overrides)), )?; let prefix = repo.prefix().expect("worktree - we have an index by now")?; for mut spec in pathspecs { for path in spec.apply_prefix(&prefix).items() { // TODO: what about paths that end in /? Pathspec might handle it, it's definitely something git considers // even if the directory doesn't exist. Seems to work as long as these are kept in the spec. let is_dir = git::path::from_bstr(path).metadata().ok().map(|m| m.is_dir()); let entry = cache.at_entry(path, is_dir, |oid, buf| repo.objects.find_blob(oid, buf))?; let match_ = entry .matching_exclude_pattern() .and_then(|m| (show_ignore_patterns || !m.pattern.is_negative()).then(|| m)); match match_ { Some(m) => writeln!( out, "{}:{}:{}\t{}", m.source.map(|p| p.to_string_lossy()).unwrap_or_default(), m.sequence_number, m.pattern, path )?, None => writeln!(out, "::\t{}", path)?, } } } Ok(())}
use std::io;
use anyhow::{bail, Context};
use git_repository as git;
use git_repository::prelude::FindExt;
use crate::OutputFormat;
pub mod query {
use std::ffi::OsString;
use crate::OutputFormat;
pub struct Options {
pub format: OutputFormat,
pub overrides: Vec<OsString>,
pub show_ignore_patterns: bool,
}
}
pub fn query(
repo: git::Repository,
pathspecs: impl Iterator<Item = git::path::Spec>,
mut out: impl io::Write,
query::Options {
overrides,
format,
show_ignore_patterns,
}: query::Options,
) -> anyhow::Result<()> {
if format != OutputFormat::Human {
bail!("JSON output isn't implemented yet");
}
let worktree = repo
.worktree()
.with_context(|| "Cannot check excludes without a current worktree")?;
let index = worktree.index()?;
let mut cache = worktree.excludes(
&index.state,
Some(git::attrs::MatchGroup::<git::attrs::Ignore>::from_overrides(overrides)),
)?;
let prefix = repo.prefix().expect("worktree - we have an index by now")?;
for mut spec in pathspecs {
for path in spec.apply_prefix(&prefix).items() {
// TODO: what about paths that end in /? Pathspec might handle it, it's definitely something git considers
// even if the directory doesn't exist. Seems to work as long as these are kept in the spec.
let is_dir = git::path::from_bstr(path).metadata().ok().map(|m| m.is_dir());
let entry = cache.at_entry(path, is_dir, |oid, buf| repo.objects.find_blob(oid, buf))?;
let match_ = entry
.matching_exclude_pattern()
.and_then(|m| (show_ignore_patterns || !m.pattern.is_negative()).then(|| m));
match match_ {
Some(m) => writeln!(
out,
"{}:{}:{}\t{}",
m.source.map(|p| p.to_string_lossy()).unwrap_or_default(),
m.sequence_number,
m.pattern,
path
)?,
None => writeln!(out, "::\t{}", path)?,
}
}
}
Ok(())
}