use std::ffi::CString;
use std::{mem, ptr};
use crate::util::Binding;
use crate::{raw, Buf, Commit, DiffFindOptions, DiffOptions, Error, IntoCString};
use crate::{Diff, Oid, Signature};
pub struct Email {
buf: Buf,
}
pub struct EmailCreateOptions {
diff_options: DiffOptions,
diff_find_options: DiffFindOptions,
subject_prefix: Option<CString>,
raw: raw::git_email_create_options,
}
impl Default for EmailCreateOptions {
fn default() -> Self {
let default_options = raw::git_email_create_options {
version: raw::GIT_EMAIL_CREATE_OPTIONS_VERSION,
flags: raw::GIT_EMAIL_CREATE_DEFAULT as u32,
diff_opts: unsafe { mem::zeroed() },
diff_find_opts: unsafe { mem::zeroed() },
subject_prefix: ptr::null(),
start_number: 1,
reroll_number: 0,
};
let mut diff_options = DiffOptions::new();
diff_options.show_binary(true).context_lines(3);
Self {
diff_options,
diff_find_options: DiffFindOptions::new(),
subject_prefix: None,
raw: default_options,
}
}
}
impl EmailCreateOptions {
pub fn new() -> Self {
Self::default()
}
fn flag(&mut self, opt: raw::git_email_create_flags_t, val: bool) -> &mut Self {
let opt = opt as u32;
if val {
self.raw.flags |= opt;
} else {
self.raw.flags &= !opt;
}
self
}
pub fn omit_numbers(&mut self, omit: bool) -> &mut Self {
self.flag(raw::GIT_EMAIL_CREATE_OMIT_NUMBERS, omit)
}
pub fn always_number(&mut self, always: bool) -> &mut Self {
self.flag(raw::GIT_EMAIL_CREATE_ALWAYS_NUMBER, always)
}
pub fn ignore_renames(&mut self, ignore: bool) -> &mut Self {
self.flag(raw::GIT_EMAIL_CREATE_NO_RENAMES, ignore)
}
pub fn diff_options(&mut self) -> &mut DiffOptions {
&mut self.diff_options
}
pub fn diff_find_options(&mut self) -> &mut DiffFindOptions {
&mut self.diff_find_options
}
pub fn subject_prefix<T: IntoCString>(&mut self, t: T) -> &mut Self {
self.subject_prefix = Some(t.into_c_string().unwrap());
self
}
pub fn start_number(&mut self, number: usize) -> &mut Self {
self.raw.start_number = number;
self
}
pub fn reroll_number(&mut self, number: usize) -> &mut Self {
self.raw.reroll_number = number;
self
}
unsafe fn raw(&mut self) -> *const raw::git_email_create_options {
self.raw.subject_prefix = self
.subject_prefix
.as_ref()
.map(|s| s.as_ptr())
.unwrap_or(ptr::null());
self.raw.diff_opts = ptr::read(self.diff_options.raw());
self.raw.diff_find_opts = ptr::read(self.diff_find_options.raw());
&self.raw as *const _
}
}
impl Email {
pub fn as_slice(&self) -> &[u8] {
&self.buf
}
pub fn from_diff<T: IntoCString>(
diff: &Diff<'_>,
patch_idx: usize,
patch_count: usize,
commit_id: &Oid,
summary: T,
body: T,
author: &Signature<'_>,
opts: &mut EmailCreateOptions,
) -> Result<Self, Error> {
let buf = Buf::new();
let summary = summary.into_c_string()?;
let body = body.into_c_string()?;
unsafe {
try_call!(raw::git_email_create_from_diff(
buf.raw(),
Binding::raw(diff),
patch_idx,
patch_count,
Binding::raw(commit_id),
summary.as_ptr(),
body.as_ptr(),
Binding::raw(author),
opts.raw()
));
Ok(Self { buf })
}
}
pub fn from_commit(commit: &Commit<'_>, opts: &mut EmailCreateOptions) -> Result<Self, Error> {
let buf = Buf::new();
unsafe {
try_call!(raw::git_email_create_from_commit(
buf.raw(),
commit.raw(),
opts.raw()
));
Ok(Self { buf })
}
}
}