Skip to content

Commit 7cf6720

Browse files
chriscoolJunio C Hamano
authored andcommitted
Trace into open fd and refactor tracing code.
Now if GIT_TRACE is set to an integer value greater than 1 and lower than 10, we interpret this as an open fd value and we trace into it. Note that this behavior is not compatible with the previous one. We also trace whole messages using one write(2) call to make sure messages from processes do net get mixed up in the middle. It's now possible to run the tests like this: GIT_TRACE=9 make test 9>/var/tmp/trace.log Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent 2c6d22d commit 7cf6720

10 files changed

Lines changed: 196 additions & 64 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ LIB_OBJS = \
249249
server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
250250
tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
251251
fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \
252-
write_or_die.o \
252+
write_or_die.o trace.o \
253253
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS)
254254

255255
BUILTIN_OBJS = \

cache.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ extern char git_commit_encoding[MAX_ENCODING_LENGTH];
398398

399399
extern int copy_fd(int ifd, int ofd);
400400
extern void write_or_die(int fd, const void *buf, size_t count);
401+
extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg);
401402

402403
/* Finish off pack transfer receiving end */
403404
extern int receive_unpack_pack(int fd[2], const char *me, int quiet, int);
@@ -423,4 +424,9 @@ extern struct commit *alloc_commit_node(void);
423424
extern struct tag *alloc_tag_node(void);
424425
extern void alloc_report(void);
425426

427+
/* trace.c */
428+
extern int nfvasprintf(char **str, const char *fmt, va_list va);
429+
extern void trace_printf(const char *format, ...);
430+
extern void trace_argv_printf(const char **argv, int count, const char *format, ...);
431+
426432
#endif /* CACHE_H */

exec_cmd.c

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -97,26 +97,12 @@ int execv_git_cmd(const char **argv)
9797
tmp = argv[0];
9898
argv[0] = git_command;
9999

100-
if (getenv("GIT_TRACE")) {
101-
const char **p = argv;
102-
fputs("trace: exec:", stderr);
103-
while (*p) {
104-
fputc(' ', stderr);
105-
sq_quote_print(stderr, *p);
106-
++p;
107-
}
108-
putc('\n', stderr);
109-
fflush(stderr);
110-
}
100+
trace_argv_printf(argv, -1, "trace: exec:");
111101

112102
/* execve() can only ever return if it fails */
113103
execve(git_command, (char **)argv, environ);
114104

115-
if (getenv("GIT_TRACE")) {
116-
fprintf(stderr, "trace: exec failed: %s\n",
117-
strerror(errno));
118-
fflush(stderr);
119-
}
105+
trace_printf("trace: exec failed: %s\n", strerror(errno));
120106

121107
argv[0] = tmp;
122108
}

git.c

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -179,17 +179,9 @@ static int handle_alias(int *argcp, const char ***argv)
179179
if (!strcmp(alias_command, new_argv[0]))
180180
die("recursive alias: %s", alias_command);
181181

182-
if (getenv("GIT_TRACE")) {
183-
int i;
184-
fprintf(stderr, "trace: alias expansion: %s =>",
185-
alias_command);
186-
for (i = 0; i < count; ++i) {
187-
fputc(' ', stderr);
188-
sq_quote_print(stderr, new_argv[i]);
189-
}
190-
fputc('\n', stderr);
191-
fflush(stderr);
192-
}
182+
trace_argv_printf(new_argv, count,
183+
"trace: alias expansion: %s =>",
184+
alias_command);
193185

194186
new_argv = xrealloc(new_argv, sizeof(char*) *
195187
(count + *argcp + 1));
@@ -292,16 +284,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
292284
prefix = setup_git_directory();
293285
if (p->option & USE_PAGER)
294286
setup_pager();
295-
if (getenv("GIT_TRACE")) {
296-
int j;
297-
fprintf(stderr, "trace: built-in: git");
298-
for (j = 0; j < argc; ++j) {
299-
fputc(' ', stderr);
300-
sq_quote_print(stderr, argv[j]);
301-
}
302-
putc('\n', stderr);
303-
fflush(stderr);
304-
}
287+
trace_argv_printf(argv, argc, "trace: built-in: git");
305288

306289
exit(p->fn(argc, argv, prefix));
307290
}

imap-send.c

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ static char *next_arg( char ** );
110110

