Unified · Split
| @@ -18,91 +18,5 @@ mod impls { · 17 unmodified lines | |||
| 18 | } | 18 | } |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | pub mod init { | 21 | pub mod init; |
| 22 | #![allow(unused)] | 22 | pub mod verify; |
| 23 | |||
| 24 | use std::path::{Path, PathBuf}; | ||
| 25 | |||
| 26 | use memmap2::Mmap; | ||
| 27 | |||
| 28 | use crate::{decode, extension, File, State}; | ||
| 29 | |||
| 30 | mod error { | ||
| 31 | use quick_error::quick_error; | ||
| 32 | |||
| 33 | quick_error! { | ||
| 34 | #[derive(Debug)] | ||
| 35 | pub enum Error { | ||
| 36 | Io(err: std::io::Error) { | ||
| 37 | display("An IO error occurred while opening the index") | ||
| 38 | source(err) | ||
| 39 | from() | ||
| 40 | } | ||
| 41 | Decode(err: crate::decode::Error) { | ||
| 42 | display("The file could not be decoded") | ||
| 43 | source(err) | ||
| 44 | from() | ||
| 45 | } | ||
| 46 | } | ||
| 47 | } | ||
| 48 | } | ||
| 49 | pub use error::Error; | ||
| 50 | |||
| 51 | impl File { | ||
| 52 | pub fn at(path: impl Into<PathBuf>, options: decode::Options) -> Result<Self, Error> { | ||
| 53 | let path = path.into(); | ||
| 54 | let (data, mtime) = { | ||
| 55 | // SAFETY: we have to take the risk of somebody changing the file underneath. Git never writes into the same file. | ||
| 56 | let file = std::fs::File::open(&path)?; | ||
| 57 | #[allow(unsafe_code)] | ||
| 58 | let data = unsafe { Mmap::map(&file)? }; | ||
| 59 | (data, filetime::FileTime::from_last_modification_time(&file.metadata()?)) | ||
| 60 | }; | ||
| 61 | |||
| 62 | let (state, checksum) = State::from_bytes(&data, mtime, options)?; | ||
| 63 | Ok(File { state, path, checksum }) | ||
| 64 | } | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | mod verify { | ||
| 69 | use crate::File; | ||
| 70 | use std::sync::atomic::AtomicBool; | ||
| 71 | |||
| 72 | pub mod error { | ||
| 73 | use quick_error::quick_error; | ||
| 74 | |||
| 75 | quick_error! { | ||
| 76 | #[derive(Debug)] | ||
| 77 | pub enum Error { | ||
| 78 | Io(err: std::io::Error) { | ||
| 79 | display("Could not read index file to generate hash") | ||
| 80 | source(err) | ||
| 81 | from() | ||
| 82 | } | ||
| 83 | ChecksumMismatch { actual: git_hash::ObjectId, expected: git_hash::ObjectId }{ | ||
| 84 | display("Index checksum should have been {}, but was {}", expected, actual) | ||
| 85 | } | ||
| 86 | } | ||
| 87 | } | ||
| 88 | } | ||
| 89 | pub use error::Error; | ||
| 90 | |||
| 91 | impl File { | ||
| 92 | pub fn verify_integrity(&self) -> Result<(), Error> { | ||
| 93 | let num_bytes_to_hash = self.path.metadata()?.len() - self.checksum.as_bytes().len() as u64; | ||
| 94 | let should_interrupt = AtomicBool::new(false); | ||
| 95 | let actual = git_features::hash::bytes_of_file( | ||
| 96 | &self.path, | ||
| 97 | num_bytes_to_hash as usize, | ||
| 98 | self.checksum.kind(), | ||
| 99 | &mut git_features::progress::Discard, | ||
| 100 | &should_interrupt, | ||
| 101 | )?; | ||
| 102 | (actual == self.checksum).then(|| ()).ok_or(Error::ChecksumMismatch { | ||
| 103 | actual, | ||
| 104 | expected: self.checksum, | ||
| 105 | }) | ||
| 106 | } | ||
| 107 | } | ||
| 108 | } | ||
| @@ -0,0 +1,45 @@ | |||
| 1 | #![allow(unused)] | ||
| 2 | |||
| 3 | use std::path::{Path, PathBuf}; | ||
| 4 | |||
| 5 | use memmap2::Mmap; | ||
| 6 | |||
| 7 | use crate::{decode, extension, File, State}; | ||
| 8 | |||
| 9 | mod error { | ||
| 10 | use quick_error::quick_error; | ||
| 11 | |||
| 12 | quick_error! { | ||
| 13 | #[derive(Debug)] | ||
| 14 | pub enum Error { | ||
| 15 | Io(err: std::io::Error) { | ||
| 16 | display("An IO error occurred while opening the index") | ||
| 17 | source(err) | ||
| 18 | from() | ||
| 19 | } | ||
| 20 | Decode(err: crate::decode::Error) { | ||
| 21 | display("The file could not be decoded") | ||
| 22 | source(err) | ||
| 23 | from() | ||
| 24 | } | ||
| 25 | } | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | pub use error::Error; | ||
| 30 | |||
| 31 | impl File { | ||
| 32 | pub fn at(path: impl Into<PathBuf>, options: decode::Options) -> Result<Self, Error> { | ||
| 33 | let path = path.into(); | ||
| 34 | let (data, mtime) = { | ||
| 35 | // SAFETY: we have to take the risk of somebody changing the file underneath. Git never writes into the same file. | ||
| 36 | let file = std::fs::File::open(&path)?; | ||
| 37 | #[allow(unsafe_code)] | ||
| 38 | let data = unsafe { Mmap::map(&file)? }; | ||
| 39 | (data, filetime::FileTime::from_last_modification_time(&file.metadata()?)) | ||
| 40 | }; | ||
| 41 | |||
| 42 | let (state, checksum) = State::from_bytes(&data, mtime, options)?; | ||
| 43 | Ok(File { state, path, checksum }) | ||
| 44 | } | ||
| 45 | } | ||
| @@ -0,0 +1,39 @@ | |||
| 1 | use crate::File; | ||
| 2 | use std::sync::atomic::AtomicBool; | ||
| 3 | |||
| 4 | pub mod error { | ||
| 5 | use quick_error::quick_error; | ||
| 6 | |||
| 7 | quick_error! { | ||
| 8 | #[derive(Debug)] | ||
| 9 | pub enum Error { | ||
| 10 | Io(err: std::io::Error) { | ||
| 11 | display("Could not read index file to generate hash") | ||
| 12 | source(err) | ||
| 13 | from() | ||
| 14 | } | ||
| 15 | ChecksumMismatch { actual: git_hash::ObjectId, expected: git_hash::ObjectId }{ | ||
| 16 | display("Index checksum should have been {}, but was {}", expected, actual) | ||
| 17 | } | ||
| 18 | } | ||
| 19 | } | ||
| 20 | } | ||
| 21 | pub use error::Error; | ||
| 22 | |||
| 23 | impl File { | ||
| 24 | pub fn verify_integrity(&self) -> Result<(), Error> { | ||
| 25 | let num_bytes_to_hash = self.path.metadata()?.len() - self.checksum.as_bytes().len() as u64; | ||
| 26 | let should_interrupt = AtomicBool::new(false); | ||
| 27 | let actual = git_features::hash::bytes_of_file( | ||
| 28 | &self.path, | ||
| 29 | num_bytes_to_hash as usize, | ||
| 30 | self.checksum.kind(), | ||
| 31 | &mut git_features::progress::Discard, | ||
| 32 | &should_interrupt, | ||
| 33 | )?; | ||
| 34 | (actual == self.checksum).then(|| ()).ok_or(Error::ChecksumMismatch { | ||
| 35 | actual, | ||
| 36 | expected: self.checksum, | ||
| 37 | }) | ||
| 38 | } | ||
| 39 | } | ||