diff --git a/git-features/src/parallel.rs b/git-features/src/parallel.rs index df445ee4f60..24f628b45a5 100644 --- a/git-features/src/parallel.rs +++ b/git-features/src/parallel.rs @@ -3,7 +3,7 @@ pub trait Reducer { type Output; type Error; fn feed(&mut self, input: Self::Input) -> Result<(), Self::Error>; - fn finalize(&mut self) -> Result; + fn finalize(self) -> Result; } mod serial { diff --git a/git-odb/src/pack/file/read.rs b/git-odb/src/pack/file/read.rs index c8f69f34551..7fbaace64c6 100644 --- a/git-odb/src/pack/file/read.rs +++ b/git-odb/src/pack/file/read.rs @@ -17,13 +17,13 @@ struct Delta { data_offset: u64, } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq, Hash, Ord, PartialOrd, Clone)] pub enum ResolvedBase { InPack(Entry), OutOfPack { kind: object::Kind, end: usize }, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Hash, Ord, PartialOrd, Clone)] pub struct DecodeEntryResult { pub kind: object::Kind, pub num_deltas: u32, diff --git a/git-odb/src/pack/index/verify.rs b/git-odb/src/pack/index/verify.rs index 3456f30d763..bc0f387646e 100644 --- a/git-odb/src/pack/index/verify.rs +++ b/git-odb/src/pack/index/verify.rs @@ -3,6 +3,7 @@ use crate::{pack, pack::index}; use git_features::progress::{self, Progress}; use git_object::SHA1_SIZE; use quick_error::quick_error; +use smallvec::alloc::collections::BTreeMap; use std::time::Instant; quick_error! { @@ -59,6 +60,14 @@ impl Into for TimeThroughput { } } +#[derive(Debug, PartialEq, Eq, Hash, Ord, PartialOrd, Clone)] +pub struct FileChecksumResult { + /// The sha1 over the whole index file + id: git_object::Id, + average: DecodeEntryResult, + objects_per_chain_length: BTreeMap, +} + /// Methods to verify and validate the content of the index file impl index::File { pub fn checksum_of_index(&self) -> git_object::Id { @@ -133,40 +142,34 @@ impl index::File { fn add_decode_result( DecodeEntryResult { - kind, - num_deltas, - decompressed_size, - compressed_size, - object_size, - }: DecodeEntryResult, + kind: _, + mut num_deltas, + mut decompressed_size, + mut compressed_size, + mut object_size, + }: &mut DecodeEntryResult, rhs: DecodeEntryResult, - ) -> DecodeEntryResult { - DecodeEntryResult { - kind, - num_deltas: num_deltas + rhs.num_deltas, - decompressed_size: decompressed_size + rhs.decompressed_size, - compressed_size: compressed_size + rhs.compressed_size, - object_size: object_size + rhs.object_size, - } + ) { + num_deltas += rhs.num_deltas; + decompressed_size += rhs.decompressed_size; + compressed_size += rhs.compressed_size; + object_size += rhs.object_size; } fn div_decode_result( DecodeEntryResult { - kind, - num_deltas, - decompressed_size, - compressed_size, - object_size, - }: DecodeEntryResult, + kind: _, + mut num_deltas, + mut decompressed_size, + mut compressed_size, + mut object_size, + }: &mut DecodeEntryResult, div: usize, - ) -> DecodeEntryResult { - DecodeEntryResult { - kind, - num_deltas: num_deltas / div as u32, - decompressed_size: decompressed_size / div as u64, - compressed_size: compressed_size / div, - object_size: object_size / div as u64, - } + ) { + num_deltas /= div as u32; + decompressed_size /= div as u64; + compressed_size /= div; + object_size /= div as u64; } struct Reducer<'a, P> { @@ -189,14 +192,15 @@ impl index::File { self.entries_seen += num_entries as u32; self.chunks_seen += 1; - self.stats = add_decode_result(self.stats, chunk_stats); + add_decode_result(&mut self.stats, chunk_stats); self.progress.lock().unwrap().set(self.entries_seen); Ok(()) } - fn finalize(&mut self) -> Result { + fn finalize(mut self) -> Result { self.progress.lock().unwrap().done("finished"); - Ok(div_decode_result(self.stats, self.chunks_seen)) + div_decode_result(&mut self.stats, self.chunks_seen); + Ok(self.stats) } } @@ -256,7 +260,7 @@ impl index::File { })?; let object_kind = entry_stats.kind; let consumed_input = entry_stats.compressed_size; - stats = add_decode_result(stats, entry_stats); + add_decode_result(&mut stats, entry_stats); let mut header_buf = [0u8; 64]; let header_size = crate::loose::db::serde::write_header( @@ -294,7 +298,7 @@ impl index::File { } progress.set(idx as u32); } - stats = div_decode_result(stats, entries.len()); + div_decode_result(&mut stats, entries.len()); Ok((entries.len(), stats)) }, Reducer { diff --git a/src/plumbing/lean.rs b/src/plumbing/lean.rs index 266b7e527df..36c4664a857 100644 --- a/src/plumbing/lean.rs +++ b/src/plumbing/lean.rs @@ -19,6 +19,9 @@ mod options { #[derive(FromArgs, PartialEq, Debug)] #[argh(subcommand, name = "verify-pack")] pub struct VerifyPack { + /// if set, output statistical information about the pack + #[argh(switch, short = 's')] + pub statistics: bool, /// if set, verbose progress messages are printed line by line #[argh(switch, short = 'v')] pub verbose: bool, @@ -37,7 +40,11 @@ pub fn main() -> Result<()> { pub use options::*; let cli: Args = argh::from_env(); match cli.subcommand { - SubCommands::VerifyPack(VerifyPack { path, verbose }) => { + SubCommands::VerifyPack(VerifyPack { + path, + verbose, + statistics, + }) => { super::init_env_logger(verbose); core::verify_pack_or_pack_index( path,