Skip to content

Commit

Permalink
Safe tracing (#732)
Browse files Browse the repository at this point in the history
* safe wrapper for tracing

* try leaky pointer casting approach

* get rid of box

* fmt
  • Loading branch information
Stephan Dilly authored Jul 27, 2021
1 parent 611fbf8 commit 26cb0b5
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ pub use crate::status::{StatusEntry, StatusIter, StatusOptions, StatusShow, Stat
pub use crate::submodule::{Submodule, SubmoduleUpdateOptions};
pub use crate::tag::Tag;
pub use crate::time::{IndexTime, Time};
pub use crate::tracing::{trace_set, TraceLevel};
pub use crate::transaction::Transaction;
pub use crate::tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult};
pub use crate::treebuilder::TreeBuilder;
Expand Down Expand Up @@ -690,6 +691,7 @@ mod submodule;
mod tag;
mod tagforeach;
mod time;
mod tracing;
mod transaction;
mod tree;
mod treebuilder;
Expand Down
82 changes: 82 additions & 0 deletions src/tracing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use std::sync::atomic::{AtomicUsize, Ordering};

use libc::c_char;

use crate::{panic, raw, util::Binding};

/// Available tracing levels. When tracing is set to a particular level,
/// callers will be provided tracing at the given level and all lower levels.
#[derive(Copy, Clone, Debug)]
pub enum TraceLevel {
/// No tracing will be performed.
None,

/// Severe errors that may impact the program's execution
Fatal,

/// Errors that do not impact the program's execution
Error,

/// Warnings that suggest abnormal data
Warn,

/// Informational messages about program execution
Info,

/// Detailed data that allows for debugging
Debug,

/// Exceptionally detailed debugging data
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_str().unwrap();
cb(Binding::from_raw(level), msg);
});
}

0 comments on commit 26cb0b5

Please sign in to comment.