//! git_tag_foreach support //! see original: use crate::{panic, raw, util::Binding, Oid}; use libc::{c_char, c_int}; use raw::git_oid; use std::ffi::{c_void, CStr}; /// boxed callback type pub(crate) type TagForeachCB<'a> = Box bool + 'a>; /// helper type to be able to pass callback to payload pub(crate) struct TagForeachData<'a> { /// callback pub(crate) cb: TagForeachCB<'a>, } /// c callback forwarding to rust callback inside `TagForeachData` /// see original: pub(crate) extern "C" fn tag_foreach_cb( name: *const c_char, oid: *mut git_oid, payload: *mut c_void, ) -> c_int { panic::wrap(|| unsafe { let id: Oid = Binding::from_raw(oid as *const _); let name = CStr::from_ptr(name); let name = name.to_bytes(); let payload = &mut *(payload as *mut TagForeachData<'_>); let cb = &mut payload.cb; let res = cb(id, name); if res { 0 } else { -1 } }) .unwrap_or(-1) } #[cfg(test)] mod tests { #[test] fn smoke() { let (_td, repo) = crate::test::repo_init(); let head = repo.head().unwrap(); let id = head.target().unwrap(); assert!(repo.find_tag(id).is_err()); let obj = repo.find_object(id, None).unwrap(); let sig = repo.signature().unwrap(); let tag_id = repo.tag("foo", &obj, &sig, "msg", false).unwrap(); let mut tags = Vec::new(); repo.tag_foreach(|id, name| { tags.push((id, String::from_utf8(name.into()).unwrap())); true }) .unwrap(); assert_eq!(tags[0].0, tag_id); assert_eq!(tags[0].1, "refs/tags/foo"); } }