diff options
Diffstat (limited to 'trace.c')
-rw-r--r-- | trace.c | 180 |
1 files changed, 108 insertions, 72 deletions
@@ -25,37 +25,10 @@ #include "cache.h" #include "quote.h" -/* Stolen from "imap-send.c". */ -int nfvasprintf(char **strp, const char *fmt, va_list ap) +/* Get a trace file descriptor from "key" env variable. */ +static int get_trace_fd(const char *key, int *need_close) { - int len; - char tmp[1024]; - - if ((len = vsnprintf(tmp, sizeof(tmp), fmt, ap)) < 0 || - !(*strp = xmalloc(len + 1))) - die("Fatal: Out of memory\n"); - if (len >= (int)sizeof(tmp)) - vsprintf(*strp, fmt, ap); - else - memcpy(*strp, tmp, len + 1); - return len; -} - -int nfasprintf(char **str, const char *fmt, ...) -{ - int rc; - va_list args; - - va_start(args, fmt); - rc = nfvasprintf(str, fmt, args); - va_end(args); - return rc; -} - -/* Get a trace file descriptor from GIT_TRACE env variable. */ -static int get_trace_fd(int *need_close) -{ - char *trace = getenv("GIT_TRACE"); + char *trace = getenv(key); if (!trace || !strcmp(trace, "") || !strcmp(trace, "0") || !strcasecmp(trace, "false")) @@ -64,7 +37,7 @@ static int get_trace_fd(int *need_close) return STDERR_FILENO; if (strlen(trace) == 1 && isdigit(*trace)) return atoi(trace); - if (*trace == '/') { + if (is_absolute_path(trace)) { int fd = open(trace, O_WRONLY | O_APPEND | O_CREAT, 0666); if (fd == -1) { fprintf(stderr, @@ -77,10 +50,10 @@ static int get_trace_fd(int *need_close) return fd; } - fprintf(stderr, "What does '%s' for GIT_TRACE means ?\n", trace); + fprintf(stderr, "What does '%s' for %s mean?\n", trace, key); fprintf(stderr, "If you want to trace into a file, " - "then please set GIT_TRACE to an absolute pathname " - "(starting with /).\n"); + "then please set %s to an absolute pathname " + "(starting with /).\n", key); fprintf(stderr, "Defaulting to tracing on stderr...\n"); return STDERR_FILENO; @@ -89,64 +62,127 @@ static int get_trace_fd(int *need_close) static const char err_msg[] = "Could not trace into fd given by " "GIT_TRACE environment variable"; -void trace_printf(const char *format, ...) +void trace_vprintf(const char *key, const char *fmt, va_list ap) { - char *trace_str; - va_list rest; - int need_close = 0; - int fd = get_trace_fd(&need_close); + struct strbuf buf = STRBUF_INIT; - if (!fd) + if (!trace_want(key)) return; - va_start(rest, format); - nfvasprintf(&trace_str, format, rest); - va_end(rest); + set_try_to_free_routine(NULL); /* is never reset */ + strbuf_vaddf(&buf, fmt, ap); + trace_strbuf(key, &buf); + strbuf_release(&buf); +} + +static void trace_printf_key(const char *key, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + trace_vprintf(key, fmt, ap); + va_end(ap); +} + +void trace_printf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + trace_vprintf("GIT_TRACE", fmt, ap); + va_end(ap); +} - write_or_whine_pipe(fd, trace_str, strlen(trace_str), err_msg); +void trace_strbuf(const char *key, const struct strbuf *buf) +{ + int fd, need_close = 0; - free(trace_str); + fd = get_trace_fd(key, &need_close); + if (!fd) + return; + + write_or_whine_pipe(fd, buf->buf, buf->len, err_msg); if (need_close) close(fd); } -void trace_argv_printf(const char **argv, int count, const char *format, ...) +void trace_argv_printf(const char **argv, const char *fmt, ...) { - char *argv_str, *format_str, *trace_str; - size_t argv_len, format_len, trace_len; - va_list rest; - int need_close = 0; - int fd = get_trace_fd(&need_close); + struct strbuf buf = STRBUF_INIT; + va_list ap; + int fd, need_close = 0; + fd = get_trace_fd("GIT_TRACE", &need_close); if (!fd) return; - /* Get the argv string. */ - argv_str = sq_quote_argv(argv, count); - argv_len = strlen(argv_str); + set_try_to_free_routine(NULL); /* is never reset */ + va_start(ap, fmt); + strbuf_vaddf(&buf, fmt, ap); + va_end(ap); + + sq_quote_argv(&buf, argv, 0); + strbuf_addch(&buf, '\n'); + write_or_whine_pipe(fd, buf.buf, buf.len, err_msg); + strbuf_release(&buf); - /* Get the formated string. */ - va_start(rest, format); - nfvasprintf(&format_str, format, rest); - va_end(rest); + if (need_close) + close(fd); +} - /* Allocate buffer for trace string. */ - format_len = strlen(format_str); - trace_len = argv_len + format_len + 1; /* + 1 for \n */ - trace_str = xmalloc(trace_len + 1); +static const char *quote_crnl(const char *path) +{ + static char new_path[PATH_MAX]; + const char *p2 = path; + char *p1 = new_path; + + if (!path) + return NULL; + + while (*p2) { + switch (*p2) { + case '\\': *p1++ = '\\'; *p1++ = '\\'; break; + case '\n': *p1++ = '\\'; *p1++ = 'n'; break; + case '\r': *p1++ = '\\'; *p1++ = 'r'; break; + default: + *p1++ = *p2; + } + p2++; + } + *p1 = '\0'; + return new_path; +} - /* Copy everything into the trace string. */ - strncpy(trace_str, format_str, format_len); - strncpy(trace_str + format_len, argv_str, argv_len); - strcpy(trace_str + trace_len - 1, "\n"); +/* FIXME: move prefix to startup_info struct and get rid of this arg */ +void trace_repo_setup(const char *prefix) +{ + static const char *key = "GIT_TRACE_SETUP"; + const char *git_work_tree; + char cwd[PATH_MAX]; - write_or_whine_pipe(fd, trace_str, trace_len, err_msg); + if (!trace_want(key)) + return; - free(argv_str); - free(format_str); - free(trace_str); + if (!getcwd(cwd, PATH_MAX)) + die("Unable to get current working directory"); - if (need_close) - close(fd); + if (!(git_work_tree = get_git_work_tree())) + git_work_tree = "(null)"; + + if (!prefix) + prefix = "(null)"; + + trace_printf_key(key, "setup: git_dir: %s\n", quote_crnl(get_git_dir())); + trace_printf_key(key, "setup: worktree: %s\n", quote_crnl(git_work_tree)); + trace_printf_key(key, "setup: cwd: %s\n", quote_crnl(cwd)); + trace_printf_key(key, "setup: prefix: %s\n", quote_crnl(prefix)); +} + +int trace_want(const char *key) +{ + const char *trace = getenv(key); + + if (!trace || !strcmp(trace, "") || + !strcmp(trace, "0") || !strcasecmp(trace, "false")) + return 0; + return 1; } |