Skip to content

Commit 5b49c1a

Browse files
committed
Merge branch 'jx/sideband-chomp-newline-fix' into maint-2.43
Sideband demultiplexer fixes. * jx/sideband-chomp-newline-fix: pkt-line: do not chomp newlines for sideband messages pkt-line: memorize sideband fragment in reader test-pkt-line: add option parser for unpack-sideband
2 parents fb3ead6 + 7033d54 commit 5b49c1a

File tree

4 files changed

+147
-10
lines changed

4 files changed

+147
-10
lines changed

pkt-line.c

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -463,8 +463,32 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
463463
}
464464

465465
if ((options & PACKET_READ_CHOMP_NEWLINE) &&
466-
len && buffer[len-1] == '\n')
467-
len--;
466+
len && buffer[len-1] == '\n') {
467+
if (options & PACKET_READ_USE_SIDEBAND) {
468+
int band = *buffer & 0xff;
469+
switch (band) {
470+
case 1:
471+
/* Chomp newline for payload */
472+
len--;
473+
break;
474+
case 2:
475+
case 3:
476+
/*
477+
* Do not chomp newline for progress and error
478+
* message.
479+
*/
480+
break;
481+
default:
482+
/*
483+
* Bad sideband, let's leave it to
484+
* demultiplex_sideband() to catch this error.
485+
*/
486+
break;
487+
}
488+
} else {
489+
len--;
490+
}
491+
}
468492

