1 /*
2  *             Copyright Andrej Mitrovic 2013.
3  *  Distributed under the Boost Software License, Version 1.0.
4  *     (See accompanying file LICENSE_1_0.txt or copy at
5  *           http://www.boost.org/LICENSE_1_0.txt)
6  */
7 module git.trace;
8 
9 import std.conv;
10 
11 import deimos.git2.trace;
12 
13 import git.exception;
14 import git.util;
15 
16 /**
17     Available tracing levels.  When tracing is set to a particular level,
18     callers will be provided tracing at the given level and all lower levels.
19 */
20 enum TraceLevel
21 {
22     /** No tracing will be performed. */
23     none = GIT_TRACE_NONE,
24 
25     /** Severe errors that may impact the program's execution. */
26     fatal = GIT_TRACE_FATAL,
27 
28     /** Errors that do not impact the program's execution. */
29     error = GIT_TRACE_ERROR,
30 
31     /** Warnings that suggest abnormal data. */
32     warn = GIT_TRACE_WARN,
33 
34     /** Informational messages about program execution. */
35     info = GIT_TRACE_INFO,
36 
37     /** Detailed data that allows for debugging. */
38     debug_ = GIT_TRACE_DEBUG,
39 
40     /** Exceptionally detailed debugging data. */
41     trace = GIT_TRACE_TRACE
42 }
43 
44 /** The trace callback function and delegate types. */
45 alias TraceFunction = void function(TraceLevel level, in char[] msg);
46 
47 /// ditto
48 alias TraceDelegate = void delegate(TraceLevel level, in char[] msg);
49 
50 /**
51     Sets the git system tracing configuration to the specified level with the
52     specified callback.  When system events occur at a level equal to, or
53     lower than, the given level they will be reported to the given callback.
54 
55     $(BLUE Note:) If libgit2 is not built with tracing support calling this
56     function will throw a $(D GitException).
57 
58     Make sure $(B -DGIT_TRACE) is set when building libgit2
59     to enable tracing support, or look at the libgit2 build instructions.
60 */
61 void setGitTracer(TraceLevel level, TraceFunction callback)
62 {
63     setGitTracerImpl(level, callback);
64 }
65 
66 /// ditto
67 void setGitTracer(TraceLevel level, scope TraceDelegate callback)
68 {
69     setGitTracerImpl(level, callback);
70 }
71 
72 /// test callback function
73 unittest
74 {
75     static void tracer(TraceLevel level, in char[] msg)
76     {
77         import std.stdio;
78         stderr.writefln("Level(%s): %s", level, msg);
79     }
80 
81     try
82     {
83         setGitTracer(TraceLevel.trace, &tracer);
84     }
85     catch (GitException exc)
86     {
87         assert(exc.msg == _noTraceMsg, exc.msg);
88     }
89 }
90 
91 /// test callback delegate
92 unittest
93 {
94     struct S
95     {
96         size_t line = 1;
97 
98         void tracer(TraceLevel level, in char[] msg)
99         {
100             import std.stdio;
101             stderr.writefln("Level(%s): Line %s - %s", line++, level, msg);
102         }
103     }
104 
105     S s;
106 
107     try
108     {
109         setGitTracer(TraceLevel.trace, &s.tracer);
110     }
111     catch (GitException exc)
112     {
113         assert(exc.msg == _noTraceMsg, exc.msg);
114     }
115 }
116 
117 version(unittest)
118 {
119     enum _noTraceMsg = "Git error (GITERR_INVALID): This version of libgit2 was not built with tracing..";
120 }
121 
122 private void setGitTracerImpl(Callback)(TraceLevel level, Callback callback)
123     if (is(Callback == TraceFunction) || is(Callback == TraceDelegate))
124 {
125     struct Tracer
126     {
127         extern(C) void tracer(git_trace_level_t level, const(char)* msg)
128         {
129             callback(cast(TraceLevel)level, to!(const(char)[])(msg));
130         }
131 
132     private:
133         /// The currently active callback
134         static Callback callback;
135     }
136 
137     Tracer.callback = callback;
138     require(git_trace_set(cast(git_trace_level_t)level, &Tracer.tracer) == 0);
139 }