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
17 use crate::file::Index;17 use crate::file::Index;
18 use std::ops::Range;18 use std::ops::Range;
19 19
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
20 /// An entry of a chunk file index45 /// An entry of a chunk file index
21 pub struct Entry {46 pub struct Entry {
22 /// The kind of the chunk file47 /// The kind of the chunk file
@@ -32,10 +57,15 @@ pub mod file { · 9 unmodified lines
32 pub const EMPTY_SIZE: usize = Index::ENTRY_SIZE;57 pub const EMPTY_SIZE: usize = Index::ENTRY_SIZE;
33 58
34 /// Find a chunk of `kind` and return its offset into the data if found59 /// 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> {
36 self.chunks65 self.chunks
37 .iter()66 .iter()
38 .find_map(|c| (c.kind == kind).then(|| c.offset.clone()))67 .find_map(|c| (c.kind == kind).then(|| c.offset.clone()))
68 .ok_or_else(|| not_found::Error { kind, name })
39 }69 }
40 }70 }
41 }71 }
git-pack/src/multi_index.rs+30−1
@@ -1,5 +1,7 @@
1#![allow(missing_docs, unused)]1#![allow(missing_docs, unused)]
2
2use filebuffer::FileBuffer;3use filebuffer::FileBuffer;
4use std::ops::Range;
3 5
4/// Known multi-index file versions6/// Known multi-index file versions
5#[derive(PartialEq, Eq, Ord, PartialOrd, Debug, Hash, Clone, Copy)]7#[derive(PartialEq, Eq, Ord, PartialOrd, Debug, Hash, Clone, Copy)]
@@ -25,6 +27,7 @@ pub struct File { · 19 unmodified lines
25 num_chunks: u8,27 num_chunks: u8,
26 /// The amount of pack files contained within28 /// The amount of pack files contained within
27 num_packs: u32,29 num_packs: u32,
30 fanout: Range<git_chunk::file::Offset>,
28}31}
29 32
30///33///
@@ -41,9 +44,27 @@ pub mod access { · 10 unmodified lines
41 }44 }
42}45}
43 46
47mod 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
44///65///
45pub mod init {66pub mod init {
46 use crate::multi_index::{File, Version};67 use crate::multi_index::{chunk, File, Version};
47 use byteorder::{BigEndian, ByteOrder, ReadBytesExt};68 use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
48 use filebuffer::FileBuffer;69 use filebuffer::FileBuffer;
49 use std::convert::{TryFrom, TryInto};70 use std::convert::{TryFrom, TryInto};
@@ -65,6 +86,8 @@ pub mod init { · 15 unmodified lines
65 UnsupportedHashKind { kind: u8 },86 UnsupportedHashKind { kind: u8 },
66 #[error(transparent)]87 #[error(transparent)]
67 ChunkFileDecode(#[from] git_chunk::file::decode::Error),88 ChunkFileDecode(#[from] git_chunk::file::decode::Error),
89 #[error(transparent)]
90 MissingChunk(#[from] git_chunk::file::index::not_found::Error),
68 }91 }
69 }92 }
70 pub use error::Error;93 pub use error::Error;
@@ -128,12 +151,18 @@ pub mod init { · 57 unmodified lines
128 };151 };
129 152
130 let chunks = git_chunk::file::Index::from_bytes(&data, HEADER_LEN, num_chunks as u32)?;153 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();
131 159
132 Ok(File {160 Ok(File {
133 data,161 data,
134 path: path.to_owned(),162 path: path.to_owned(),
135 version,163 version,
136 hash_kind,164 hash_kind,
165 fanout,
137 num_chunks,166 num_chunks,
138 num_packs,167 num_packs,
139 })168 })