use std::sync::atomic::{AtomicUsize, Ordering};
use libc::c_char;
use crate::{panic, raw, util::Binding};
#[derive(Copy, Clone, Debug)]
pub enum TraceLevel {
None,
Fatal,
Error,
Warn,
Info,
Debug,
Trace,
}
impl Binding for TraceLevel {
type Raw = raw::git_trace_level_t;
unsafe fn from_raw(raw: raw::git_trace_level_t) -> Self {
match raw {
raw::GIT_TRACE_NONE => Self::None,
raw::GIT_TRACE_FATAL => Self::Fatal,
raw::GIT_TRACE_ERROR => Self::Error,
raw::GIT_TRACE_WARN => Self::Warn,
raw::GIT_TRACE_INFO => Self::Info,
raw::GIT_TRACE_DEBUG => Self::Debug,
raw::GIT_TRACE_TRACE => Self::Trace,
_ => panic!("Unknown git trace level"),
}
}
fn raw(&self) -> raw::git_trace_level_t {
match *self {
Self::None => raw::GIT_TRACE_NONE,
Self::Fatal => raw::GIT_TRACE_FATAL,
Self::Error => raw::GIT_TRACE_ERROR,
Self::Warn => raw::GIT_TRACE_WARN,
Self::Info => raw::GIT_TRACE_INFO,
Self::Debug => raw::GIT_TRACE_DEBUG,
Self::Trace => raw::GIT_TRACE_TRACE,
}
}
}
pub type TracingCb = fn(TraceLevel, &str);
static CALLBACK: AtomicUsize = AtomicUsize::new(0);
pub fn trace_set(level: TraceLevel, cb: TracingCb) -> bool {
CALLBACK.store(cb as usize, Ordering::SeqCst);
unsafe {
raw::git_trace_set(level.raw(), Some(tracing_cb_c));
}
return true;
}
extern "C" fn tracing_cb_c(level: raw::git_trace_level_t, msg: *const c_char) {
let cb = CALLBACK.load(Ordering::SeqCst);
panic::wrap(|| unsafe {
let cb: TracingCb = std::mem::transmute(cb);
let msg = std::ffi::CStr::from_ptr(msg).to_string_lossy();
cb(Binding::from_raw(level), msg.as_ref());
});
}