Showing the changes to gitoxide-core/src/commitgraph (2 of 5 files). Show all
Unified · Split
| @@ -0,0 +1,2 @@ | |||
| 1 | pub mod verify; | ||
| 2 | pub use verify::function::verify; | ||
| @@ -0,0 +1,79 @@ | |||
| 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 | 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 | } | ||
| 21 | |||
| 22 | pub(crate) mod function { | ||
| 23 | use crate::OutputFormat; | ||
| 24 | use anyhow::{Context as AnyhowContext, Result}; | ||
| 25 | use gix::commitgraph::{verify::Outcome, Graph}; | ||
| 26 | use std::{io, path::Path}; | ||
| 27 | |||
| 28 | pub fn verify<W1, W2>( | ||
| 29 | path: impl AsRef<Path>, | ||
| 30 | super::Context { | ||
| 31 | err: _err, | ||
| 32 | mut out, | ||
| 33 | output_statistics, | ||
| 34 | }: super::Context<W1, W2>, | ||
| 35 | ) -> Result<gix::commitgraph::verify::Outcome> | ||
| 36 | where | ||
| 37 | W1: io::Write, | ||
| 38 | W2: io::Write, | ||
| 39 | { | ||
| 40 | let g = Graph::at(path).with_context(|| "Could not open commit graph")?; | ||
| 41 | |||
| 42 | #[allow(clippy::unnecessary_wraps, unknown_lints)] | ||
| 43 | fn noop_processor(_commit: &gix::commitgraph::file::Commit<'_>) -> std::result::Result<(), std::fmt::Error> { | ||
| 44 | Ok(()) | ||
| 45 | } | ||
| 46 | let stats = g | ||
| 47 | .verify_integrity(noop_processor) | ||
| 48 | .with_context(|| "Verification failure")?; | ||
| 49 | |||
| 50 | #[cfg_attr(not(feature = "serde"), allow(clippy::single_match))] | ||
| 51 | match output_statistics { | ||
| 52 | Some(OutputFormat::Human) => drop(print_human_output(&mut out, &stats)), | ||
| 53 | #[cfg(feature = "serde")] | ||
| 54 | Some(OutputFormat::Json) => serde_json::to_writer_pretty(out, &stats)?, | ||
| 55 | _ => {} | ||
| 56 | } | ||
| 57 | |||
| 58 | Ok(stats) | ||
| 59 | } | ||
| 60 | |||
| 61 | fn print_human_output(out: &mut impl io::Write, stats: &Outcome) -> io::Result<()> { | ||
| 62 | writeln!(out, "number of commits with the given number of parents")?; | ||
| 63 | let mut parent_counts: Vec<_> = stats.parent_counts.iter().map(|(a, b)| (*a, *b)).collect(); | ||
| 64 | parent_counts.sort_by_key(|e| e.0); | ||
| 65 | for (parent_count, commit_count) in parent_counts.into_iter() { | ||
| 66 | writeln!(out, "\t{parent_count:>2}: {commit_count}")?; | ||
| 67 | } | ||
| 68 | writeln!(out, "\t->: {}", stats.num_commits)?; | ||
| 69 | |||
| 70 | write!(out, "\nlongest path length between two commits: ")?; | ||
| 71 | if let Some(n) = stats.longest_path_length { | ||
| 72 | writeln!(out, "{n}")?; | ||
| 73 | } else { | ||
| 74 | writeln!(out, "unknown")?; | ||
| 75 | } | ||
| 76 | |||
| 77 | Ok(()) | ||
| 78 | } | ||
| 79 | } | ||