1use std::ffi::CString;
2use std::ptr;
3
4use crate::util::Binding;
5use crate::{raw, Error, Signature};
6
7pub struct Mailmap {
11 raw: *mut raw::git_mailmap,
12}
13
14impl Binding for Mailmap {
15 type Raw = *mut raw::git_mailmap;
16
17 unsafe fn from_raw(ptr: *mut raw::git_mailmap) -> Mailmap {
18 Mailmap { raw: ptr }
19 }
20
21 fn raw(&self) -> *mut raw::git_mailmap {
22 self.raw
23 }
24}
25
26impl Drop for Mailmap {
27 fn drop(&mut self) {
28 unsafe {
29 raw::git_mailmap_free(self.raw);
30 }
31 }
32}
33
34impl Mailmap {
35 pub fn new() -> Result<Mailmap, Error> {
37 crate::init();
38 let mut ret = ptr::null_mut();
39 unsafe {
40 try_call!(raw::git_mailmap_new(&mut ret));
41 Ok(Binding::from_raw(ret))
42 }
43 }
44
45 pub fn from_buffer(buf: &str) -> Result<Mailmap, Error> {
47 crate::init();
48 let mut ret = ptr::null_mut();
49 let len = buf.len();
50 let buf = CString::new(buf)?;
51 unsafe {
52 try_call!(raw::git_mailmap_from_buffer(&mut ret, buf, len));
53 Ok(Binding::from_raw(ret))
54 }
55 }
56
57 pub fn add_entry(
59 &mut self,
60 real_name: Option<&str>,
61 real_email: Option<&str>,
62 replace_name: Option<&str>,
63 replace_email: &str,
64 ) -> Result<(), Error> {
65 let real_name = crate::opt_cstr(real_name)?;
66 let real_email = crate::opt_cstr(real_email)?;
67 let replace_name = crate::opt_cstr(replace_name)?;
68 let replace_email = CString::new(replace_email)?;
69 unsafe {
70 try_call!(raw::git_mailmap_add_entry(
71 self.raw,
72 real_name,
73 real_email,
74 replace_name,
75 replace_email
76 ));
77 Ok(())
78 }
79 }
80
81 pub fn resolve_signature(&self, sig: &Signature<'_>) -> Result<Signature<'static>, Error> {
83 let mut ret = ptr::null_mut();
84 unsafe {
85 try_call!(raw::git_mailmap_resolve_signature(
86 &mut ret,
87 &*self.raw,
88 sig.raw()
89 ));
90 Ok(Binding::from_raw(ret))
91 }
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn smoke() {
101 let sig_name = "name";
102 let sig_email = "email";
103 let sig = t!(Signature::now(sig_name, sig_email));
104
105 let mut mm = t!(Mailmap::new());
106
107 let mailmapped_sig = t!(mm.resolve_signature(&sig));
108 assert_eq!(mailmapped_sig.name(), Some(sig_name));
109 assert_eq!(mailmapped_sig.email(), Some(sig_email));
110
111 t!(mm.add_entry(None, None, None, sig_email));
112 t!(mm.add_entry(
113 Some("real name"),
114 Some("real@email"),
115 Some(sig_name),
116 sig_email,
117 ));
118
119 let mailmapped_sig = t!(mm.resolve_signature(&sig));
120 assert_eq!(mailmapped_sig.name(), Some("real name"));
121 assert_eq!(mailmapped_sig.email(), Some("real@email"));
122 }
123
124 #[test]
125 fn from_buffer() {
126 let buf = "<prøper@emæil> <email>";
127 let mm = t!(Mailmap::from_buffer(&buf));
128
129 let sig = t!(Signature::now("name", "email"));
130 let mailmapped_sig = t!(mm.resolve_signature(&sig));
131 assert_eq!(mailmapped_sig.name(), Some("name"));
132 assert_eq!(mailmapped_sig.email(), Some("prøper@emæil"));
133 }
134}