gitoxide_core/repository/
dirwalk.rs1use anyhow::bail;
2use gix::{
3 bstr::BString,
4 dir::{
5 EntryRef,
6 walk::{self, EmissionMode},
7 },
8};
9
10use crate::OutputFormat;
11
12#[derive(Copy, Clone)]
13pub enum Untracked {
14 Collapsed,
15 Matching,
16}
17
18pub struct Options {
19 pub output_format: OutputFormat,
20 pub statistics: bool,
21 pub untracked: Untracked,
22}
23
24pub fn walk(
25 repo: gix::Repository,
26 patterns: Vec<BString>,
27 mut out: impl std::io::Write,
28 mut err: impl std::io::Write,
29 Options {
30 output_format,
31 statistics,
32 untracked,
33 }: Options,
34) -> anyhow::Result<()> {
35 if output_format != OutputFormat::Human {
36 bail!("Only human format is supported right now");
37 }
38 let index = repo.index_or_empty()?;
39 let options = repo.dirwalk_options()?.emit_untracked(match untracked {
40 Untracked::Collapsed => EmissionMode::CollapseDirectory,
41 Untracked::Matching => EmissionMode::Matching,
42 });
43
44 let start = std::time::Instant::now();
45 let mut delegate = Count::default();
46 let outcome = repo.dirwalk(
47 &index,
48 patterns,
49 &gix::interrupt::IS_INTERRUPTED,
50 options,
51 &mut delegate,
52 )?;
53
54 if statistics {
55 writeln!(
56 err,
57 "dirwalk done {} entries in {:.2?}",
58 delegate.entries,
59 start.elapsed()
60 )?;
61 writeln!(err, "{:?}", outcome.dirwalk)?;
62 } else {
63 writeln!(out, "{}", delegate.entries)?;
64 }
65 Ok(())
66}
67
68#[derive(Default)]
69struct Count {
70 entries: u64,
71}
72
73impl walk::Delegate for Count {
74 fn emit(
75 &mut self,
76 _entry: EntryRef<'_>,
77 _collapsed_directory_status: Option<gix::dir::entry::Status>,
78 ) -> walk::Action {
79 self.entries += 1;
80 std::ops::ControlFlow::Continue(())
81 }
82}