Skip to content

Commit

Permalink
Merge branch 'jk/pkt-log-pack'
Browse files Browse the repository at this point in the history
Enhance packet tracing machinery to allow capturing an incoming
pack data to a file for debugging.

* jk/pkt-log-pack:
  pkt-line: support tracing verbatim pack contents
  pkt-line: tighten sideband PACK check when tracing
  pkt-line: simplify starts_with checks in packet tracing
  • Loading branch information
Junio C Hamano committed Aug 3, 2015
2 parents 9f56db7 + 3235983 commit 0b9ce18
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 17 deletions.
13 changes: 12 additions & 1 deletion Documentation/git.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1009,9 +1009,20 @@ Unsetting the variable, or setting it to empty, "0" or
Enables trace messages for all packets coming in or out of a
given program. This can help with debugging object negotiation
or other protocol issues. Tracing is turned off at a packet
starting with "PACK".
starting with "PACK" (but see 'GIT_TRACE_PACKFILE' below).
See 'GIT_TRACE' for available trace output options.

'GIT_TRACE_PACKFILE'::
Enables tracing of packfiles sent or received by a
given program. Unlike other trace output, this trace is
verbatim: no headers, and no quoting of binary data. You almost
certainly want to direct into a file (e.g.,
`GIT_TRACE_PACKFILE=/tmp/my.pack`) rather than displaying it on
the terminal or mixing it with other trace output.
+
Note that this is currently only implemented for the client side
of clones and fetches.

'GIT_TRACE_PERFORMANCE'::
Enables performance related trace messages, e.g. total execution
time of each Git command.
Expand Down
60 changes: 44 additions & 16 deletions pkt-line.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,51 @@
char packet_buffer[LARGE_PACKET_MAX];
static const char *packet_trace_prefix = "git";
static struct trace_key trace_packet = TRACE_KEY_INIT(PACKET);
static struct trace_key trace_pack = TRACE_KEY_INIT(PACKFILE);

void packet_trace_identity(const char *prog)
{
packet_trace_prefix = xstrdup(prog);
}

static int packet_trace_pack(const char *buf, unsigned int len, int sideband)
{
if (!sideband) {
trace_verbatim(&trace_pack, buf, len);
return 1;
} else if (len && *buf == '\1') {
trace_verbatim(&trace_pack, buf + 1, len - 1);
return 1;
} else {
/* it's another non-pack sideband */
return 0;
}
}

static void packet_trace(const char *buf, unsigned int len, int write)
{
int i;
struct strbuf out;
static int in_pack, sideband;

if (!trace_want(&trace_packet) && !trace_want(&trace_pack))
return;

if (in_pack) {
if (packet_trace_pack(buf, len, sideband))
return;
} else if (starts_with(buf, "PACK") || starts_with(buf, "\1PACK")) {
in_pack = 1;
sideband = *buf == '\1';
packet_trace_pack(buf, len, sideband);

/*
* Make a note in the human-readable trace that the pack data
* started.
*/
buf = "PACK ...";
len = strlen(buf);
}

if (!trace_want(&trace_packet))
return;
Expand All @@ -24,22 +59,15 @@ static void packet_trace(const char *buf, unsigned int len, int write)
strbuf_addf(&out, "packet: %12s%c ",
packet_trace_prefix, write ? '>' : '<');

if ((len >= 4 && starts_with(buf, "PACK")) ||
(len >= 5 && starts_with(buf+1, "PACK"))) {
strbuf_addstr(&out, "PACK ...");
trace_disable(&trace_packet);
}
else {
/* XXX we should really handle printable utf8 */
for (i = 0; i < len; i++) {
/* suppress newlines */
if (buf[i] == '\n')
continue;
if (buf[i] >= 0x20 && buf[i] <= 0x7e)
strbuf_addch(&out, buf[i]);
else
strbuf_addf(&out, "\\%o", buf[i]);
}
/* XXX we should really handle printable utf8 */
for (i = 0; i < len; i++) {
/* suppress newlines */
if (buf[i] == '\n')
continue;
if (buf[i] >= 0x20 && buf[i] <= 0x7e)
strbuf_addch(&out, buf[i]);
else
strbuf_addf(&out, "\\%o", buf[i]);
}

strbuf_addch(&out, '\n');
Expand Down
7 changes: 7 additions & 0 deletions t/t5601-clone.sh
Original file line number Diff line number Diff line change
Expand Up @@ -496,4 +496,11 @@ test_expect_success 'shallow clone locally' '
( cd ddsstt && git fsck )
'

test_expect_success 'GIT_TRACE_PACKFILE produces a usable pack' '
rm -rf dst.git &&
GIT_TRACE_PACKFILE=$PWD/tmp.pack git clone --no-local --bare src dst.git &&
git init --bare replay.git &&
git -C replay.git index-pack -v --stdin <tmp.pack
'

test_done
7 changes: 7 additions & 0 deletions trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ static int prepare_trace_line(const char *file, int line,
return 1;
}

void trace_verbatim(struct trace_key *key, const void *buf, unsigned len)
{
if (!trace_want(key))
return;
write_or_whine_pipe(get_trace_fd(key), buf, len, err_msg);
}

static void print_trace_line(struct trace_key *key, struct strbuf *buf)
{
strbuf_complete_line(buf);
Expand Down
1 change: 1 addition & 0 deletions trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ extern int trace_want(struct trace_key *key);
extern void trace_disable(struct trace_key *key);
extern uint64_t getnanotime(void);
extern void trace_command_performance(const char **argv);
extern void trace_verbatim(struct trace_key *key, const void *buf, unsigned len);

#ifndef HAVE_VARIADIC_MACROS

Expand Down

0 comments on commit 0b9ce18

Please sign in to comment.