#include "clar_libgit2.h"
#include "clar_libgit2_trace.h"
#include "clar_libgit2_timer.h"
#include "trace.h"
struct method {
const char *name;
void (*git_trace_cb)(git_trace_level_t level, const char *msg);
void (*close)(void);
};
#if defined(GIT_TRACE)
static void _git_trace_cb__printf(git_trace_level_t level, const char *msg)
{
GIT_UNUSED(level);
printf("%s\n", msg);
}
#if defined(GIT_WIN32)
static void _git_trace_cb__debug(git_trace_level_t level, const char *msg)
{
GIT_UNUSED(level);
OutputDebugString(msg);
OutputDebugString("\n");
printf("%s\n", msg);
}
#else
#define _git_trace_cb__debug _git_trace_cb__printf
#endif
static void _trace_printf_close(void)
{
fflush(stdout);
}
#define _trace_debug_close _trace_printf_close
static struct method s_methods[] = {
{ "printf", _git_trace_cb__printf, _trace_printf_close },
{ "debug", _git_trace_cb__debug, _trace_debug_close },
{0},
};
static int s_trace_loaded = 0;
static int s_trace_level = GIT_TRACE_NONE;
static struct method *s_trace_method = NULL;
static int set_method(const char *name)
{
int k;
if (!name || !*name)
name = "printf";
for (k=0; (s_methods[k].name); k++) {
if (strcmp(name, s_methods[k].name) == 0) {
s_trace_method = &s_methods[k];
return 0;
}
}
fprintf(stderr, "Unknown CLAR_TRACE_METHOD: '%s'\n", name);
return -1;
}
static void _load_trace_params(void)
{
char *sz_level;
char *sz_method;
s_trace_loaded = 1;
sz_level = cl_getenv("CLAR_TRACE_LEVEL");
if (!sz_level || !*sz_level) {
s_trace_level = GIT_TRACE_NONE;
s_trace_method = NULL;
return;
}
s_trace_level = GIT_TRACE_TRACE;
sz_method = cl_getenv("CLAR_TRACE_METHOD");
if (set_method(sz_method) < 0)
set_method(NULL);
}
#define HR "================================================================"
static cl_perf_timer s_timer_run = CL_PERF_TIMER_INIT;
static cl_perf_timer s_timer_test = CL_PERF_TIMER_INIT;
void _cl_trace_cb__event_handler(
cl_trace_event ev,
const char *suite_name,
const char *test_name,
void *payload)
{
GIT_UNUSED(payload);
switch (ev) {
case CL_TRACE__SUITE_BEGIN:
git_trace(GIT_TRACE_TRACE, "\n\n%s\n%s: Begin Suite", HR, suite_name);
break;
case CL_TRACE__SUITE_END:
git_trace(GIT_TRACE_TRACE, "\n\n%s: End Suite\n%s", suite_name, HR);
break;
case CL_TRACE__TEST__BEGIN:
git_trace(GIT_TRACE_TRACE, "\n%s::%s: Begin Test", suite_name, test_name);
cl_perf_timer__init(&s_timer_test);
cl_perf_timer__start(&s_timer_test);
break;
case CL_TRACE__TEST__END:
cl_perf_timer__stop(&s_timer_test);
git_trace(GIT_TRACE_TRACE, "%s::%s: End Test (%.3f %.3f)", suite_name, test_name,
cl_perf_timer__last(&s_timer_run),
cl_perf_timer__last(&s_timer_test));
break;
case CL_TRACE__TEST__RUN_BEGIN:
git_trace(GIT_TRACE_TRACE, "%s::%s: Begin Run", suite_name, test_name);
cl_perf_timer__init(&s_timer_run);
cl_perf_timer__start(&s_timer_run);
break;
case CL_TRACE__TEST__RUN_END:
cl_perf_timer__stop(&s_timer_run);
git_trace(GIT_TRACE_TRACE, "%s::%s: End Run", suite_name, test_name);
break;
case CL_TRACE__TEST__LONGJMP:
cl_perf_timer__stop(&s_timer_run);
git_trace(GIT_TRACE_TRACE, "%s::%s: Aborted", suite_name, test_name);
break;
default:
break;
}
}
#endif
void cl_global_trace_register(void)
{
#if defined(GIT_TRACE)
if (!s_trace_loaded)
_load_trace_params();
if (s_trace_level == GIT_TRACE_NONE)
return;
if (s_trace_method == NULL)
return;
if (s_trace_method->git_trace_cb == NULL)
return;
git_trace_set(s_trace_level, s_trace_method->git_trace_cb);
cl_trace_register(_cl_trace_cb__event_handler, NULL);
#endif
}
void cl_global_trace_disable(void)
{
#if defined(GIT_TRACE)
cl_trace_register(NULL, NULL);
git_trace_set(GIT_TRACE_NONE, NULL);
if (s_trace_method && s_trace_method->close)
s_trace_method->close();
#endif
}