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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use std::{
cell::Ref,
ops::{Deref, DerefMut},
path::Path,
};
use git_odb::Find;
use git_ref::file::ReferenceExt;
use crate::easy;
#[must_use = "Iterators should be obtained from this iterator platform"]
pub struct Platform<'r, A>
where
A: easy::Access + Sized,
{
pub(crate) repo: A::RepoRef,
pub(crate) packed_refs: Ref<'r, easy::reference::packed::ModifieablePackedRefsBuffer>,
pub(crate) access: &'r A,
}
pub struct Iter<'r, A> {
inner: git_ref::file::iter::LooseThenPacked<'r, 'r>,
packed_refs: Option<&'r git_ref::packed::Buffer>,
peel: bool,
access: &'r A,
}
impl<'r, A> Platform<'r, A>
where
A: easy::Access + Sized,
{
pub fn all(&self) -> Result<Iter<'_, A>, init::Error> {
let repo = self.repo.deref();
Ok(Iter {
inner: repo.refs.iter(self.packed_refs.buffer.as_ref())?,
packed_refs: self.packed_refs.buffer.as_ref(),
peel: false,
access: self.access,
})
}
pub fn prefixed(&self, prefix: impl AsRef<Path>) -> Result<Iter<'_, A>, init::Error> {
let repo = self.repo.deref();
Ok(Iter {
inner: repo.refs.iter_prefixed(self.packed_refs.buffer.as_ref(), prefix)?,
packed_refs: self.packed_refs.buffer.as_ref(),
peel: false,
access: self.access,
})
}
}
impl<'r, A> Iter<'r, A> {
pub fn peeled(mut self) -> Self {
self.peel = true;
self
}
}
impl<'r, A> Iterator for Iter<'r, A>
where
A: easy::Access + Sized,
{
type Item = Result<easy::Reference<'r, A>, Box<dyn std::error::Error + Send + Sync + 'static>>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|res| {
res.map_err(|err| Box::new(err) as Box<dyn std::error::Error + Send + Sync + 'static>)
.and_then(|mut r| {
if self.peel {
let repo = self.access.repo()?;
let state = self.access.state();
let mut pack_cache = state.try_borrow_mut_pack_cache()?;
r.peel_to_id_in_place(&repo.refs, self.packed_refs, |oid, buf| {
repo.odb
.try_find(oid, buf, pack_cache.deref_mut())
.map(|po| po.map(|o| (o.kind, o.data)))
})
.map_err(|err| Box::new(err) as Box<dyn std::error::Error + Send + Sync + 'static>)
.map(|_| r)
} else {
Ok(r)
}
})
.map(|r| easy::Reference::from_ref(r, self.access))
})
}
}
pub mod init {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
Io(#[from] std::io::Error),
}
}
mod error {
use crate::easy;
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
PackedRefsOpen(#[from] git_ref::packed::buffer::open::Error),
#[error("BUG: Part of interior state could not be borrowed.")]
BorrowState(#[from] easy::borrow::state::Error),
#[error("BUG: The repository could not be borrowed")]
BorrowRepo(#[from] easy::borrow::repo::Error),
}
impl From<easy::reference::packed::Error> for Error {
fn from(err: easy::reference::packed::Error) -> Self {
match err {
easy::reference::packed::Error::PackedRefsOpen(err) => Error::PackedRefsOpen(err),
easy::reference::packed::Error::BorrowState(err) => Error::BorrowState(err),
}
}
}
}
pub use error::Error;