diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index 383db6c37e..32c2af9f92 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -741,8 +741,9 @@ git_enum! { } } -pub type git_treewalk_cb = - Option c_int>; +pub type git_treewalk_inner_cb = + extern "C" fn(*const c_char, *const git_tree_entry, *mut c_void) -> c_int; +pub type git_treewalk_cb = Option; pub type git_treebuilder_filter_cb = Option c_int>; diff --git a/src/call.rs b/src/call.rs index a18f05da91..57aaa26dbd 100644 --- a/src/call.rs +++ b/src/call.rs @@ -116,6 +116,17 @@ mod impls { } } + impl Convert for crate::TreeWalkMode { + #[cfg(target_env = "msvc")] + fn convert(&self) -> raw::git_treewalk_mode { + *self as i32 + } + #[cfg(not(target_env = "msvc"))] + fn convert(&self) -> raw::git_treewalk_mode { + *self as u32 + } + } + impl Convert for Direction { fn convert(&self) -> raw::git_direction { match *self { diff --git a/src/tree.rs b/src/tree.rs index ae8fe3b4c5..a509852025 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -36,6 +36,7 @@ pub struct TreeIter<'tree> { /// A binary indicator of whether a tree walk should be performed in pre-order /// or post-order. +#[derive(Clone, Copy)] pub enum TreeWalkMode { /// Runs the traversal in pre-order. PreOrder = 0, @@ -60,17 +61,6 @@ impl Into for TreeWalkResult { } } -impl Into for TreeWalkMode { - #[cfg(target_env = "msvc")] - fn into(self) -> raw::git_treewalk_mode { - self as i32 - } - #[cfg(not(target_env = "msvc"))] - fn into(self) -> raw::git_treewalk_mode { - self as u32 - } -} - impl<'repo> Tree<'repo> { /// Get the id (SHA1) of a repository object pub fn id(&self) -> Oid { @@ -126,12 +116,12 @@ impl<'repo> Tree<'repo> { let mut data = TreeWalkCbData { callback: &mut callback, }; - raw::git_tree_walk( + try_call!(raw::git_tree_walk( self.raw(), - mode.into(), - Some(treewalk_cb::), - &mut data as *mut _ as *mut c_void, - ); + mode, + Some(treewalk_cb:: as raw::git_treewalk_inner_cb), + &mut data as *mut _ as *mut c_void + )); Ok(()) } } @@ -599,4 +589,18 @@ mod tests { .unwrap(); assert_eq!(ct, 8); } + + #[test] + fn tree_walk_error() { + let (td, repo) = crate::test::repo_init(); + + setup_repo(&td, &repo); + + let head = repo.head().unwrap(); + let target = head.target().unwrap(); + let commit = repo.find_commit(target).unwrap(); + let tree = repo.find_tree(commit.tree_id()).unwrap(); + + assert!(tree.walk(TreeWalkMode::PreOrder, |_, _| { -1 }).is_err()); + } }