Skip to main content

gitoxide_core/repository/
dirwalk.rs

1use 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}