diff options
Diffstat (limited to 'trace.c')
-rw-r--r-- | trace.c | 83 |
1 files changed, 52 insertions, 31 deletions
@@ -25,15 +25,25 @@ #include "cache.h" #include "quote.h" +/* + * "Normalize" a key argument by converting NULL to our trace_default, + * and otherwise passing through the value. All caller-facing functions + * should normalize their inputs in this way, though most get it + * for free by calling get_trace_fd() (directly or indirectly). + */ +static void normalize_trace_key(struct trace_key **key) +{ + static struct trace_key trace_default = { "GIT_TRACE" }; + if (!*key) + *key = &trace_default; +} + /* Get a trace file descriptor from "key" env variable. */ static int get_trace_fd(struct trace_key *key) { - static struct trace_key trace_default = { "GIT_TRACE" }; const char *trace; - /* use default "GIT_TRACE" if NULL */ - if (!key) - key = &trace_default; + normalize_trace_key(&key); /* don't open twice */ if (key->initialized) @@ -51,22 +61,19 @@ static int get_trace_fd(struct trace_key *key) else if (is_absolute_path(trace)) { int fd = open(trace, O_WRONLY | O_APPEND | O_CREAT, 0666); if (fd == -1) { - fprintf(stderr, - "Could not open '%s' for tracing: %s\n" - "Defaulting to tracing on stderr...\n", + warning("could not open '%s' for tracing: %s", trace, strerror(errno)); - key->fd = STDERR_FILENO; + trace_disable(key); } else { key->fd = fd; key->need_close = 1; } } else { - fprintf(stderr, "What does '%s' for %s mean?\n" - "If you want to trace into a file, then please set " - "%s to an absolute pathname (starting with /).\n" - "Defaulting to tracing on stderr...\n", - trace, key->key, key->key); - key->fd = STDERR_FILENO; + warning("unknown trace value for '%s': %s\n" + " If you want to trace into a file, then please set %s\n" + " to an absolute pathname (starting with /)", + key->key, trace, key->key); + trace_disable(key); } key->initialized = 1; @@ -75,6 +82,8 @@ static int get_trace_fd(struct trace_key *key) void trace_disable(struct trace_key *key) { + normalize_trace_key(&key); + if (key->need_close) close(key->fd); key->fd = 0; @@ -82,9 +91,6 @@ void trace_disable(struct trace_key *key) key->need_close = 0; } -static const char err_msg[] = "Could not trace into fd given by " - "GIT_TRACE environment variable"; - static int prepare_trace_line(const char *file, int line, struct trace_key *key, struct strbuf *buf) { @@ -120,11 +126,27 @@ static int prepare_trace_line(const char *file, int line, return 1; } +static void trace_write(struct trace_key *key, const void *buf, unsigned len) +{ + if (write_in_full(get_trace_fd(key), buf, len) < 0) { + normalize_trace_key(&key); + warning("unable to write trace for %s: %s", + key->key, strerror(errno)); + trace_disable(key); + } +} + +void trace_verbatim(struct trace_key *key, const void *buf, unsigned len) +{ + if (!trace_want(key)) + return; + trace_write(key, buf, len); +} + static void print_trace_line(struct trace_key *key, struct strbuf *buf) { strbuf_complete_line(buf); - - write_or_whine_pipe(get_trace_fd(key), buf->buf, buf->len, err_msg); + trace_write(key, buf->buf, buf->len); strbuf_release(buf); } @@ -270,25 +292,24 @@ void trace_performance_fl(const char *file, int line, uint64_t nanos, static const char *quote_crnl(const char *path) { - static char new_path[PATH_MAX]; - const char *p2 = path; - char *p1 = new_path; + static struct strbuf new_path = STRBUF_INIT; if (!path) return NULL; - while (*p2) { - switch (*p2) { - case '\\': *p1++ = '\\'; *p1++ = '\\'; break; - case '\n': *p1++ = '\\'; *p1++ = 'n'; break; - case '\r': *p1++ = '\\'; *p1++ = 'r'; break; + strbuf_reset(&new_path); + + while (*path) { + switch (*path) { + case '\\': strbuf_addstr(&new_path, "\\\\"); break; + case '\n': strbuf_addstr(&new_path, "\\n"); break; + case '\r': strbuf_addstr(&new_path, "\\r"); break; default: - *p1++ = *p2; + strbuf_addch(&new_path, *path); } - p2++; + path++; } - *p1 = '\0'; - return new_path; + return new_path.buf; } /* FIXME: move prefix to startup_info struct and get rid of this arg */ |