Commit 6f83a781 by Vicent Martí

Merge pull request #1403 from ethomson/tracing

Optional tracing back to consumers
parents 33abaad8 b5ec5430
...@@ -22,6 +22,7 @@ OPTION( BUILD_CLAR "Build Tests using the Clar suite" ON ) ...@@ -22,6 +22,7 @@ OPTION( BUILD_CLAR "Build Tests using the Clar suite" ON )
OPTION( BUILD_EXAMPLES "Build library usage example apps" OFF ) OPTION( BUILD_EXAMPLES "Build library usage example apps" OFF )
OPTION( TAGS "Generate tags" OFF ) OPTION( TAGS "Generate tags" OFF )
OPTION( PROFILE "Generate profiling information" OFF ) OPTION( PROFILE "Generate profiling information" OFF )
OPTION( ENABLE_TRACE "Enables tracing support" OFF )
IF(MSVC) IF(MSVC)
# This option is only availalbe when building with MSVC. By default, # This option is only availalbe when building with MSVC. By default,
# libgit2 is build using the stdcall calling convention, as that's what # libgit2 is build using the stdcall calling convention, as that's what
...@@ -105,6 +106,11 @@ ELSE() ...@@ -105,6 +106,11 @@ ELSE()
FILE(GLOB SRC_SHA1 src/hash/hash_generic.c) FILE(GLOB SRC_SHA1 src/hash/hash_generic.c)
ENDIF() ENDIF()
# Enable tracing
IF (ENABLE_TRACE STREQUAL "ON")
ADD_DEFINITIONS(-DGIT_TRACE)
ENDIF()
# Include POSIX regex when it is required # Include POSIX regex when it is required
IF(WIN32 OR AMIGA) IF(WIN32 OR AMIGA)
INCLUDE_DIRECTORIES(deps/regex) INCLUDE_DIRECTORIES(deps/regex)
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_trace_h__
#define INCLUDE_git_trace_h__
#include "common.h"
#include "types.h"
/**
* @file git2/trace.h
* @brief Git tracing configuration routines
* @defgroup git_trace Git tracing configuration routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Available tracing levels. When tracing is set to a particular level,
* callers will be provided tracing at the given level and all lower levels.
*/
typedef enum {
/** No tracing will be performed. */
GIT_TRACE_NONE = 0,
/** Severe errors that may impact the program's execution */
GIT_TRACE_FATAL = 1,
/** Errors that do not impact the program's execution */
GIT_TRACE_ERROR = 2,
/** Warnings that suggest abnormal data */
GIT_TRACE_WARN = 3,
/** Informational messages about program execution */
GIT_TRACE_INFO = 4,
/** Detailed data that allows for debugging */
GIT_TRACE_DEBUG = 5,
/** Exceptionally detailed debugging data */
GIT_TRACE_TRACE = 6
} git_trace_level_t;
/**
* An instance for a tracing function
*/
typedef void (*git_trace_callback)(git_trace_level_t level, const char *msg);
/**
* Sets the system tracing configuration to the specified level with the
* specified callback. When system events occur at a level equal to, or
* lower than, the given level they will be reported to the given callback.
*
* @param level Level to set tracing to
* @param cb Function to call with trace data
* @return 0 or an error code
*/
GIT_EXTERN(int) git_trace_set(git_trace_level_t level, git_trace_callback cb);
/** @} */
GIT_END_DECL
#endif
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "buffer.h"
#include "common.h"
#include "global.h"
#include "trace.h"
#include "git2/trace.h"
#ifdef GIT_TRACE
struct git_trace_data git_trace__data = {0};
#endif
int git_trace_set(git_trace_level_t level, git_trace_callback callback)
{
#ifdef GIT_TRACE
assert(level == 0 || callback != NULL);
git_trace__data.level = level;
git_trace__data.callback = callback;
GIT_MEMORY_BARRIER;
return 0;
#else
GIT_UNUSED(level);
GIT_UNUSED(callback);
giterr_set(GITERR_INVALID,
"This version of libgit2 was not built with tracing.");
return -1;
#endif
}
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_trace_h__
#define INCLUDE_trace_h__
#include <stdarg.h>
#include <git2/trace.h>
#include "buffer.h"
#ifdef GIT_TRACE
struct git_trace_data {
git_trace_level_t level;
git_trace_callback callback;
};
extern struct git_trace_data git_trace__data;
GIT_INLINE(void) git_trace__write_fmt(
git_trace_level_t level,
const char *fmt, ...)
{
git_trace_callback callback = git_trace__data.callback;
git_buf message = GIT_BUF_INIT;
va_list ap;
va_start(ap, fmt);
git_buf_vprintf(&message, fmt, ap);
va_end(ap);
callback(level, git_buf_cstr(&message));
git_buf_free(&message);
}
#define git_trace_level() (git_trace__data.level)
#define git_trace(l, ...) { \
if (git_trace__data.level >= l && \
git_trace__data.callback != NULL) { \
git_trace__write_fmt(l, __VA_ARGS__); \
} \
}
#else
#define git_trace_level() ((void)0)
#define git_trace(lvl, ...) ((void)0)
#endif
#endif
#include "clar_libgit2.h"
#include "trace.h"
static int written = 0;
static void trace_callback(git_trace_level_t level, const char *message)
{
cl_assert(strcmp(message, "Hello world!") == 0);
written = 1;
}
void test_trace_trace__initialize(void)
{
git_trace_set(GIT_TRACE_INFO, trace_callback);
written = 0;
}
void test_trace_trace__cleanup(void)
{
git_trace_set(GIT_TRACE_NONE, NULL);
}
void test_trace_trace__sets(void)
{
#ifdef GIT_TRACE
cl_assert(git_trace_level() == GIT_TRACE_INFO);
#endif
}
void test_trace_trace__can_reset(void)
{
#ifdef GIT_TRACE
cl_assert(git_trace_level() == GIT_TRACE_INFO);
cl_git_pass(git_trace_set(GIT_TRACE_ERROR, trace_callback));
cl_assert(written == 0);
git_trace(GIT_TRACE_INFO, "Hello %s!", "world");
cl_assert(written == 0);
git_trace(GIT_TRACE_ERROR, "Hello %s!", "world");
cl_assert(written == 1);
#endif
}
void test_trace_trace__can_unset(void)
{
#ifdef GIT_TRACE
cl_assert(git_trace_level() == GIT_TRACE_INFO);
cl_git_pass(git_trace_set(GIT_TRACE_NONE, NULL));
cl_assert(git_trace_level() == GIT_TRACE_NONE);
cl_assert(written == 0);
git_trace(GIT_TRACE_FATAL, "Hello %s!", "world");
cl_assert(written == 0);
#endif
}
void test_trace_trace__skips_higher_level(void)
{
#ifdef GIT_TRACE
cl_assert(written == 0);
git_trace(GIT_TRACE_DEBUG, "Hello %s!", "world");
cl_assert(written == 0);
#endif
}
void test_trace_trace__writes(void)
{
#ifdef GIT_TRACE
cl_assert(written == 0);
git_trace(GIT_TRACE_INFO, "Hello %s!", "world");
cl_assert(written == 1);
#endif
}
void test_trace_trace__writes_lower_level(void)
{
#ifdef GIT_TRACE
cl_assert(written == 0);
git_trace(GIT_TRACE_ERROR, "Hello %s!", "world");
cl_assert(written == 1);
#endif
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment