Merge branch 'jk/pkt-log-pack'

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
This commit is contained in:
Junio C Hamano 2015-08-03 11:01:16 -07:00
commit 0b9ce18ede
5 changed files with 71 additions and 17 deletions

View file

@ -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.

View file

@ -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;
@ -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');

View file

@ -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

View file

@ -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);

View file

@ -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