This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / knot2 / third_party / gix-pack / src / verify.rs
2.5 kB 65 lines
1use std::{path::Path, sync::atomic::AtomicBool}; 2 3use gix_features::progress::Progress; 4 5/// 6pub mod checksum { 7 /// Returned by various methods to verify the checksum of a memory mapped file that might also exist on disk. 8 #[derive(thiserror::Error, Debug)] 9 #[allow(missing_docs)] 10 pub enum Error { 11 #[error("Interrupted by user")] 12 Interrupted, 13 #[error("Failed to hash data")] 14 Hasher(#[from] gix_hash::hasher::Error), 15 #[error(transparent)] 16 Verify(#[from] gix_hash::verify::Error), 17 #[error("Failed to read pack data for checksum verification")] 18 Io(#[from] std::io::Error), 19 } 20} 21 22/// Returns the `index` at which the following `index + 1` value is not an increment over the value at `index`. 23pub fn fan(data: &[u32]) -> Option<usize> { 24 data.windows(2) 25 .enumerate() 26 .find_map(|(win_index, v)| (v[0] > v[1]).then_some(win_index)) 27} 28 29/// Calculate the hash of the given kind by trying to read the file from disk at `data_path` or falling back on the mapped content in `data`. 30/// `Ok(expected)` or [`checksum::Error::Verify`] is returned if the hash matches or mismatches. 31/// If the [`checksum::Error::Interrupted`] is returned, the operation was interrupted. 32pub fn checksum_on_disk_or_mmap( 33 data_path: &Path, 34 data: &[u8], 35 expected: gix_hash::ObjectId, 36 object_hash: gix_hash::Kind, 37 progress: &mut dyn Progress, 38 should_interrupt: &AtomicBool, 39) -> Result<gix_hash::ObjectId, checksum::Error> { 40 let data_len_without_trailer = data.len() - object_hash.len_in_bytes(); 41 let actual = match gix_hash::bytes_of_file( 42 data_path, 43 data_len_without_trailer as u64, 44 object_hash, 45 progress, 46 should_interrupt, 47 ) { 48 Ok(id) => id, 49 Err(gix_hash::io::Error::Io(err)) if err.kind() == std::io::ErrorKind::Interrupted => { 50 return Err(checksum::Error::Interrupted); 51 } 52 Err(gix_hash::io::Error::Io(_io_err)) => { 53 let start = std::time::Instant::now(); 54 let mut hasher = gix_hash::hasher(object_hash); 55 hasher.update(&data[..data_len_without_trailer]); 56 progress.inc_by(data_len_without_trailer); 57 progress.show_throughput(start); 58 hasher.try_finalize()? 59 } 60 Err(gix_hash::io::Error::Hasher(err)) => return Err(checksum::Error::Hasher(err)), 61 }; 62 63 actual.verify(&expected)?; 64 Ok(actual) 65}