469493
buffer[len] = 0;
470494
if (options & PACKET_READ_REDACT_URI_PATH &&
@@ -593,17 +617,19 @@ void packet_reader_init(struct packet_reader *reader, int fd,
593617
reader->options = options;
594618
reader->me = "git";
595619
reader->hash_algo = &hash_algos[GIT_HASH_SHA1];
620+
strbuf_init(&reader->scratch, 0);
596621
}
597622

598623
enum packet_read_status packet_reader_read(struct packet_reader *reader)
599624
{
600-
struct strbuf scratch = STRBUF_INIT;
601-
602625
if (reader->line_peeked) {
603626
reader->line_peeked = 0;
604627
return reader->status;
605628
}
606629

630+
if (reader->use_sideband)
631+
reader->options |= PACKET_READ_USE_SIDEBAND;
632+
607633
/*
608634
* Consume all progress packets until a primary payload packet is
609635
* received
@@ -621,7 +647,7 @@ enum packet_read_status packet_reader_read(struct packet_reader *reader)
621647
break;
622648
if (demultiplex_sideband(reader->me, reader->status,
623649
reader->buffer, reader->pktlen, 1,
624-
&scratch, &sideband_type))
650+
&reader->scratch, &sideband_type))
625651
break;
626652
}
627653

pkt-line.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ void packet_fflush(FILE *f);
8484
#define PACKET_READ_DIE_ON_ERR_PACKET (1u<<2)
8585
#define PACKET_READ_GENTLE_ON_READ_ERROR (1u<<3)
8686
#define PACKET_READ_REDACT_URI_PATH (1u<<4)
87+
#define PACKET_READ_USE_SIDEBAND (1u<<5)
8788
int packet_read(int fd, char *buffer, unsigned size, int options);
8889

8990
/*
@@ -193,6 +194,9 @@ struct packet_reader {
193194

194195
/* hash algorithm in use */
195196
const struct git_hash_algo *hash_algo;
197+
198+
/* hold temporary sideband message */
199+
struct strbuf scratch;
196200
};
197201

198202
/*

t/helper/test-pkt-line.c

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "pkt-line.h"
44
#include "sideband.h"
55
#include "write-or-die.h"
6+
#include "parse-options.h"
67

78
static void pack_line(const char *line)
89
{
@@ -65,12 +66,33 @@ static void unpack(void)
6566
}
6667
}
6768

68-
static void unpack_sideband(void)
69+
static void unpack_sideband(int argc, const char **argv)
6970
{
7071
struct packet_reader reader;
71-
packet_reader_init(&reader, 0, NULL, 0,
72-
PACKET_READ_GENTLE_ON_EOF |
73-
PACKET_READ_CHOMP_NEWLINE);
72+
int options = PACKET_READ_GENTLE_ON_EOF;
73+
int chomp_newline = 1;
74+
int reader_use_sideband = 0;
75+
const char *const unpack_sideband_usage[] = {
76+
"test_tool unpack_sideband [options...]", NULL
77+
};
78+
struct option cmd_options[] = {
79+
OPT_BOOL(0, "reader-use-sideband", &reader_use_sideband,
80+
"set use_sideband bit for packet reader (Default: off)"),
81+
OPT_BOOL(0, "chomp-newline", &chomp_newline,
82+
"chomp newline in packet (Default: on)"),
83+
OPT_END()
84+
};
85+
86+
argc = parse_options(argc, argv, "", cmd_options, unpack_sideband_usage,
87+
0);
88+
if (argc > 0)
89+
usage_msg_opt(_("too many arguments"), unpack_sideband_usage,
90+
cmd_options);
91+
92+
if (chomp_newline)
93+
options |= PACKET_READ_CHOMP_NEWLINE;
94+
packet_reader_init(&reader, 0, NULL, 0, options);
95+
reader.use_sideband = reader_use_sideband;
7496

7597
while (packet_reader_read(&reader) != PACKET_READ_EOF) {
7698
int band;
@@ -80,6 +102,17 @@ static void unpack_sideband(void)
80102
case PACKET_READ_EOF:
81103
break;
82104
case PACKET_READ_NORMAL:
105+
/*
106+
* When the "use_sideband" field of the reader is turned
107+
* on, sideband packets other than the payload have been
108+
* parsed and consumed in packet_reader_read(), and only
109+
* the payload arrives here.
110+
*/
111+
if (reader.use_sideband) {
112+
write_or_die(1, reader.line, reader.pktlen - 1);
113+
break;
114+
}
115+
83116
band = reader.line[0] & 0xff;
84117
if (band < 1 || band > 2)
85118
continue; /* skip non-sideband packets */
@@ -98,15 +131,31 @@ static void unpack_sideband(void)
98131

99132
static int send_split_sideband(void)
100133
{
134+
const char *foo = "Foo.\n";
135+
const char *bar = "Bar.\n";
101136
const char *part1 = "Hello,";
102137
const char *primary = "\001primary: regular output\n";
103138
const char *part2 = " world!\n";
104139

140+
/* Each sideband message has a trailing newline character. */
141+
send_sideband(1, 2, foo, strlen(foo), LARGE_PACKET_MAX);
142+
send_sideband(1, 2, bar, strlen(bar), LARGE_PACKET_MAX);
143+
144+
/*
145+
* One sideband message is divided into part1 and part2
146+
* by the primary message.
147+
*/
105148
send_sideband(1, 2, part1, strlen(part1), LARGE_PACKET_MAX);
106149
packet_write(1, primary, strlen(primary));
107150
send_sideband(1, 2, part2, strlen(part2), LARGE_PACKET_MAX);
108151
packet_response_end(1);
109152

153+
/*
154+
* We use unpack_sideband() to consume packets. A flush packet
155+
* is required to end parsing.
156+
*/
157+
packet_flush(1);
158+
110159
return 0;
111160
}
112161

@@ -127,7 +176,7 @@ int cmd__pkt_line(int argc, const char **argv)
127176
else if (!strcmp(argv[1], "unpack"))
128177
unpack();
129178
else if (!strcmp(argv[1], "unpack-sideband"))
130-
unpack_sideband();
179+
unpack_sideband(argc - 1, argv + 1);
131180
else if (!strcmp(argv[1], "send-split-sideband"))
132181
send_split_sideband();
133182
else if (!strcmp(argv[1], "receive-sideband"))

t/t0070-fundamental.sh

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,62 @@ test_expect_success 'missing sideband designator is reported' '
5353
test_grep "missing sideband" err
5454
'
5555

56+
test_expect_success 'unpack-sideband: --no-chomp-newline' '
57+
test_when_finished "rm -f expect-out expect-err" &&
58+
test-tool pkt-line send-split-sideband >split-sideband &&
59+
test-tool pkt-line unpack-sideband \
60+
--no-chomp-newline <split-sideband >out 2>err &&
61+
cat >expect-out <<-EOF &&
62+
primary: regular output
63+
EOF
64+
cat >expect-err <<-EOF &&
65+
Foo.
66+
Bar.
67+
Hello, world!
68+
EOF
69+
test_cmp expect-out out &&
70+
test_cmp expect-err err
71+
'
72+
73+
test_expect_success 'unpack-sideband: --chomp-newline (default)' '
74+
test_when_finished "rm -f expect-out expect-err" &&
75+
test-tool pkt-line send-split-sideband >split-sideband &&
76+
test-tool pkt-line unpack-sideband \
77+
--chomp-newline <split-sideband >out 2>err &&
78+
printf "primary: regular output" >expect-out &&
79+
printf "Foo.Bar.Hello, world!" >expect-err &&
80+
test_cmp expect-out out &&
81+
test_cmp expect-err err
82+
'
83+
84+
test_expect_success 'unpack-sideband: packet_reader_read() consumes sideband, no chomp payload' '
85+
test_when_finished "rm -f expect-out expect-err" &&
86+
test-tool pkt-line send-split-sideband >split-sideband &&
87+
test-tool pkt-line unpack-sideband \
88+
--reader-use-sideband \
89+
--no-chomp-newline <split-sideband >out 2>err &&
90+
cat >expect-out <<-EOF &&
91+
primary: regular output
92+
EOF
93+
printf "remote: Foo. \n" >expect-err &&
94+
printf "remote: Bar. \n" >>expect-err &&
95+
printf "remote: Hello, world! \n" >>expect-err &&
96+
test_cmp expect-out out &&
97+
test_cmp expect-err err
98+
'
99+
100+
test_expect_success 'unpack-sideband: packet_reader_read() consumes sideband, chomp payload' '
101+
test_when_finished "rm -f expect-out expect-err" &&
102+
test-tool pkt-line send-split-sideband >split-sideband &&
103+
test-tool pkt-line unpack-sideband \
104+
--reader-use-sideband \
105+
--chomp-newline <split-sideband >out 2>err &&
106+
printf "primary: regular output" >expect-out &&
107+
printf "remote: Foo. \n" >expect-err &&
108+
printf "remote: Bar. \n" >>expect-err &&
109+
printf "remote: Hello, world! \n" >>expect-err &&
110+
test_cmp expect-out out &&
111+
test_cmp expect-err err
112+
'
113+
56114
test_done

0 commit comments

Comments
 (0)