111111
static void free_generic_messages( message_t * );
112112

113-
static int nfvasprintf( char **str, const char *fmt, va_list va );
114113
static int nfsnprintf( char *buf, int blen, const char *fmt, ... );
115114

116115

@@ -371,21 +370,6 @@ free_generic_messages( message_t *msgs )
371370
}
372371
}
373372

374-
static int
375-
git_vasprintf( char **strp, const char *fmt, va_list ap )
376-
{
377-
int len;
378-
char tmp[1024];
379-
380-
if ((len = vsnprintf( tmp, sizeof(tmp), fmt, ap )) < 0 || !(*strp = xmalloc( len + 1 )))
381-
return -1;
382-
if (len >= (int)sizeof(tmp))
383-
vsprintf( *strp, fmt, ap );
384-
else
385-
memcpy( *strp, tmp, len + 1 );
386-
return len;
387-
}
388-
389373
static int
390374
nfsnprintf( char *buf, int blen, const char *fmt, ... )
391375
{
@@ -399,15 +383,6 @@ nfsnprintf( char *buf, int blen, const char *fmt, ... )
399383
return ret;
400384
}
401385

402-
static int
403-
nfvasprintf( char **str, const char *fmt, va_list va )
404-
{
405-
int ret = git_vasprintf( str, fmt, va );
406-
if (ret < 0)
407-
die( "Fatal: Out of memory\n");
408-
return ret;
409-
}
410-
411386
static struct {
412387
unsigned char i, j, s[256];
413388
} rs;

quote.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,38 @@ char *sq_quote(const char *src)
7474
return buf;
7575
}
7676

