1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
use gix_features::fs;
use crate::store_impls::loose;
/// Returned by [`loose::Store::iter()`]
pub type Error = gix_features::fs::walkdir::Error;
impl loose::Iter {
fn path_to_id(
&self,
res: Result<fs::walkdir::DirEntry, fs::walkdir::Error>,
) -> Option<Result<gix_hash::ObjectId, Error>> {
use std::path::Component::Normal;
match res {
Ok(e) => {
let p = e.path();
let mut ci = p.components();
let (c2, c1) = (ci.next_back(), ci.next_back());
if let (Some(Normal(c1)), Some(Normal(c2))) = (c1, c2) {
if c1.len() == 2 && c2.len() == self.hash_hex_len - 2 {
if let (Some(c1), Some(c2)) = (c1.to_str(), c2.to_str()) {
let mut buf = gix_hash::Kind::hex_buf();
{
let (first_byte, rest) = buf[..self.hash_hex_len].split_at_mut(2);
first_byte.copy_from_slice(c1.as_bytes());
rest.copy_from_slice(c2.as_bytes());
}
if let Ok(b) = gix_hash::ObjectId::from_hex(&buf[..self.hash_hex_len]) {
return Some(Ok(b));
}
}
}
}
}
Err(err) => return Some(Err(err)),
};
None
}
}
impl Iterator for loose::Iter {
type Item = Result<gix_hash::ObjectId, Error>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(res) = self.inner.next() {
if let Some(res) = self.path_to_id(res) {
return Some(res);
}
}
None
}
}
/// Iteration and traversal
impl loose::Store {
/// Return an iterator over all objects contained in the database.
///
/// The [`Id`][gix_hash::ObjectId]s returned by the iterator can typically be used in the [`locate(…)`][loose::Store::try_find()] method.
/// _Note_ that the result is not sorted or stable, thus ordering can change between runs.
///
/// # Notes
///
/// [`loose::Iter`] is used instead of `impl Iterator<…>` to allow using this iterator in struct fields, as is currently
/// needed if iterators need to be implemented by hand in the absence of generators.
pub fn iter(&self) -> loose::Iter {
loose::Iter {
inner: fs::walkdir_new(
&self.path,
fs::walkdir::Parallelism::ThreadPoolPerTraversal {
thread_name: "gix_odb::loose::Store::iter: fs-walk",
},
false,
)
.min_depth(2)
.max_depth(3)
.follow_links(false)
.into_iter(),
hash_hex_len: self.object_hash.len_in_hex(),
}
}
}