summaryrefslogtreecommitdiffstats
path: root/vendor/gix-odb/src/store_impls/loose/iter.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix-odb/src/store_impls/loose/iter.rs')
-rw-r--r--vendor/gix-odb/src/store_impls/loose/iter.rs81
1 files changed, 81 insertions, 0 deletions
diff --git a/vendor/gix-odb/src/store_impls/loose/iter.rs b/vendor/gix-odb/src/store_impls/loose/iter.rs
new file mode 100644
index 000000000..5904aeb12
--- /dev/null
+++ b/vendor/gix-odb/src/store_impls/loose/iter.rs
@@ -0,0 +1,81 @@
+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",
+ },
+ )
+ .min_depth(2)
+ .max_depth(3)
+ .follow_links(false)
+ .into_iter(),
+ hash_hex_len: self.object_hash.len_in_hex(),
+ }
+ }
+}