1 #![macro_use]
2 use libc;
3
4 use crate::Error;
5
6 macro_rules! call {
7 (raw::$p:ident ($($e:expr),*)) => (
8 raw::$p($(crate::call::convert(&$e)),*)
9 )
10 }
11
12 macro_rules! try_call {
13 (raw::$p:ident ($($e:expr),*)) => ({
14 match crate::call::c_try(raw::$p($(crate::call::convert(&$e)),*)) {
15 Ok(o) => o,
16 Err(e) => { crate::panic::check(); return Err(e) }
17 }
18 })
19 }
20
21 macro_rules! try_call_iter {
22 ($($f:tt)*) => {
23 match call!($($f)*) {
24 0 => {}
25 raw::GIT_ITEROVER => return None,
26 e => return Some(Err(crate::call::last_error(e)))
27 }
28 }
29 }
30
31 #[doc(hidden)]
32 pub trait Convert<T> {
convert(&self) -> T33 fn convert(&self) -> T;
34 }
35
convert<T, U: Convert<T>>(u: &U) -> T36 pub fn convert<T, U: Convert<T>>(u: &U) -> T {
37 u.convert()
38 }
39
c_try(ret: libc::c_int) -> Result<libc::c_int, Error>40 pub fn c_try(ret: libc::c_int) -> Result<libc::c_int, Error> {
41 match ret {
42 n if n < 0 => Err(last_error(n)),
43 n => Ok(n),
44 }
45 }
46
last_error(code: libc::c_int) -> Error47 pub fn last_error(code: libc::c_int) -> Error {
48 // nowadays this unwrap is safe as `Error::last_error` always returns
49 // `Some`.
50 Error::last_error(code).unwrap()
51 }
52
53 mod impls {
54 use std::ffi::CString;
55 use std::ptr;
56
57 use libc;
58
59 use crate::call::Convert;
60 use crate::{raw, BranchType, ConfigLevel, Direction, ObjectType, ResetType};
61 use crate::{AutotagOption, DiffFormat, FetchPrune, FileFavor, SubmoduleIgnore};
62
63 impl<T: Copy> Convert<T> for T {
convert(&self) -> T64 fn convert(&self) -> T {
65 *self
66 }
67 }
68
69 impl Convert<libc::c_int> for bool {
convert(&self) -> libc::c_int70 fn convert(&self) -> libc::c_int {
71 *self as libc::c_int
72 }
73 }
74 impl<'a, T> Convert<*const T> for &'a T {
convert(&self) -> *const T75 fn convert(&self) -> *const T {
76 *self as *const T
77 }
78 }
79 impl<'a, T> Convert<*mut T> for &'a mut T {
convert(&self) -> *mut T80 fn convert(&self) -> *mut T {
81 &**self as *const T as *mut T
82 }
83 }
84 impl<T> Convert<*const T> for *mut T {
convert(&self) -> *const T85 fn convert(&self) -> *const T {
86 *self as *const T
87 }
88 }
89
90 impl Convert<*const libc::c_char> for CString {
convert(&self) -> *const libc::c_char91 fn convert(&self) -> *const libc::c_char {
92 self.as_ptr()
93 }
94 }
95
96 impl<T, U: Convert<*const T>> Convert<*const T> for Option<U> {
convert(&self) -> *const T97 fn convert(&self) -> *const T {
98 self.as_ref().map(|s| s.convert()).unwrap_or(ptr::null())
99 }
100 }
101
102 impl<T, U: Convert<*mut T>> Convert<*mut T> for Option<U> {
convert(&self) -> *mut T103 fn convert(&self) -> *mut T {
104 self.as_ref()
105 .map(|s| s.convert())
106 .unwrap_or(ptr::null_mut())
107 }
108 }
109
110 impl Convert<raw::git_reset_t> for ResetType {
convert(&self) -> raw::git_reset_t111 fn convert(&self) -> raw::git_reset_t {
112 match *self {
113 ResetType::Soft => raw::GIT_RESET_SOFT,
114 ResetType::Hard => raw::GIT_RESET_HARD,
115 ResetType::Mixed => raw::GIT_RESET_MIXED,
116 }
117 }
118 }
119
120 impl Convert<raw::git_direction> for Direction {
convert(&self) -> raw::git_direction121 fn convert(&self) -> raw::git_direction {
122 match *self {
123 Direction::Push => raw::GIT_DIRECTION_PUSH,
124 Direction::Fetch => raw::GIT_DIRECTION_FETCH,
125 }
126 }
127 }
128
129 impl Convert<raw::git_object_t> for ObjectType {
convert(&self) -> raw::git_object_t130 fn convert(&self) -> raw::git_object_t {
131 match *self {
132 ObjectType::Any => raw::GIT_OBJECT_ANY,
133 ObjectType::Commit => raw::GIT_OBJECT_COMMIT,
134 ObjectType::Tree => raw::GIT_OBJECT_TREE,
135 ObjectType::Blob => raw::GIT_OBJECT_BLOB,
136 ObjectType::Tag => raw::GIT_OBJECT_TAG,
137 }
138 }
139 }
140
141 impl Convert<raw::git_object_t> for Option<ObjectType> {
convert(&self) -> raw::git_object_t142 fn convert(&self) -> raw::git_object_t {
143 self.unwrap_or(ObjectType::Any).convert()
144 }
145 }
146
147 impl Convert<raw::git_branch_t> for BranchType {
convert(&self) -> raw::git_branch_t148 fn convert(&self) -> raw::git_branch_t {
149 match *self {
150 BranchType::Remote => raw::GIT_BRANCH_REMOTE,
151 BranchType::Local => raw::GIT_BRANCH_LOCAL,
152 }
153 }
154 }
155
156 impl Convert<raw::git_branch_t> for Option<BranchType> {
convert(&self) -> raw::git_branch_t157 fn convert(&self) -> raw::git_branch_t {
158 self.map(|s| s.convert()).unwrap_or(raw::GIT_BRANCH_ALL)
159 }
160 }
161
162 impl Convert<raw::git_config_level_t> for ConfigLevel {
convert(&self) -> raw::git_config_level_t163 fn convert(&self) -> raw::git_config_level_t {
164 match *self {
165 ConfigLevel::ProgramData => raw::GIT_CONFIG_LEVEL_PROGRAMDATA,
166 ConfigLevel::System => raw::GIT_CONFIG_LEVEL_SYSTEM,
167 ConfigLevel::XDG => raw::GIT_CONFIG_LEVEL_XDG,
168 ConfigLevel::Global => raw::GIT_CONFIG_LEVEL_GLOBAL,
169 ConfigLevel::Local => raw::GIT_CONFIG_LEVEL_LOCAL,
170 ConfigLevel::App => raw::GIT_CONFIG_LEVEL_APP,
171 ConfigLevel::Highest => raw::GIT_CONFIG_HIGHEST_LEVEL,
172 }
173 }
174 }
175
176 impl Convert<raw::git_diff_format_t> for DiffFormat {
convert(&self) -> raw::git_diff_format_t177 fn convert(&self) -> raw::git_diff_format_t {
178 match *self {
179 DiffFormat::Patch => raw::GIT_DIFF_FORMAT_PATCH,
180 DiffFormat::PatchHeader => raw::GIT_DIFF_FORMAT_PATCH_HEADER,
181 DiffFormat::Raw => raw::GIT_DIFF_FORMAT_RAW,
182 DiffFormat::NameOnly => raw::GIT_DIFF_FORMAT_NAME_ONLY,
183 DiffFormat::NameStatus => raw::GIT_DIFF_FORMAT_NAME_STATUS,
184 DiffFormat::PatchId => raw::GIT_DIFF_FORMAT_PATCH_ID,
185 }
186 }
187 }
188
189 impl Convert<raw::git_merge_file_favor_t> for FileFavor {
convert(&self) -> raw::git_merge_file_favor_t190 fn convert(&self) -> raw::git_merge_file_favor_t {
191 match *self {
192 FileFavor::Normal => raw::GIT_MERGE_FILE_FAVOR_NORMAL,
193 FileFavor::Ours => raw::GIT_MERGE_FILE_FAVOR_OURS,
194 FileFavor::Theirs => raw::GIT_MERGE_FILE_FAVOR_THEIRS,
195 FileFavor::Union => raw::GIT_MERGE_FILE_FAVOR_UNION,
196 }
197 }
198 }
199
200 impl Convert<raw::git_submodule_ignore_t> for SubmoduleIgnore {
convert(&self) -> raw::git_submodule_ignore_t201 fn convert(&self) -> raw::git_submodule_ignore_t {
202 match *self {
203 SubmoduleIgnore::Unspecified => raw::GIT_SUBMODULE_IGNORE_UNSPECIFIED,
204 SubmoduleIgnore::None => raw::GIT_SUBMODULE_IGNORE_NONE,
205 SubmoduleIgnore::Untracked => raw::GIT_SUBMODULE_IGNORE_UNTRACKED,
206 SubmoduleIgnore::Dirty => raw::GIT_SUBMODULE_IGNORE_DIRTY,
207 SubmoduleIgnore::All => raw::GIT_SUBMODULE_IGNORE_ALL,
208 }
209 }
210 }
211
212 impl Convert<raw::git_remote_autotag_option_t> for AutotagOption {
convert(&self) -> raw::git_remote_autotag_option_t213 fn convert(&self) -> raw::git_remote_autotag_option_t {
214 match *self {
215 AutotagOption::Unspecified => raw::GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED,
216 AutotagOption::None => raw::GIT_REMOTE_DOWNLOAD_TAGS_NONE,
217 AutotagOption::Auto => raw::GIT_REMOTE_DOWNLOAD_TAGS_AUTO,
218 AutotagOption::All => raw::GIT_REMOTE_DOWNLOAD_TAGS_ALL,
219 }
220 }
221 }
222
223 impl Convert<raw::git_fetch_prune_t> for FetchPrune {
convert(&self) -> raw::git_fetch_prune_t224 fn convert(&self) -> raw::git_fetch_prune_t {
225 match *self {
226 FetchPrune::Unspecified => raw::GIT_FETCH_PRUNE_UNSPECIFIED,
227 FetchPrune::On => raw::GIT_FETCH_PRUNE,
228 FetchPrune::Off => raw::GIT_FETCH_NO_PRUNE,
229 }
230 }
231 }
232 }
233