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 | +} | |