Skip to content

Commit bb35c69

Browse files
committed
very first experimental support for multi-pack index verification (#279)
1 parent bf04644 commit bb35c69

File tree

9 files changed

+69
-45
lines changed

9 files changed

+69
-45
lines changed

git-odb/src/cache.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
use std::ops::{Deref, DerefMut};
2-
use std::{cell::RefCell, sync::Arc};
1+
use std::{
2+
cell::RefCell,
3+
ops::{Deref, DerefMut},
4+
sync::Arc,
5+
};
36

47
use crate::Cache;
58

git-odb/src/store_impls/dynamic/handle.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ pub(crate) mod index_lookup {
7171

7272
use git_hash::oid;
7373

74-
use crate::store::handle::IntraPackLookup;
75-
use crate::store::{handle, types};
74+
use crate::store::{handle, handle::IntraPackLookup, types};
7675

7776
pub(crate) struct Outcome<'a> {
7877
pub object_index: handle::IndexForObjectInPack,

git-pack/src/index/access.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ use std::mem::size_of;
22

33
use byteorder::{BigEndian, ByteOrder};
44

5-
use crate::index::EntryIndex;
65
use crate::{
76
data,
8-
index::{self, FAN_LEN},
7+
index::{self, EntryIndex, FAN_LEN},
98
};
109

1110
const N32_SIZE: usize = size_of::<u32>();

git-pack/src/multi_index/access.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ use std::path::{Path, PathBuf};
22

33
use byteorder::{BigEndian, ByteOrder};
44

5-
use crate::multi_index::EntryIndex;
65
use crate::{
76
data,
8-
multi_index::{File, PackIndex, Version},
7+
multi_index::{EntryIndex, File, PackIndex, Version},
98
};
109

1110
/// Represents an entry within a multi index file, effectively mapping object [`IDs`][git_hash::ObjectId] to pack data

git-pack/src/multi_index/verify.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
use crate::multi_index::File;
2-
use git_features::progress::Progress;
31
use std::sync::atomic::AtomicBool;
42

3+
use git_features::progress::Progress;
4+
5+
use crate::multi_index::File;
6+
57
///
68
pub mod integrity {
79
/// Returned by [`multi_index::File::verify_integrity()`][crate::multi_index::File::verify_integrity()].

git-pack/src/verify.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
use std::{path::Path, sync::atomic::AtomicBool};
2+
13
use git_features::progress::Progress;
2-
use std::path::Path;
3-
use std::sync::atomic::AtomicBool;
44

55
///
66
pub mod checksum {

git-pack/tests/pack/index.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
mod file {
22
const SHA1_SIZE: usize = git_hash::Kind::Sha1.len_in_bytes();
33

4+
use std::sync::atomic::AtomicBool;
5+
46
use git_object::{self as object};
57
use git_odb::pack;
6-
use std::sync::atomic::AtomicBool;
78

89
use crate::{
910
fixture_path, hex_to_id,

git-pack/tests/pack/multi_index.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use git_pack::multi_index::File;
21
use std::path::PathBuf;
32

3+
use git_pack::multi_index::File;
44
use git_testtools::hex_to_id;
55

66
fn multi_index() -> (File, PathBuf) {
@@ -52,10 +52,12 @@ fn access() {
5252
}
5353

5454
mod verify {
55-
use crate::pack::multi_index::multi_index;
55+
use std::sync::atomic::AtomicBool;
56+
5657
use common_macros::b_tree_map;
5758
use git_features::progress;
58-
use std::sync::atomic::AtomicBool;
59+
60+
use crate::pack::multi_index::multi_index;
5961

6062
#[test]
6163
fn checksum() {

gitoxide-core/src/pack/verify.rs

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use std::{io, path::Path, str::FromStr, sync::atomic::AtomicBool};
22

33
use anyhow::{anyhow, Context as AnyhowContext, Result};
44
use bytesize::ByteSize;
5+
use git_pack_for_configuration_only::index::traverse::Outcome;
56
use git_repository as git;
67
use git_repository::{
78
easy::object,
8-
hash::ObjectId,
99
odb,
1010
odb::{pack, pack::index},
1111
Progress,
@@ -113,19 +113,27 @@ pub fn pack_or_pack_index<W1, W2>(
113113
algorithm,
114114
should_interrupt,
115115
}: Context<'_, W1, W2>,
116-
) -> Result<(ObjectId, Option<index::traverse::Outcome>)>
116+
) -> Result<()>
117117
where
118118
W1: io::Write,
119119
W2: io::Write,
120120
{
121121
let path = path.as_ref();
122-
let ext = path.extension().and_then(|ext| ext.to_str()).ok_or_else(|| {
123-
anyhow!(
124-
"Cannot determine data type on path without extension '{}', expecting default extensions 'idx' and 'pack'",
125-
path.display()
126-
)
127-
})?;
122+
let ext = path.extension().and_then(|ext| ext.to_str()).unwrap_or("");
128123
let object_hash = git::hash::Kind::Sha1; // TODO: make it configurable via Context/CLI
124+
const CACHE_SIZE: usize = 64;
125+
let cache = || -> EitherCache<CACHE_SIZE> {
126+
if matches!(algorithm, Algorithm::LessMemory) {
127+
if output_statistics.is_some() {
128+
// turn off acceleration as we need to see entire chains all the time
129+
EitherCache::Left(pack::cache::Never)
130+
} else {
131+
EitherCache::Right(pack::cache::lru::StaticLinkedList::<CACHE_SIZE>::default())
132+
}
133+
} else {
134+
EitherCache::Left(pack::cache::Never)
135+
}
136+
};
129137
let res = match ext {
130138
"pack" => {
131139
let pack = odb::pack::data::File::at(path, object_hash).with_context(|| "Could not open pack file")?;
@@ -148,19 +156,6 @@ where
148156
e
149157
})
150158
.ok();
151-
const CACHE_SIZE: usize = 64;
152-
let cache = || -> EitherCache<CACHE_SIZE> {
153-
if matches!(algorithm, Algorithm::LessMemory) {
154-
if output_statistics.is_some() {
155-
// turn off acceleration as we need to see entire chains all the time
156-
EitherCache::Left(pack::cache::Never)
157-
} else {
158-
EitherCache::Right(pack::cache::lru::StaticLinkedList::<CACHE_SIZE>::default())
159-
}
160-
} else {
161-
EitherCache::Left(pack::cache::Never)
162-
}
163-
};
164159

165160
idx.verify_integrity(
166161
pack.as_ref().map(|p| git::odb::pack::index::verify::PackContext {
@@ -176,18 +171,42 @@ where
176171
.map(|o| (o.actual_index_checksum, o.pack_traverse_outcome))
177172
.with_context(|| "Verification failure")?
178173
}
174+
"" => {
175+
match path.file_name() {
176+
Some(file_name) if file_name == "multi-pack-index" => {
177+
let multi_index = git::odb::pack::multi_index::File::at(path)?;
178+
let res = multi_index.verify_integrity(mode, algorithm.into(), cache, thread_limit, progress, should_interrupt)?;
179+
for stats in res.pack_traverse_outcomes {
180+
output_outcome(&mut out, output_statistics, &stats)?;
181+
}
182+
return Ok(())
183+
},
184+
_ => return Err(anyhow!(
185+
"Cannot determine data type on path without extension '{}', expecting default extensions 'idx' and 'pack'",
186+
path.display()
187+
))
188+
}
189+
}
179190
ext => return Err(anyhow!("Unknown extension {:?}, expecting 'idx' or 'pack'", ext)),
180191
};
181192
if let Some(stats) = res.1.as_ref() {
182-
#[cfg_attr(not(feature = "serde1"), allow(clippy::single_match))]
183-
match output_statistics {
184-
Some(OutputFormat::Human) => drop(print_statistics(&mut out, stats)),
185-
#[cfg(feature = "serde1")]
186-
Some(OutputFormat::Json) => serde_json::to_writer_pretty(out, stats)?,
187-
_ => {}
188-
};
193+
output_outcome(&mut out, output_statistics, stats)?;
189194
}
190-
Ok(res)
195+
Ok(())
196+
}
197+
198+
fn output_outcome<W1>(mut out: &mut W1, output_statistics: Option<OutputFormat>, stats: &Outcome) -> anyhow::Result<()>
199+
where
200+
W1: io::Write,
201+
{
202+
#[cfg_attr(not(feature = "serde1"), allow(clippy::single_match))]
203+
match output_statistics {
204+
Some(OutputFormat::Human) => drop(print_statistics(&mut out, stats)),
205+
#[cfg(feature = "serde1")]
206+
Some(OutputFormat::Json) => serde_json::to_writer_pretty(out, stats)?,
207+
_ => {}
208+
};
209+
Ok(())
191210
}
192211

193212
fn print_statistics(out: &mut impl io::Write, stats: &index::traverse::Outcome) -> io::Result<()> {

0 commit comments

Comments
 (0)