use anyhow::bail; use gix::{ bstr::BString, dir::{ EntryRef, walk::{self, EmissionMode}, }, }; use crate::OutputFormat; #[derive(Copy, Clone)] pub enum Untracked { Collapsed, Matching, } pub struct Options { pub output_format: OutputFormat, pub statistics: bool, pub untracked: Untracked, } pub fn walk( repo: gix::Repository, patterns: Vec, mut out: impl std::io::Write, mut err: impl std::io::Write, Options { output_format, statistics, untracked, }: Options, ) -> anyhow::Result<()> { if output_format != OutputFormat::Human { bail!("Only human format is supported right now"); } let index = repo.index_or_empty()?; let options = repo.dirwalk_options()?.emit_untracked(match untracked { Untracked::Collapsed => EmissionMode::CollapseDirectory, Untracked::Matching => EmissionMode::Matching, }); let start = std::time::Instant::now(); let mut delegate = Count::default(); let outcome = repo.dirwalk( &index, patterns, &gix::interrupt::IS_INTERRUPTED, options, &mut delegate, )?; if statistics { writeln!( err, "dirwalk done {} entries in {:.2?}", delegate.entries, start.elapsed() )?; writeln!(err, "{:?}", outcome.dirwalk)?; } else { writeln!(out, "{}", delegate.entries)?; } Ok(()) } #[derive(Default)] struct Count { entries: u64, } impl walk::Delegate for Count { fn emit( &mut self, _entry: EntryRef<'_>, _collapsed_directory_status: Option, ) -> walk::Action { self.entries += 1; std::ops::ControlFlow::Continue(()) } }