1 use std
::path
::{Path, PathBuf}
;
3 use gix_features
::fs
::walkdir
::DirEntryIter
;
4 use gix_object
::bstr
::ByteSlice
;
6 use crate::{file::iter::LooseThenPacked, store_impl::file, BString, FullName}
;
8 /// An iterator over all valid loose reference paths as seen from a particular base directory.
9 pub(in crate::store_impl
::file
) struct SortedLoosePaths
{
10 pub(crate) base
: PathBuf
,
11 filename_prefix
: Option
<BString
>,
12 file_walk
: Option
<DirEntryIter
>,
15 impl SortedLoosePaths
{
16 pub fn at(path
: &Path
, base
: PathBuf
, filename_prefix
: Option
<BString
>) -> Self {
20 file_walk
: path
.is_dir().then(|| {
21 // serial iteration as we expect most refs in packed-refs anyway.
22 gix_features
::fs
::walkdir_sorted_new(path
, gix_features
::fs
::walkdir
::Parallelism
::Serial
).into_iter()
28 impl Iterator
for SortedLoosePaths
{
29 type Item
= std
::io
::Result
<(PathBuf
, FullName
)>;
31 fn next(&mut self) -> Option
<Self::Item
> {
32 for entry
in self.file_walk
.as_mut()?
.by_ref() {
35 if !entry
.file_type().is_file() {
38 let full_path
= entry
.path().to_owned();
39 if let Some((prefix
, name
)) = self
42 .and_then(|prefix
| full_path
.file_name().map(|name
| (prefix
, name
)))
44 match gix_path
::os_str_into_bstr(name
) {
46 if !name
.starts_with(prefix
) {
50 Err(_
) => continue, // TODO: silently skipping ill-formed UTF-8 on windows - maybe this can be better?
53 let full_name
= full_path
54 .strip_prefix(&self.base
)
55 .expect("prefix-stripping cannot fail as prefix is our root");
56 let full_name
= match gix_path
::try_into_bstr(full_name
) {
58 let name
= gix_path
::to_unix_separators_on_windows(name
);
61 Err(_
) => continue, // TODO: silently skipping ill-formed UTF-8 on windows here, maybe there are better ways?
64 if gix_validate
::reference
::name_partial(full_name
.as_bstr()).is_ok() {
65 let name
= FullName(full_name
);
66 return Some(Ok((full_path
, name
)));
71 Err(err
) => return Some(Err(err
.into_io_error().expect("no symlink related errors"))),
79 /// Return an iterator over all loose references, notably not including any packed ones, in lexical order.
80 /// Each of the references may fail to parse and the iterator will not stop if parsing fails, allowing the caller
81 /// to see all files that look like references whether valid or not.
83 /// Reference files that do not constitute valid names will be silently ignored.
84 pub fn loose_iter(&self) -> std
::io
::Result
<LooseThenPacked
<'_
, '_
>> {
85 self.iter_packed(None
)
88 /// Return an iterator over all loose references that start with the given `prefix`.
90 /// Otherwise it's similar to [`loose_iter()`][file::Store::loose_iter()].
91 pub fn loose_iter_prefixed(&self, prefix
: &Path
) -> std
::io
::Result
<LooseThenPacked
<'_
, '_
>> {
92 self.iter_prefixed_packed(prefix
, None
)