gix_ref/store/file/loose/
iter.rs1use std::path::{Path, PathBuf};
2
3use gix_features::fs::walkdir::DirEntryIter;
4use gix_object::bstr::ByteSlice;
5use gix_path::RelativePath;
6
7use crate::{file::iter::LooseThenPacked, store_impl::file, BString, FullName};
8
9pub(in crate::store_impl::file) struct SortedLoosePaths {
11 pub(crate) base: PathBuf,
12 prefix: Option<BString>,
14 file_walk: Option<DirEntryIter>,
15}
16
17impl SortedLoosePaths {
18 pub fn at(path: &Path, base: PathBuf, prefix: Option<BString>, precompose_unicode: bool) -> Self {
19 SortedLoosePaths {
20 base,
21 prefix,
22 file_walk: path.is_dir().then(|| {
23 gix_features::fs::walkdir_sorted_new(
25 path,
26 gix_features::fs::walkdir::Parallelism::Serial,
27 precompose_unicode,
28 )
29 .into_iter()
30 }),
31 }
32 }
33}
34
35impl Iterator for SortedLoosePaths {
36 type Item = std::io::Result<(PathBuf, FullName)>;
37
38 fn next(&mut self) -> Option<Self::Item> {
39 for entry in self.file_walk.as_mut()?.by_ref() {
40 match entry {
41 Ok(entry) => {
42 if !entry.file_type().is_ok_and(|ft| ft.is_file()) {
43 continue;
44 }
45 let full_path = entry.path().into_owned();
46 let full_name = full_path
47 .strip_prefix(&self.base)
48 .expect("prefix-stripping cannot fail as base is within our root");
49 let Ok(full_name) = gix_path::try_into_bstr(full_name)
50 .map(|name| gix_path::to_unix_separators_on_windows(name).into_owned())
51 else {
52 continue;
53 };
54 if let Some(prefix) = &self.prefix {
55 if !full_name.starts_with(prefix) {
56 continue;
57 }
58 }
59 if gix_validate::reference::name_partial(full_name.as_bstr()).is_ok() {
60 let name = FullName(full_name);
61 return Some(Ok((full_path, name)));
62 } else {
63 continue;
64 }
65 }
66 Err(err) => return Some(Err(err.into_io_error().expect("no symlink related errors"))),
67 }
68 }
69 None
70 }
71}
72
73impl file::Store {
74 pub fn loose_iter(&self) -> std::io::Result<LooseThenPacked<'_, '_>> {
80 self.iter_packed(None)
81 }
82
83 pub fn loose_iter_prefixed(&self, prefix: &RelativePath) -> std::io::Result<LooseThenPacked<'_, '_>> {
93 self.iter_prefixed_packed(prefix, None)
94 }
95}