Skip to content

Commit 2213321

Browse files
committed
Merge branch 'fix-commitgraph'
2 parents 8d2e6a9 + ff8d42a commit 2213321

File tree

9 files changed

+142
-18
lines changed

9 files changed

+142
-18
lines changed

gitoxide-core/src/commitgraph/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
1-
pub mod list;
2-
pub use list::function::list;
3-
41
pub mod verify;
52
pub use verify::function::verify;

gitoxide-core/src/commitgraph/verify.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,35 @@ pub struct Context<W1: std::io::Write, W2: std::io::Write> {
99
pub output_statistics: Option<OutputFormat>,
1010
}
1111

12-
pub(crate) mod function {
13-
use std::io;
12+
impl Default for Context<Vec<u8>, Vec<u8>> {
13+
fn default() -> Self {
14+
Context {
15+
err: Vec::new(),
16+
out: Vec::new(),
17+
output_statistics: None,
18+
}
19+
}
20+
}
1421

15-
use crate::commitgraph::verify::Context;
22+
pub(crate) mod function {
1623
use crate::OutputFormat;
1724
use anyhow::{Context as AnyhowContext, Result};
25+
use gix::commitgraph::{verify::Outcome, Graph};
26+
use std::{io, path::Path};
1827

1928
pub fn verify<W1, W2>(
20-
repo: gix::Repository,
21-
Context {
29+
path: impl AsRef<Path>,
30+
super::Context {
2231
err: _err,
2332
mut out,
2433
output_statistics,
25-
}: Context<W1, W2>,
34+
}: super::Context<W1, W2>,
2635
) -> Result<gix::commitgraph::verify::Outcome>
2736
where
2837
W1: io::Write,
2938
W2: io::Write,
3039
{
31-
let g = repo.commit_graph()?;
40+
let g = Graph::at(path).with_context(|| "Could not open commit graph")?;
3241

3342
#[allow(clippy::unnecessary_wraps, unknown_lints)]
3443
fn noop_processor(_commit: &gix::commitgraph::file::Commit<'_>) -> std::result::Result<(), std::fmt::Error> {
@@ -49,7 +58,7 @@ pub(crate) mod function {
4958
Ok(stats)
5059
}
5160

52-
fn print_human_output(out: &mut impl io::Write, stats: &gix::commitgraph::verify::Outcome) -> io::Result<()> {
61+
fn print_human_output(out: &mut impl io::Write, stats: &Outcome) -> io::Result<()> {
5362
writeln!(out, "number of commits with the given number of parents")?;
5463
let mut parent_counts: Vec<_> = stats.parent_counts.iter().map(|(a, b)| (*a, *b)).collect();
5564
parent_counts.sort_by_key(|e| e.0);

gitoxide-core/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ impl FromStr for OutputFormat {
6363
}
6464
}
6565

66+
pub mod commitgraph;
6667
pub mod net;
6768

68-
pub mod commitgraph;
6969
#[cfg(feature = "estimate-hours")]
7070
pub mod hours;
7171
pub mod index;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub mod list;
2+
pub use list::function::list;
3+
4+
pub mod verify;
5+
pub use verify::function::verify;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use crate::OutputFormat;
2+
3+
/// A general purpose context for many operations provided here
4+
pub struct Context<W1: std::io::Write, W2: std::io::Write> {
5+
/// A stream to which to output errors
6+
pub err: W2,
7+
/// A stream to which to output operation results
8+
pub out: W1,
9+
pub output_statistics: Option<OutputFormat>,
10+
}
11+
12+
pub(crate) mod function {
13+
use std::io;
14+
15+
use crate::repository::commitgraph::verify::Context;
16+
use crate::OutputFormat;
17+
use anyhow::{Context as AnyhowContext, Result};
18+
19+
pub fn verify<W1, W2>(
20+
repo: gix::Repository,
21+
Context {
22+
err: _err,
23+
mut out,
24+
output_statistics,
25+
}: Context<W1, W2>,
26+
) -> Result<gix::commitgraph::verify::Outcome>
27+
where
28+
W1: io::Write,
29+
W2: io::Write,
30+
{
31+
let g = repo.commit_graph()?;
32+
33+
#[allow(clippy::unnecessary_wraps, unknown_lints)]
34+
fn noop_processor(_commit: &gix::commitgraph::file::Commit<'_>) -> std::result::Result<(), std::fmt::Error> {
35+
Ok(())
36+
}
37+
let stats = g
38+
.verify_integrity(noop_processor)
39+
.with_context(|| "Verification failure")?;
40+
41+
#[cfg_attr(not(feature = "serde"), allow(clippy::single_match))]
42+
match output_statistics {
43+
Some(OutputFormat::Human) => drop(print_human_output(&mut out, &stats)),
44+
#[cfg(feature = "serde")]
45+
Some(OutputFormat::Json) => serde_json::to_writer_pretty(out, &stats)?,
46+
_ => {}
47+
}
48+
49+
Ok(stats)
50+
}
51+
52+
fn print_human_output(out: &mut impl io::Write, stats: &gix::commitgraph::verify::Outcome) -> io::Result<()> {
53+
writeln!(out, "number of commits with the given number of parents")?;
54+
let mut parent_counts: Vec<_> = stats.parent_counts.iter().map(|(a, b)| (*a, *b)).collect();
55+
parent_counts.sort_by_key(|e| e.0);
56+
for (parent_count, commit_count) in parent_counts.into_iter() {
57+
writeln!(out, "\t{parent_count:>2}: {commit_count}")?;
58+
}
59+
writeln!(out, "\t->: {}", stats.num_commits)?;
60+
61+
write!(out, "\nlongest path length between two commits: ")?;
62+
if let Some(n) = stats.longest_path_length {
63+
writeln!(out, "{n}")?;
64+
} else {
65+
writeln!(out, "unknown")?;
66+
}
67+
68+
Ok(())
69+
}
70+
}

gitoxide-core/src/repository/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub mod fetch;
2525
pub use clone::function::clone;
2626
#[cfg(feature = "blocking-client")]
2727
pub use fetch::function::fetch;
28+
pub mod commitgraph;
2829
pub mod index;
2930
pub mod mailmap;
3031
pub mod odb;

src/plumbing/main.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@ use gitoxide_core as core;
1313
use gitoxide_core::pack::verify;
1414
use gix::bstr::io::BufReadExt;
1515

16-
use crate::plumbing::options::commitgraph;
1716
use crate::{
1817
plumbing::{
1918
options::{
20-
attributes, commit, config, credential, exclude, free, index, mailmap, odb, revision, tree, Args,
21-
Subcommands,
19+
attributes, commit, commitgraph, config, credential, exclude, free, index, mailmap, odb, revision, tree,
20+
Args, Subcommands,
2221
},
2322
show_progress,
2423
},
@@ -136,7 +135,9 @@ pub fn main() -> Result<()> {
136135
progress,
137136
progress_keep_open,
138137
None,
139-
move |_progress, out, _err| core::commitgraph::list(repository(Mode::Lenient)?, spec, out, format),
138+
move |_progress, out, _err| {
139+
core::repository::commitgraph::list(repository(Mode::Lenient)?, spec, out, format)
140+
},
140141
)
141142
.map(|_| ()),
142143
commitgraph::Subcommands::Verify { statistics } => prepare_and_run(
@@ -147,9 +148,9 @@ pub fn main() -> Result<()> {
147148
None,
148149
move |_progress, out, err| {
149150
let output_statistics = if statistics { Some(format) } else { None };
150-
core::commitgraph::verify(
151+
core::repository::commitgraph::verify(
151152
repository(Mode::Lenient)?,
152-
core::commitgraph::verify::Context {
153+
core::repository::commitgraph::verify::Context {
153154
err,
154155
out,
155156
output_statistics,
@@ -301,6 +302,27 @@ pub fn main() -> Result<()> {
301302
)
302303
.map(|_| ()),
303304
Subcommands::Free(subcommands) => match subcommands {
305+
free::Subcommands::CommitGraph(cmd) => match cmd {
306+
free::commitgraph::Subcommands::Verify { path, statistics } => prepare_and_run(
307+
"commitgraph-verify",
308+
auto_verbose,
309+
progress,
310+
progress_keep_open,
311+
None,
312+
move |_progress, out, err| {
313+
let output_statistics = if statistics { Some(format) } else { None };
314+
core::commitgraph::verify(
315+
path,
316+
core::commitgraph::verify::Context {
317+
err,
318+
out,
319+
output_statistics,
320+
},
321+
)
322+
},
323+
)
324+
.map(|_| ()),
325+
},
304326
free::Subcommands::Index(free::index::Platform {
305327
object_hash,
306328
index_path,

src/plumbing/options/free.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#[derive(Debug, clap::Subcommand)]
22
#[clap(visible_alias = "no-repo")]
33
pub enum Subcommands {
4+
/// Subcommands for interacting with commit-graphs
5+
#[clap(subcommand)]
6+
CommitGraph(commitgraph::Subcommands),
47
/// Subcommands for interacting with mailmaps
58
Mailmap {
69
#[clap(flatten)]
@@ -13,6 +16,23 @@ pub enum Subcommands {
1316
Index(index::Platform),
1417
}
1518

19+
///
20+
pub mod commitgraph {
21+
use std::path::PathBuf;
22+
23+
#[derive(Debug, clap::Subcommand)]
24+
pub enum Subcommands {
25+
/// Verify the integrity of a commit graph
26+
Verify {
27+
/// The path to '.git/objects/info/', '.git/objects/info/commit-graphs/', or '.git/objects/info/commit-graph' to validate.
28+
path: PathBuf,
29+
/// output statistical information about the pack
30+
#[clap(long, short = 's')]
31+
statistics: bool,
32+
},
33+
}
34+
}
35+
1636
pub mod index {
1737
use std::path::PathBuf;
1838

0 commit comments

Comments
 (0)