History

Read all mandatory and optional chunks (#279)

Sebastian Thiel committed 4 years ago

Commit 99023bb1 parent fac8efa2 files · +61 −2Browse files

Unified · Split

2 files
  1. git-chunk/src/lib.rs +31 −1
  2. git-pack/src/multi_index.rs +30 −1
git-chunk/src/lib.rs+31−1
@@ -17,6 +17,31 @@ pub mod file { · 16 unmodified lines
1717 use crate::file::Index;
1818 use std::ops::Range;
1919
20+ ///
21+ pub mod not_found {
22+ use std::fmt::{Display, Formatter};
23+
24+ /// The error returned by [Index::offset_by_kind()][super::Index::offset_by_kind()].
25+ #[allow(missing_docs)]
26+ #[derive(Debug)]
27+ pub struct Error {
28+ pub kind: crate::Kind,
29+ pub name: &'static str,
30+ }
31+
32+ impl Display for Error {
33+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
34+ write!(
35+ f,
36+ "Chunk named {:?} (id = {}) was not found in chunk file index",
37+ self.name, self.kind
38+ )
39+ }
40+ }
41+
42+ impl std::error::Error for Error {}
43+ }
44+
2045 /// An entry of a chunk file index
2146 pub struct Entry {
2247 /// The kind of the chunk file
@@ -32,10 +57,15 @@ pub mod file { · 9 unmodified lines
3257 pub const EMPTY_SIZE: usize = Index::ENTRY_SIZE;
3358
3459 /// Find a chunk of `kind` and return its offset into the data if found
35− pub fn offset_by_kind(&self, kind: crate::Kind) -> Option<Range<crate::file::Offset>> {
60+ pub fn offset_by_kind(
61+ &self,
62+ kind: crate::Kind,
63+ name: &'static str,
64+ ) -> Result<Range<crate::file::Offset>, not_found::Error> {
3665 self.chunks
3766 .iter()
3867 .find_map(|c| (c.kind == kind).then(|| c.offset.clone()))
68+ .ok_or_else(|| not_found::Error { kind, name })
3969 }
4070 }
4171 }
git-pack/src/multi_index.rs+30−1
@@ -1,5 +1,7 @@
11 #![allow(missing_docs, unused)]
2+
23 use filebuffer::FileBuffer;
4+use std::ops::Range;
35
46 /// Known multi-index file versions
57 #[derive(PartialEq, Eq, Ord, PartialOrd, Debug, Hash, Clone, Copy)]
@@ -25,6 +27,7 @@ pub struct File { · 19 unmodified lines
2527 num_chunks: u8,
2628 /// The amount of pack files contained within
2729 num_packs: u32,
30+ fanout: Range<git_chunk::file::Offset>,
2831 }
2932
3033 ///
@@ -41,9 +44,27 @@ pub mod access { · 10 unmodified lines
4144 }
4245 }
4346
47+mod chunk {
48+ pub mod pack_names {
49+ pub const ID: git_chunk::Kind = 0x504e414d; /* "PNAM" */
50+ }
51+ pub mod fanout {
52+ pub const ID: git_chunk::Kind = 0x4f494446; /* "OIDF" */
53+ }
54+ pub mod lookup {
55+ pub const ID: git_chunk::Kind = 0x4f49444c; /* "OIDL" */
56+ }
57+ pub mod offsets {
58+ pub const ID: git_chunk::Kind = 0x4f4f4646; /* "OOFF" */
59+ }
60+ pub mod large_offsets {
61+ pub const ID: git_chunk::Kind = 0x4c4f4646; /* "LOFF" */
62+ }
63+}
64+
4465 ///
4566 pub mod init {
46− use crate::multi_index::{File, Version};
67+ use crate::multi_index::{chunk, File, Version};
4768 use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
4869 use filebuffer::FileBuffer;
4970 use std::convert::{TryFrom, TryInto};
@@ -65,6 +86,8 @@ pub mod init { · 15 unmodified lines
6586 UnsupportedHashKind { kind: u8 },
6687 #[error(transparent)]
6788 ChunkFileDecode(#[from] git_chunk::file::decode::Error),
89+ #[error(transparent)]
90+ MissingChunk(#[from] git_chunk::file::index::not_found::Error),
6891 }
6992 }
7093 pub use error::Error;
@@ -128,12 +151,18 @@ pub mod init { · 57 unmodified lines
128151 };
129152
130153 let chunks = git_chunk::file::Index::from_bytes(&data, HEADER_LEN, num_chunks as u32)?;
154+ let pack_names = chunks.offset_by_kind(chunk::pack_names::ID, "PNAM")?;
155+ let fanout = chunks.offset_by_kind(chunk::fanout::ID, "OIDF")?;
156+ let lookup = chunks.offset_by_kind(chunk::lookup::ID, "OIDL")?;
157+ let offsets = chunks.offset_by_kind(chunk::offsets::ID, "OOFF")?;
158+ let large_offsets = chunks.offset_by_kind(chunk::large_offsets::ID, "LOFF").ok();
131159
132160 Ok(File {
133161 data,
134162 path: path.to_owned(),
135163 version,
136164 hash_kind,
165+ fanout,
137166 num_chunks,
138167 num_packs,
139168 })