Skip to content

Commit 26cb0b5

Browse files
author
Stephan Dilly
authored
Safe tracing (rust-lang#732)
* safe wrapper for tracing * try leaky pointer casting approach * get rid of box * fmt
1 parent 611fbf8 commit 26cb0b5

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ pub use crate::status::{StatusEntry, StatusIter, StatusOptions, StatusShow, Stat
130130
pub use crate::submodule::{Submodule, SubmoduleUpdateOptions};
131131
pub use crate::tag::Tag;
132132
pub use crate::time::{IndexTime, Time};
133+
pub use crate::tracing::{trace_set, TraceLevel};
133134
pub use crate::transaction::Transaction;
134135
pub use crate::tree::{Tree, TreeEntry, TreeIter, TreeWalkMode, TreeWalkResult};
135136
pub use crate::treebuilder::TreeBuilder;
@@ -690,6 +691,7 @@ mod submodule;
690691
mod tag;
691692
mod tagforeach;
692693
mod time;
694+
mod tracing;
693695
mod transaction;
694696
mod tree;
695697
mod treebuilder;

src/tracing.rs

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use std::sync::atomic::{AtomicUsize, Ordering};
2+
3+
use libc::c_char;
4+
5+
use crate::{panic, raw, util::Binding};
6+
7+
/// Available tracing levels. When tracing is set to a particular level,
8+
/// callers will be provided tracing at the given level and all lower levels.
9+
#[derive(Copy, Clone, Debug)]
10+
pub enum TraceLevel {
11+
/// No tracing will be performed.
12+
None,
13+
14+
/// Severe errors that may impact the program's execution
15+
Fatal,
16+
17+
/// Errors that do not impact the program's execution
18+
Error,
19+
20+
/// Warnings that suggest abnormal data
21+
Warn,
22+
23+
/// Informational messages about program execution
24+
Info,
25+
26+
/// Detailed data that allows for debugging
27+
Debug,
28+
29+
/// Exceptionally detailed debugging data
30+
Trace,
31+
}
32+
33+
impl Binding for TraceLevel {
34+
type Raw = raw::git_trace_level_t;
35+
unsafe fn from_raw(raw: raw::git_trace_level_t) -> Self {
36+
match raw {
37+
raw::GIT_TRACE_NONE => Self::None,
38+
raw::GIT_TRACE_FATAL => Self::Fatal,
39+
raw::GIT_TRACE_ERROR => Self::Error,
40+
raw::GIT_TRACE_WARN => Self::Warn,
41+
raw::GIT_TRACE_INFO => Self::Info,
42+
raw::GIT_TRACE_DEBUG => Self::Debug,
43+
raw::GIT_TRACE_TRACE => Self::Trace,
44+
_ => panic!("Unknown git trace level"),
45+
}
46+
}
47+
fn raw(&self) -> raw::git_trace_level_t {
48+
match *self {
49+
Self::None => raw::GIT_TRACE_NONE,
50+
Self::Fatal => raw::GIT_TRACE_FATAL,
51+
Self::Error => raw::GIT_TRACE_ERROR,
52+
Self::Warn => raw::GIT_TRACE_WARN,
53+
Self::Info => raw::GIT_TRACE_INFO,
54+
Self::Debug => raw::GIT_TRACE_DEBUG,
55+
Self::Trace => raw::GIT_TRACE_TRACE,
56+
}
57+
}
58+
}
59+
60+
pub type TracingCb = fn(TraceLevel, &str);
61+
62+
static CALLBACK: AtomicUsize = AtomicUsize::new(0);
63+
64+
///
65+
pub fn trace_set(level: TraceLevel, cb: TracingCb) -> bool {
66+
CALLBACK.store(cb as usize, Ordering::SeqCst);
67+
68+
unsafe {
69+
raw::git_trace_set(level.raw(), Some(tracing_cb_c));
70+
}
71+
72+
return true;
73+
}
74+
75+
extern "C" fn tracing_cb_c(level: raw::git_trace_level_t, msg: *const c_char) {
76+
let cb = CALLBACK.load(Ordering::SeqCst);
77+
panic::wrap(|| unsafe {
78+
let cb: TracingCb = std::mem::transmute(cb);
79+
let msg = std::ffi::CStr::from_ptr(msg).to_str().unwrap();
80+
cb(Binding::from_raw(level), msg);
81+
});
82+
}

0 commit comments

Comments
 (0)