This repository has no description
3.4 kB
121 lines
1//! Git stores all of its data as _Objects_, which are data along with a hash over all data. Storing objects efficiently
2//! is what git packs are concerned about.
3//!
4//! Packs consist of [data files][data::File] and [index files][index::File]. The latter can be generated from a data file
5//! and make accessing objects within a pack feasible.
6//!
7//! A [Bundle] conveniently combines a data pack alongside its index to allow [finding][Find] objects or verifying the pack.
8//! Objects returned by `.find(…)` are [objects][gix_object::Data] which know their pack location in order to speed up
9//! various common operations like creating new packs from existing ones.
10//!
11//! When traversing all objects in a pack, a _delta tree acceleration structure_ can be built from pack data or an index
12//! in order to decompress packs in parallel and without any waste.
13//! ## Feature Flags
14#![cfg_attr(
15 all(doc, feature = "document-features"),
16 doc = ::document_features::document_features!()
17)]
18#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]
19#![deny(unsafe_code)]
20
21use std::{borrow::Cow, ops::Deref, path::Path};
22
23/// The default in-memory backing store for index and multi-index files.
24#[allow(missing_docs)]
25pub struct MMap(Vec<u8>);
26
27impl MMap {
28 #[allow(missing_docs)]
29 pub fn map(file: &std::fs::File) -> std::io::Result<Self> {
30 use std::os::unix::fs::FileExt;
31 let len = usize::try_from(file.metadata()?.len())
32 .map_err(|_| std::io::Error::other("file too large to load into memory"))?;
33 let mut bytes = vec![0u8; len];
34 file.read_exact_at(&mut bytes, 0)?;
35 Ok(MMap(bytes))
36 }
37}
38
39impl Deref for MMap {
40 type Target = [u8];
41
42 fn deref(&self) -> &[u8] {
43 &self.0
44 }
45}
46
47/// A byte-oriented backing store for pack data and indices.
48pub trait FileData: Deref<Target = [u8]> {}
49
50impl<T> FileData for T where T: Deref<Target = [u8]> {}
51
52///
53pub mod bundle;
54/// A bundle of pack data and the corresponding pack index
55pub struct Bundle {
56 /// The pack file corresponding to `index`
57 pub pack: data::File,
58 /// The index file corresponding to `pack`
59 pub index: index::File,
60}
61
62///
63pub mod find;
64
65///
66pub mod cache;
67///
68pub mod data;
69
70mod find_traits;
71pub use find_traits::{Find, FindExt};
72
73///
74pub mod index;
75///
76pub mod multi_index;
77
78///
79pub mod verify;
80
81mod mmap {
82 use std::path::Path;
83
84 pub fn read_only(path: &Path) -> std::io::Result<super::MMap> {
85 Ok(super::MMap(std::fs::read(path)?))
86 }
87}
88
89/// Return a display-friendly name for pack- or index-related progress messages.
90///
91/// Prefer the file name, but fall back to the full path for paths without a terminal component.
92fn source_name(path: &Path) -> Cow<'_, str> {
93 if path.as_os_str().is_empty() {
94 Cow::Borrowed("<memory>")
95 } else if let Some(name) = path.file_name() {
96 name.to_string_lossy()
97 } else {
98 path.as_os_str().to_string_lossy()
99 }
100}
101
102#[inline]
103fn read_u32(b: &[u8]) -> u32 {
104 u32::from_be_bytes(b.try_into().unwrap())
105}
106
107#[inline]
108fn read_u64(b: &[u8]) -> u64 {
109 u64::from_be_bytes(b.try_into().unwrap())
110}
111
112fn exact_vec<T>(capacity: usize) -> Vec<T> {
113 let mut v = Vec::new();
114 v.reserve_exact(capacity);
115 v
116}
117
118#[inline]
119fn fan_is_monotonically_increasing(fan: &[u32]) -> bool {
120 !fan.windows(2).any(|window| window[0] > window[1])
121}