1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
#include "git-compat-util.h"
#include "test-tool.h"
#include "pkt-line.h"
#include "sideband.h"
#include "write-or-die.h"
#include "parse-options.h"
static void pack_line(const char *line)
{
if (!strcmp(line, "0000") || !strcmp(line, "0000\n"))
packet_flush(1);
else if (!strcmp(line, "0001") || !strcmp(line, "0001\n"))
packet_delim(1);
else
packet_write_fmt(1, "%s", line);
}
static void pack(int argc, const char **argv)
{
if (argc) { /* read from argv */
int i;
for (i = 0; i < argc; i++)
pack_line(argv[i]);
} else { /* read from stdin */
char line[LARGE_PACKET_MAX];
while (fgets(line, sizeof(line), stdin)) {
pack_line(line);
}
}
}
static void pack_raw_stdin(void)
{
struct strbuf sb = STRBUF_INIT;
if (strbuf_read(&sb, 0, 0) < 0)
die_errno("failed to read from stdin");
packet_write(1, sb.buf, sb.len);
strbuf_release(&sb);
}
static void unpack(void)
{
struct packet_reader reader;
packet_reader_init(&reader, 0, NULL, 0,
PACKET_READ_GENTLE_ON_EOF |
PACKET_READ_CHOMP_NEWLINE);
while (packet_reader_read(&reader) != PACKET_READ_EOF) {
switch (reader.status) {
case PACKET_READ_EOF:
break;
case PACKET_READ_NORMAL:
printf("%s\n", reader.line);
break;
case PACKET_READ_FLUSH:
printf("0000\n");
break;
case PACKET_READ_DELIM:
printf("0001\n");
break;
case PACKET_READ_RESPONSE_END:
printf("0002\n");
break;
}
}
}
static void unpack_sideband(int argc, const char **argv)
{
struct packet_reader reader;
int options = PACKET_READ_GENTLE_ON_EOF;
int chomp_newline = 1;
int reader_use_sideband = 0;
const char *const unpack_sideband_usage[] = {
"test_tool unpack_sideband [options...]", NULL
};
struct option cmd_options[] = {
OPT_BOOL(0, "reader-use-sideband", &reader_use_sideband,
"set use_sideband bit for packet reader (Default: off)"),
OPT_BOOL(0, "chomp-newline", &chomp_newline,
"chomp newline in packet (Default: on)"),
OPT_END()
};
argc = parse_options(argc, argv, "", cmd_options, unpack_sideband_usage,
0);
if (argc > 0)
usage_msg_opt(_("too many arguments"), unpack_sideband_usage,
cmd_options);
if (chomp_newline)
options |= PACKET_READ_CHOMP_NEWLINE;
packet_reader_init(&reader, 0, NULL, 0, options);
reader.use_sideband = reader_use_sideband;
while (packet_reader_read(&reader) != PACKET_READ_EOF) {
int band;
int fd;
switch (reader.status) {
case PACKET_READ_EOF:
break;
case PACKET_READ_NORMAL:
/*
* When the "use_sideband" field of the reader is turned
* on, sideband packets other than the payload have been
* parsed and consumed in packet_reader_read(), and only
* the payload arrives here.
*/
if (reader.use_sideband) {
write_or_die(1, reader.line, reader.pktlen - 1);
break;
}
band = reader.line[0] & 0xff;
if (band < 1 || band > 2)
continue; /* skip non-sideband packets */
fd = band;
write_or_die(fd, reader.line + 1, reader.pktlen - 1);
break;
case PACKET_READ_FLUSH:
return;
case PACKET_READ_DELIM:
case PACKET_READ_RESPONSE_END:
break;
}
}
}
static int send_split_sideband(void)
{
const char *foo = "Foo.\n";
const char *bar = "Bar.\n";
const char *part1 = "Hello,";
const char *primary = "\001primary: regular output\n";
const char *part2 = " world!\n";
/* Each sideband message has a trailing newline character. */
send_sideband(1, 2, foo, strlen(foo), LARGE_PACKET_MAX);
send_sideband(1, 2, bar, strlen(bar), LARGE_PACKET_MAX);
/*
* One sideband message is divided into part1 and part2
* by the primary message.
*/
send_sideband(1, 2, part1, strlen(part1), LARGE_PACKET_MAX);
packet_write(1, primary, strlen(primary));
send_sideband(1, 2, part2, strlen(part2), LARGE_PACKET_MAX);
packet_response_end(1);
/*
* We use unpack_sideband() to consume packets. A flush packet
* is required to end parsing.
*/
packet_flush(1);
return 0;
}
static int receive_sideband(void)
{
return recv_sideband("sideband", 0, 1);
}
int cmd__pkt_line(int argc, const char **argv)
{
if (argc < 2)
die("too few arguments");
if (!strcmp(argv[1], "pack"))
pack(argc - 2, argv + 2);
else if (!strcmp(argv[1], "pack-raw-stdin"))
pack_raw_stdin();
else if (!strcmp(argv[1], "unpack"))
unpack();
else if (!strcmp(argv[1], "unpack-sideband"))
unpack_sideband(argc - 1, argv + 1);
else if (!strcmp(argv[1], "send-split-sideband"))
send_split_sideband();
else if (!strcmp(argv[1], "receive-sideband"))
receive_sideband();
else
die("invalid argument '%s'", argv[1]);
return 0;
}
|