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
use std::marker;
use std::str;
use {raw, signature, Signature, Oid, Repository};
use util::Binding;
pub struct Note<'repo> {
raw: *mut raw::git_note,
_marker: marker::PhantomData<&'repo Repository>,
}
pub struct Notes<'repo> {
raw: *mut raw::git_note_iterator,
_marker: marker::PhantomData<&'repo Repository>,
}
impl<'repo> Note<'repo> {
pub fn author(&self) -> Signature {
unsafe {
signature::from_raw_const(self, raw::git_note_author(&*self.raw))
}
}
pub fn committer(&self) -> Signature {
unsafe {
signature::from_raw_const(self, raw::git_note_committer(&*self.raw))
}
}
pub fn message_bytes(&self) -> &[u8] {
unsafe { ::opt_bytes(self, raw::git_note_message(&*self.raw)).unwrap() }
}
pub fn message(&self) -> Option<&str> {
str::from_utf8(self.message_bytes()).ok()
}
pub fn id(&self) -> Oid {
unsafe { Binding::from_raw(raw::git_note_id(&*self.raw)) }
}
}
impl<'repo> Binding for Note<'repo> {
type Raw = *mut raw::git_note;
unsafe fn from_raw(raw: *mut raw::git_note) -> Note<'repo> {
Note { raw: raw, _marker: marker::PhantomData, }
}
fn raw(&self) -> *mut raw::git_note { self.raw }
}
impl<'repo> Drop for Note<'repo> {
fn drop(&mut self) {
unsafe { raw::git_note_free(self.raw); }
}
}
impl<'repo> Binding for Notes<'repo> {
type Raw = *mut raw::git_note_iterator;
unsafe fn from_raw(raw: *mut raw::git_note_iterator) -> Notes<'repo> {
Notes { raw: raw, _marker: marker::PhantomData, }
}
fn raw(&self) -> *mut raw::git_note_iterator { self.raw }
}
impl<'repo> Iterator for Notes<'repo> {
type Item = (Oid, Oid);
fn next(&mut self) -> Option<(Oid, Oid)> {
let mut note_id = raw::git_oid { id: [0; raw::GIT_OID_RAWSZ] };
let mut annotated_id = note_id;
unsafe {
match raw::git_note_next(&mut note_id, &mut annotated_id, self.raw) {
0 => Some((Binding::from_raw(¬e_id as *const _),
Binding::from_raw(&annotated_id as *const _))),
_ => None,
}
}
}
}
impl<'repo> Drop for Notes<'repo> {
fn drop(&mut self) {
unsafe { raw::git_note_iterator_free(self.raw); }
}
}
#[cfg(test)]
mod tests {
#[test]
fn smoke() {
let (_td, repo) = ::test::repo_init();
assert!(repo.notes(None).is_err());
let sig = repo.signature().unwrap();
let head = repo.head().unwrap().target().unwrap();
let note = repo.note(&sig, &sig, None, head, "foo", false).unwrap();
assert_eq!(repo.notes(None).unwrap().count(), 1);
let note_obj = repo.find_note(None, head).unwrap();
assert_eq!(note_obj.id(), note);
assert_eq!(note_obj.message(), Some("foo"));
let (a, b) = repo.notes(None).unwrap().next().unwrap();
assert_eq!(a, note);
assert_eq!(b, head);
assert_eq!(repo.note_default_ref().unwrap(), "refs/notes/commits");
assert_eq!(sig.name(), note_obj.author().name());
assert_eq!(sig.name(), note_obj.committer().name());
assert!(sig.when() == note_obj.committer().when());
}
}