Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit add4cf4

Browse files
codexByron
andcommitted
feat: gix dirwalk as a way to run gix-dir directly
This is mostly for testing walks specifically, without needing them as part of `gix clean` or `gix status`. Co-authored-by: Sebastian Thiel <[email protected]>
1 parent c01236a commit add4cf4

4 files changed

Lines changed: 145 additions & 0 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use anyhow::bail;
2+
use gix::{
3+
bstr::BString,
4+
dir::{
5+
EntryRef,
6+
walk::{self, EmissionMode},
7+
},
8+
};
9+
10+
use crate::OutputFormat;
11+
12+
#[derive(Copy, Clone)]
13+
pub enum Untracked {
14+
Collapsed,
15+
Matching,
16+
}
17+
18+
pub struct Options {
19+
pub output_format: OutputFormat,
20+
pub statistics: bool,
21+
pub untracked: Untracked,
22+
}
23+
24+
pub 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)]
69+
struct Count {
70+
entries: u64,
71+
}
72+
73+
impl 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+
}

gitoxide-core/src/repository/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub mod attributes;
1919
pub mod clean;
2020
pub mod diff;
2121
pub mod dirty;
22+
pub mod dirwalk;
2223
#[cfg(feature = "clean")]
2324
pub use clean::function::clean;
2425
#[cfg(feature = "blocking-client")]

src/plumbing/main.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,38 @@ pub fn main() -> Result<()> {
443443
)
444444
},
445445
),
446+
Subcommands::Dirwalk(crate::plumbing::options::dirwalk::Platform {
447+
statistics,
448+
untracked,
449+
pathspec,
450+
}) => prepare_and_run(
451+
"dirwalk",
452+
trace,
453+
auto_verbose,
454+
progress,
455+
progress_keep_open,
456+
None,
457+
move |_progress, out, err| {
458+
core::repository::dirwalk::walk(
459+
repository(Mode::Lenient)?,
460+
pathspec,
461+
out,
462+
err,
463+
core::repository::dirwalk::Options {
464+
output_format: format,
465+
statistics,
466+
untracked: match untracked {
467+
crate::plumbing::options::dirwalk::Untracked::Collapsed => {
468+
core::repository::dirwalk::Untracked::Collapsed
469+
}
470+
crate::plumbing::options::dirwalk::Untracked::Matching => {
471+
core::repository::dirwalk::Untracked::Matching
472+
}
473+
},
474+
},
475+
)
476+
},
477+
),
446478
Subcommands::Submodule(platform) => match platform
447479
.cmds
448480
.unwrap_or(crate::plumbing::options::submodule::Subcommands::List { dirty_suffix: None })

src/plumbing/options/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ pub enum Subcommands {
153153
/// Show which git configuration values are used or planned.
154154
ConfigTree,
155155
Status(status::Platform),
156+
Dirwalk(dirwalk::Platform),
156157
Config(config::Platform),
157158
#[cfg(feature = "gitoxide-core-tools-corpus")]
158159
Corpus(corpus::Platform),
@@ -325,6 +326,35 @@ pub mod status {
325326
}
326327
}
327328

329+
pub mod dirwalk {
330+
use gix::bstr::BString;
331+
332+
use crate::shared::CheckPathSpec;
333+
334+
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)]
335+
pub enum Untracked {
336+
/// Collapse untracked directories when possible.
337+
#[default]
338+
Collapsed,
339+
/// Emit matching untracked files and directories.
340+
Matching,
341+
}
342+
343+
#[derive(Debug, clap::Parser)]
344+
#[command(about = "Run only the repository directory walk")]
345+
pub struct Platform {
346+
/// Print additional statistics to help understanding performance.
347+
#[clap(long, short = 's')]
348+
pub statistics: bool,
349+
/// How untracked files should be emitted.
350+
#[clap(long, default_value = "collapsed")]
351+
pub untracked: Untracked,
352+
/// The git path specifications to walk.
353+
#[clap(value_parser = CheckPathSpec)]
354+
pub pathspec: Vec<BString>,
355+
}
356+
}
357+
328358
pub mod merge_base {
329359
#[derive(Debug, clap::Parser)]
330360
#[command(about = "A command for calculating all merge-bases")]

0 commit comments

Comments
 (0)