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