This RFC/patch is a first step to trace the git commands used when running the test suite. Thanks, Christian. -- 8< -- [RFC/PATCH] Trace into a file if GIT_TRACE can interpreted as a filename. If GIT_TRACE is set to something different than "1" or "true" then we suppose it's a filemane and try to trace into it instead of stderr. So this change is not compatible with the previous behavior, because stderr will not be used anymore if GIT_TRACE is set to something other than "1" or "true". No file locking is done. This maybe a problem. Signed-off-by: Christian Couder <chriscool@xxxxxxxxxxxxx> --- Makefile | 3 ++- cache.h | 4 ++++ exec_cmd.c | 19 ++++++++++--------- git.c | 26 ++++++++++++++------------ t/test-lib.sh | 3 +++ trace.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 76 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index c6b62d9..8ce78b3 100644 --- a/Makefile +++ b/Makefile @@ -253,7 +253,8 @@ LIB_OBJS = \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ tag.o tree.o usage.o config.o environment.o ctype.o copy.o \ fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \ - alloc.o merge-file.o path-list.o unpack-trees.o help.o $(DIFF_OBJS) + alloc.o merge-file.o path-list.o unpack-trees.o help.o trace.o \ + $(DIFF_OBJS) BUILTIN_OBJS = \ builtin-add.o \ diff --git a/cache.h b/cache.h index 913be6a..0efcf50 100644 --- a/cache.h +++ b/cache.h @@ -409,4 +409,8 @@ extern struct commit *alloc_commit_node( extern struct tag *alloc_tag_node(void); extern void alloc_report(void); +/* trace.c */ +extern FILE *start_trace(void); +extern void stop_trace(void); + #endif /* CACHE_H */ diff --git a/exec_cmd.c b/exec_cmd.c index 62f51fc..ddb45a3 100644 --- a/exec_cmd.c +++ b/exec_cmd.c @@ -43,6 +43,7 @@ int execv_git_cmd(const char **argv) int rc; const char *exec_dir = paths[i]; const char *tmp; + FILE *trace_file; if (!exec_dir || !*exec_dir) continue; @@ -97,25 +98,25 @@ int execv_git_cmd(const char **argv) tmp = argv[0]; argv[0] = git_command; - if (getenv("GIT_TRACE")) { + if ((trace_file = start_trace())) { const char **p = argv; - fputs("trace: exec:", stderr); + fputs("trace: exec:", trace_file); while (*p) { - fputc(' ', stderr); - sq_quote_print(stderr, *p); + fputc(' ', trace_file); + sq_quote_print(trace_file, *p); ++p; } - putc('\n', stderr); - fflush(stderr); + putc('\n', trace_file); + stop_trace(); } /* execve() can only ever return if it fails */ execve(git_command, (char **)argv, environ); - if (getenv("GIT_TRACE")) { - fprintf(stderr, "trace: exec failed: %s\n", + if ((trace_file = start_trace())) { + fprintf(trace_file, "trace: exec failed: %s\n", strerror(errno)); - fflush(stderr); + stop_trace(); } argv[0] = tmp; diff --git a/git.c b/git.c index 96e596b..39b78e2 100644 --- a/git.c +++ b/git.c @@ -161,6 +161,7 @@ static int handle_alias(int *argcp, cons const char *subdir; int count, option_count; const char** new_argv; + FILE *trace_file; subdir = setup_git_directory_gently(&nongit); @@ -179,16 +180,16 @@ static int handle_alias(int *argcp, cons if (!strcmp(alias_command, new_argv[0])) die("recursive alias: %s", alias_command); - if (getenv("GIT_TRACE")) { + if ((trace_file = start_trace())) { int i; - fprintf(stderr, "trace: alias expansion: %s =>", + fprintf(trace_file, "trace: alias expansion: %s =>", alias_command); for (i = 0; i < count; ++i) { - fputc(' ', stderr); - sq_quote_print(stderr, new_argv[i]); + fputc(' ', trace_file); + sq_quote_print(trace_file, new_argv[i]); } - fputc('\n', stderr); - fflush(stderr); + fputc('\n', trace_file); + stop_trace(); } new_argv = realloc(new_argv, sizeof(char*) * @@ -282,6 +283,7 @@ static void handle_internal_command(int for (i = 0; i < ARRAY_SIZE(commands); i++) { struct cmd_struct *p = commands+i; const char *prefix; + FILE * trace_file; if (strcmp(p->cmd, cmd)) continue; @@ -290,15 +292,15 @@ static void handle_internal_command(int prefix = setup_git_directory(); if (p->option & USE_PAGER) setup_pager(); - if (getenv("GIT_TRACE")) { + if ((trace_file = start_trace())) { int i; - fprintf(stderr, "trace: built-in: git"); + fprintf(trace_file, "trace: built-in: git"); for (i = 0; i < argc; ++i) { - fputc(' ', stderr); - sq_quote_print(stderr, argv[i]); + fputc(' ', trace_file); + sq_quote_print(trace_file, argv[i]); } - putc('\n', stderr); - fflush(stderr); + putc('\n', trace_file); + stop_trace(); } exit(p->fn(argc, argv, prefix)); diff --git a/t/test-lib.sh b/t/test-lib.sh index b6d119a..5afa5f0 100755 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -35,6 +35,9 @@ export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME export EDITOR VISUAL +# Uncomment the following line to trace the git commands into a file. +# export GIT_TRACE=`pwd`/git_trace.log + # Each test should start with something like this, after copyright notices: # # test_description='Description of this test... diff --git a/trace.c b/trace.c new file mode 100644 index 0000000..b1a14e0 --- /dev/null +++ b/trace.c @@ -0,0 +1,43 @@ +/* + * GIT - The information manager from hell + * + * Copyright (C) Christian Couder, 2006 + * + */ +#include "cache.h" + +static FILE *trace_file = NULL; + +FILE *start_trace() +{ + char * trace = getenv("GIT_TRACE"); + + if (trace && (!strcmp(trace,"1") || !strcasecmp(trace,"true"))) + trace_file = stderr; + else if (trace && strcmp(trace, "") && + strcmp(trace, "0") && strcasecmp(trace, "false")) { + /* We suppose we have a filename. */ + trace_file = fopen(trace, "a"); + if (!trace_file) { + fprintf(stderr, "Error: %s\n" + "when opening trace file: %s\n" + "Tracing on stderr instead.\n", + strerror(errno), trace); + trace_file = stderr; + } + } + + return trace_file; +} + +void stop_trace() +{ + if (trace_file) { + if (trace_file == stderr) + fflush(stderr); + else + fclose(trace_file); + trace_file = NULL; + } +} + -- 1.4.2.rc3.gcc6ea - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html