77+
char *sq_quote_argv(const char** argv, int count)
78+
{
79+
char *buf, *to;
80+
int i;
81+
size_t len = 0;
82+
83+
/* Count argv if needed. */
84+
if (count < 0) {
85+
for (count = 0; argv[count]; count++)
86+
; /* just counting */
87+
}
88+
89+
/* Special case: no argv. */
90+
if (!count)
91+
return xcalloc(1,1);
92+
93+
/* Get destination buffer length. */
94+
for (i = 0; i < count; i++)
95+
len += sq_quote_buf(NULL, 0, argv[i]) + 1;
96+
97+
/* Alloc destination buffer. */
98+
to = buf = xmalloc(len + 1);
99+
100+
/* Copy into destination buffer. */
101+
for (i = 0; i < count; ++i) {
102+
*to++ = ' ';
103+
to += sq_quote_buf(to, len, argv[i]);
104+
}
105+
106+
return buf;
107+
}
108+
77109
char *sq_dequote(char *arg)
78110
{
79111
char *dst = arg;

quote.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
extern char *sq_quote(const char *src);
3232
extern void sq_quote_print(FILE *stream, const char *src);
3333
extern size_t sq_quote_buf(char *dst, size_t n, const char *src);
34+
extern char *sq_quote_argv(const char** argv, int count);
3435

3536
/* This unwraps what sq_quote() produces in place, but returns
3637
* NULL if the input does not look like what sq_quote would have

t/test-lib.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ unset GIT_DIR
2828
unset GIT_EXTERNAL_DIFF
2929
unset GIT_INDEX_FILE
3030
unset GIT_OBJECT_DIRECTORY
31-
unset GIT_TRACE
3231
unset SHA1_FILE_DIRECTORIES
3332
unset SHA1_FILE_DIRECTORY
3433
export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME

trace.c

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* GIT - The information manager from hell
3+
*
4+
* Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org>
5+
* Copyright (C) 2002-2004 Oswald Buddenhagen <ossi@users.sf.net>
6+
* Copyright (C) 2004 Theodore Y. Ts'o <tytso@mit.edu>
7+
* Copyright (C) 2006 Mike McCormack
8+
* Copyright (C) 2006 Christian Couder
9+
*
10+
* This program is free software; you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License as published by
12+
* the Free Software Foundation; either version 2 of the License, or
13+
* (at your option) any later version.
14+
*
15+
* This program is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU General Public License
21+
* along with this program; if not, write to the Free Software
22+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23+
*/
24+
25+
#include "cache.h"
26+
#include "quote.h"
27+
28+
/* Stolen from "imap-send.c". */
29+
static int git_vasprintf(char **strp, const char *fmt, va_list ap)
30+
{
31+
int len;
32+
char tmp[1024];
33+
34+
if ((len = vsnprintf(tmp, sizeof(tmp), fmt, ap)) < 0 ||
35+
!(*strp = xmalloc(len + 1)))
36+
return -1;
37+
if (len >= (int)sizeof(tmp))
38+
vsprintf(*strp, fmt, ap);
39+
else
40+
memcpy(*strp, tmp, len + 1);
41+
return len;
42+
}
43+
44+
/* Stolen from "imap-send.c". */
45+
int nfvasprintf(char **str, const char *fmt, va_list va)
46+
{
47+
int ret = git_vasprintf(str, fmt, va);
48+
if (ret < 0)
49+
die("Fatal: Out of memory\n");
50+
return ret;
51+
}
52+
53+
/* Get a trace file descriptor from GIT_TRACE env variable. */
54+
static int get_trace_fd()
55+
{
56+
char *trace = getenv("GIT_TRACE");
57+
58+
if (!trace || !strcmp(trace, "0") || !strcasecmp(trace," false"))
59+
return 0;
60+
if (!strcmp(trace, "1") || !strcasecmp(trace, "true"))
61+
return STDERR_FILENO;
62+
if (strlen(trace) == 1 && isdigit(*trace))
63+
return atoi(trace);
64+
65+
fprintf(stderr, "What does '%s' for GIT_TRACE means ?\n", trace);
66+
fprintf(stderr, "Defaulting to tracing on stderr...\n");
67+
return STDERR_FILENO;
68+
}
69+
70+
static const char err_msg[] = "Could not trace into fd given by "
71+
"GIT_TRACE environment variable";
72+
73+
void trace_printf(const char *format, ...)
74+
{
75+
char *trace_str;
76+
va_list rest;
77+
int fd = get_trace_fd();
78+
79+
if (!fd)
80+
return;
81+
82+
va_start(rest, format);
83+
nfvasprintf(&trace_str, format, rest);
84+
va_end(rest);
85+
86+
write_or_whine(fd, trace_str, strlen(trace_str), err_msg);
87+
88+
free(trace_str);
89+
}
90+
91+
void trace_argv_printf(const char **argv, int count, const char *format, ...)
92+
{
93+
char *argv_str, *format_str, *trace_str;
94+
size_t argv_len, format_len, trace_len;
95+
va_list rest;
96+
int fd = get_trace_fd();
97+
98+
if (!fd)
99+
return;
100+
101+
/* Get the argv string. */
102+
argv_str = sq_quote_argv(argv, count);
103+
argv_len = strlen(argv_str);
104+
105+
/* Get the formated string. */
106+
va_start(rest, format);
107+
nfvasprintf(&format_str, format, rest);
108+
va_end(rest);
109+
110+
/* Allocate buffer for trace string. */
111+
format_len = strlen(format_str);
112+
trace_len = argv_len + format_len + 1; /* + 1 for \n */
113+
trace_str = xmalloc(trace_len + 1);
114+
115+
/* Copy everything into the trace string. */
116+
strncpy(trace_str, format_str, format_len);
117+
strncpy(trace_str + format_len, argv_str, argv_len);
118+
strcpy(trace_str + trace_len - 1, "\n");
119+
120+
write_or_whine(fd, trace_str, trace_len, err_msg);
121+
122+
free(argv_str);
123+
free(format_str);
124+
free(trace_str);
125+
}

write_or_die.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,28 @@ void write_or_die(int fd, const void *buf, size_t count)
1818
p += written;
1919
}
2020
}
21+
22+
int write_or_whine(int fd, const void *buf, size_t count, const char *msg)
23+
{
24+
const char *p = buf;
25+
ssize_t written;
26+
27+
while (count > 0) {
28+
written = xwrite(fd, p, count);
29+
if (written == 0) {
30+
fprintf(stderr, "%s: disk full?\n", msg);
31+
return 0;
32+
}
33+
else if (written < 0) {
34+
if (errno == EPIPE)
35+
exit(0);
36+
fprintf(stderr, "%s: write error (%s)\n",
37+
msg, strerror(errno));
38+
return 0;
39+
}
40+
count -= written;
41+
p += written;
42+
}
43+
44+
return 1;
45+
}

0 commit comments

Comments
 (0)