| #![macro_use] |
| use libc; |
| |
| use crate::Error; |
| |
| macro_rules! call { |
| (raw::$p:ident ($($e:expr),*)) => ( |
| raw::$p($(crate::call::convert(&$e)),*) |
| ) |
| } |
| |
| macro_rules! try_call { |
| (raw::$p:ident ($($e:expr),*)) => ({ |
| match crate::call::c_try(raw::$p($(crate::call::convert(&$e)),*)) { |
| Ok(o) => o, |
| Err(e) => { crate::panic::check(); return Err(e) } |
| } |
| }) |
| } |
| |
| macro_rules! try_call_iter { |
| ($($f:tt)*) => { |
| match call!($($f)*) { |
| 0 => {} |
| raw::GIT_ITEROVER => return None, |
| e => return Some(Err(crate::call::last_error(e))) |
| } |
| } |
| } |
| |
| #[doc(hidden)] |
| pub trait Convert<T> { |
| fn convert(&self) -> T; |
| } |
| |
| pub fn convert<T, U: Convert<T>>(u: &U) -> T { |
| u.convert() |
| } |
| |
| pub fn c_try(ret: libc::c_int) -> Result<libc::c_int, Error> { |
| match ret { |
| n if n < 0 => Err(last_error(n)), |
| n => Ok(n), |
| } |
| } |
| |
| pub fn last_error(code: libc::c_int) -> Error { |
| // nowadays this unwrap is safe as `Error::last_error` always returns |
| // `Some`. |
| Error::last_error(code).unwrap() |
| } |
| |
| mod impls { |
| use std::ffi::CString; |
| use std::ptr; |
| |
| use libc; |
| |
| use crate::call::Convert; |
| use crate::{raw, BranchType, ConfigLevel, Direction, ObjectType, ResetType}; |
| use crate::{ |
| AutotagOption, DiffFormat, FetchPrune, FileFavor, SubmoduleIgnore, SubmoduleUpdate, |
| }; |
| |
| impl<T: Copy> Convert<T> for T { |
| fn convert(&self) -> T { |
| *self |
| } |
| } |
| |
| impl Convert<libc::c_int> for bool { |
| fn convert(&self) -> libc::c_int { |
| *self as libc::c_int |
| } |
| } |
| impl<'a, T> Convert<*const T> for &'a T { |
| fn convert(&self) -> *const T { |
| *self as *const T |
| } |
| } |
| impl<'a, T> Convert<*mut T> for &'a mut T { |
| fn convert(&self) -> *mut T { |
| &**self as *const T as *mut T |
| } |
| } |
| impl<T> Convert<*const T> for *mut T { |
| fn convert(&self) -> *const T { |
| *self as *const T |
| } |
| } |
| |
| impl Convert<*const libc::c_char> for CString { |
| fn convert(&self) -> *const libc::c_char { |
| self.as_ptr() |
| } |
| } |
| |
| impl<T, U: Convert<*const T>> Convert<*const T> for Option<U> { |
| fn convert(&self) -> *const T { |
| self.as_ref().map(|s| s.convert()).unwrap_or(ptr::null()) |
| } |
| } |
| |
| impl<T, U: Convert<*mut T>> Convert<*mut T> for Option<U> { |
| fn convert(&self) -> *mut T { |
| self.as_ref() |
| .map(|s| s.convert()) |
| .unwrap_or(ptr::null_mut()) |
| } |
| } |
| |
| impl Convert<raw::git_reset_t> for ResetType { |
| fn convert(&self) -> raw::git_reset_t { |
| match *self { |
| ResetType::Soft => raw::GIT_RESET_SOFT, |
| ResetType::Hard => raw::GIT_RESET_HARD, |
| ResetType::Mixed => raw::GIT_RESET_MIXED, |
| } |
| } |
| } |
| |
| impl Convert<raw::git_direction> for Direction { |
| fn convert(&self) -> raw::git_direction { |
| match *self { |
| Direction::Push => raw::GIT_DIRECTION_PUSH, |
| Direction::Fetch => raw::GIT_DIRECTION_FETCH, |
| } |
| } |
| } |
| |
| impl Convert<raw::git_object_t> for ObjectType { |
| fn convert(&self) -> raw::git_object_t { |
| match *self { |
| ObjectType::Any => raw::GIT_OBJECT_ANY, |
| ObjectType::Commit => raw::GIT_OBJECT_COMMIT, |
| ObjectType::Tree => raw::GIT_OBJECT_TREE, |
| ObjectType::Blob => raw::GIT_OBJECT_BLOB, |
| ObjectType::Tag => raw::GIT_OBJECT_TAG, |
| } |
| } |
| } |
| |
| impl Convert<raw::git_object_t> for Option<ObjectType> { |
| fn convert(&self) -> raw::git_object_t { |
| self.unwrap_or(ObjectType::Any).convert() |
| } |
| } |
| |
| impl Convert<raw::git_branch_t> for BranchType { |
| fn convert(&self) -> raw::git_branch_t { |
| match *self { |
| BranchType::Remote => raw::GIT_BRANCH_REMOTE, |
| BranchType::Local => raw::GIT_BRANCH_LOCAL, |
| } |
| } |
| } |
| |
| impl Convert<raw::git_branch_t> for Option<BranchType> { |
| fn convert(&self) -> raw::git_branch_t { |
| self.map(|s| s.convert()).unwrap_or(raw::GIT_BRANCH_ALL) |
| } |
| } |
| |
| impl Convert<raw::git_config_level_t> for ConfigLevel { |
| fn convert(&self) -> raw::git_config_level_t { |
| match *self { |
| ConfigLevel::ProgramData => raw::GIT_CONFIG_LEVEL_PROGRAMDATA, |
| ConfigLevel::System => raw::GIT_CONFIG_LEVEL_SYSTEM, |
| ConfigLevel::XDG => raw::GIT_CONFIG_LEVEL_XDG, |
| ConfigLevel::Global => raw::GIT_CONFIG_LEVEL_GLOBAL, |
| ConfigLevel::Local => raw::GIT_CONFIG_LEVEL_LOCAL, |
| ConfigLevel::App => raw::GIT_CONFIG_LEVEL_APP, |
| ConfigLevel::Highest => raw::GIT_CONFIG_HIGHEST_LEVEL, |
| } |
| } |
| } |
| |
| impl Convert<raw::git_diff_format_t> for DiffFormat { |
| fn convert(&self) -> raw::git_diff_format_t { |
| match *self { |
| DiffFormat::Patch => raw::GIT_DIFF_FORMAT_PATCH, |
| DiffFormat::PatchHeader => raw::GIT_DIFF_FORMAT_PATCH_HEADER, |
| DiffFormat::Raw => raw::GIT_DIFF_FORMAT_RAW, |
| DiffFormat::NameOnly => raw::GIT_DIFF_FORMAT_NAME_ONLY, |
| DiffFormat::NameStatus => raw::GIT_DIFF_FORMAT_NAME_STATUS, |
| DiffFormat::PatchId => raw::GIT_DIFF_FORMAT_PATCH_ID, |
| } |
| } |
| } |
| |
| impl Convert<raw::git_merge_file_favor_t> for FileFavor { |
| fn convert(&self) -> raw::git_merge_file_favor_t { |
| match *self { |
| FileFavor::Normal => raw::GIT_MERGE_FILE_FAVOR_NORMAL, |
| FileFavor::Ours => raw::GIT_MERGE_FILE_FAVOR_OURS, |
| FileFavor::Theirs => raw::GIT_MERGE_FILE_FAVOR_THEIRS, |
| FileFavor::Union => raw::GIT_MERGE_FILE_FAVOR_UNION, |
| } |
| } |
| } |
| |
| impl Convert<raw::git_submodule_ignore_t> for SubmoduleIgnore { |
| fn convert(&self) -> raw::git_submodule_ignore_t { |
| match *self { |
| SubmoduleIgnore::Unspecified => raw::GIT_SUBMODULE_IGNORE_UNSPECIFIED, |
| SubmoduleIgnore::None => raw::GIT_SUBMODULE_IGNORE_NONE, |
| SubmoduleIgnore::Untracked => raw::GIT_SUBMODULE_IGNORE_UNTRACKED, |
| SubmoduleIgnore::Dirty => raw::GIT_SUBMODULE_IGNORE_DIRTY, |
| SubmoduleIgnore::All => raw::GIT_SUBMODULE_IGNORE_ALL, |
| } |
| } |
| } |
| |
| impl Convert<raw::git_submodule_update_t> for SubmoduleUpdate { |
| fn convert(&self) -> raw::git_submodule_update_t { |
| match *self { |
| SubmoduleUpdate::Checkout => raw::GIT_SUBMODULE_UPDATE_CHECKOUT, |
| SubmoduleUpdate::Rebase => raw::GIT_SUBMODULE_UPDATE_REBASE, |
| SubmoduleUpdate::Merge => raw::GIT_SUBMODULE_UPDATE_MERGE, |
| SubmoduleUpdate::None => raw::GIT_SUBMODULE_UPDATE_NONE, |
| SubmoduleUpdate::Default => raw::GIT_SUBMODULE_UPDATE_DEFAULT, |
| } |
| } |
| } |
| |
| impl Convert<raw::git_remote_autotag_option_t> for AutotagOption { |
| fn convert(&self) -> raw::git_remote_autotag_option_t { |
| match *self { |
| AutotagOption::Unspecified => raw::GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED, |
| AutotagOption::None => raw::GIT_REMOTE_DOWNLOAD_TAGS_NONE, |
| AutotagOption::Auto => raw::GIT_REMOTE_DOWNLOAD_TAGS_AUTO, |
| AutotagOption::All => raw::GIT_REMOTE_DOWNLOAD_TAGS_ALL, |
| } |
| } |
| } |
| |
| impl Convert<raw::git_fetch_prune_t> for FetchPrune { |
| fn convert(&self) -> raw::git_fetch_prune_t { |
| match *self { |
| FetchPrune::Unspecified => raw::GIT_FETCH_PRUNE_UNSPECIFIED, |
| FetchPrune::On => raw::GIT_FETCH_PRUNE, |
| FetchPrune::Off => raw::GIT_FETCH_NO_PRUNE, |
| } |
| } |
| } |
| } |