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
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct References<'a> {
inner: Vec<git2::References<'a>>,
}
impl<'a> References<'a> {
pub fn new(refs: impl IntoIterator<Item = git2::References<'a>>) -> Self {
Self {
inner: refs.into_iter().collect(),
}
}
pub fn from_globs(
repo: &'a git2::Repository,
globs: impl IntoIterator<Item = impl AsRef<str>>,
) -> Result<Self, git2::Error> {
let globs = globs.into_iter();
let mut iters = globs
.size_hint()
.1
.map(Vec::with_capacity)
.unwrap_or_else(Vec::new);
for glob in globs {
let iter = repo.references_glob(glob.as_ref())?;
iters.push(iter);
}
Ok(Self::new(iters))
}
pub fn names<'b>(&'b mut self) -> ReferenceNames<'a, 'b> {
ReferenceNames {
inner: self.inner.iter_mut().map(|refs| refs.names()).collect(),
}
}
pub fn peeled(self) -> impl Iterator<Item = (String, git2::Oid)> + 'a {
self.filter_map(|reference| {
reference.ok().and_then(|head| {
head.name().and_then(|name| {
head.target()
.map(|target| (name.to_owned(), target.to_owned()))
})
})
})
}
}
impl<'a> Iterator for References<'a> {
type Item = Result<git2::Reference<'a>, git2::Error>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.pop().and_then(|mut iter| match iter.next() {
None => self.next(),
Some(item) => {
self.inner.push(iter);
Some(item)
},
})
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ReferenceNames<'repo, 'references> {
inner: Vec<git2::ReferenceNames<'repo, 'references>>,
}
impl<'a, 'b> Iterator for ReferenceNames<'a, 'b> {
type Item = Result<&'b str, git2::Error>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.pop().and_then(|mut iter| match iter.next() {
None => self.next(),
Some(item) => {
self.inner.push(iter);
Some(item)
},
})
}
}