Skip to content

Commit 3dfec81

Browse files
committed
bare-bones loose object integrity check (#287)
1 parent a24307d commit 3dfec81

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

git-odb/src/store_impls/loose/verify.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#![allow(missing_docs)]
21
use crate::loose::Store;
2+
use crate::Write;
33

44
///
55
pub mod integrity {
@@ -14,21 +14,49 @@ pub mod integrity {
1414
id: git_hash::ObjectId,
1515
},
1616
#[error("{kind} object {expected} wasn't re-encoded without change - new hash is {actual}")]
17-
ObjectEncodeMismatch {
17+
ObjectHashMismatch {
1818
kind: git_object::Kind,
1919
actual: git_hash::ObjectId,
2020
expected: git_hash::ObjectId,
2121
},
22+
#[error("Objects were deleted during iteration - try again")]
23+
Retry,
2224
}
2325

26+
/// The outcome returned by [`verify_integrity()`][super::Store::verify_integrity()].
2427
pub struct Outcome {
2528
/// The amount of loose objects we checked.
2629
pub num_objects: usize,
2730
}
2831
}
2932

3033
impl Store {
34+
/// Check all loose objects for their integrity checking their hash matches the actual data and by decoding them fully.
3135
pub fn verify_integrity(&self) -> Result<integrity::Outcome, integrity::Error> {
32-
todo!()
36+
let mut buf = Vec::new();
37+
let mut num_objects = 0;
38+
let sink = crate::sink(self.object_hash);
39+
40+
for id in self.iter().filter_map(Result::ok) {
41+
let object = self
42+
.try_find(id, &mut buf)
43+
.map_err(|_| integrity::Error::Retry)?
44+
.ok_or(integrity::Error::Retry)?;
45+
let actual_id = sink.write_buf(object.kind, object.data).expect("sink never fails");
46+
if actual_id != id {
47+
return Err(integrity::Error::ObjectHashMismatch {
48+
kind: object.kind,
49+
actual: actual_id,
50+
expected: id,
51+
});
52+
}
53+
object.decode().map_err(|err| integrity::Error::ObjectDecode {
54+
source: err,
55+
kind: object.kind,
56+
id,
57+
})?;
58+
num_objects += 1;
59+
}
60+
Ok(integrity::Outcome { num_objects })
3361
}
3462
}

git-odb/tests/odb/store/loose.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,10 @@ pub fn locate_oid(id: git_hash::ObjectId, buf: &mut Vec<u8>) -> git_object::Data
3333
}
3434

3535
#[test]
36-
#[ignore]
3736
fn verify_integrity() {
3837
let db = ldb();
3938
let outcome = db.verify_integrity().unwrap();
40-
assert_eq!(outcome.num_objects, 42);
39+
assert_eq!(outcome.num_objects, 7);
4140
}
4241

4342
mod write {

0 commit comments

Comments
 (0)