Skip to content

Commit fbd76cd

Browse files
jonathantanmygitster
authored andcommitted
sideband: reverse its dependency on pkt-line
A subsequent patch will teach struct packet_reader a new field that, if set, instructs it to interpret read data as multiplexed. This will create a dependency from pkt-line to sideband. To avoid a circular dependency, split recv_sideband() into 2 parts: the reading loop (left in recv_sideband()) and the processing of the contents (in demultiplex_sideband()), and move the former into pkt-line. This reverses the direction of dependency: sideband no longer depends on pkt-line, and pkt-line now depends on sideband. Signed-off-by: Jonathan Tan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent bc2e795 commit fbd76cd

File tree

4 files changed

+141
-95
lines changed

4 files changed

+141
-95
lines changed

pkt-line.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,29 @@ ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out)
439439
return sb_out->len - orig_len;
440440
}
441441

442+
int recv_sideband(const char *me, int in_stream, int out)
443+
{
444+
char buf[LARGE_PACKET_MAX + 1];
445+
int len;
446+
struct strbuf scratch = STRBUF_INIT;
447+
enum sideband_type sideband_type;
448+
449+
while (1) {
450+
len = packet_read(in_stream, NULL, NULL, buf, LARGE_PACKET_MAX,
451+
0);
452+
if (!demultiplex_sideband(me, buf, len, &scratch,
453+
&sideband_type))
454+
continue;
455+
switch (sideband_type) {
456+
case SIDEBAND_PRIMARY:
457+
write_or_die(out, buf + 1, len - 1);
458+
break;
459+
default: /* errors: message already written */
460+
return sideband_type;
461+
}
462+
}
463+
}
464+
442465
/* Packet Reader Functions */
443466
void packet_reader_init(struct packet_reader *reader, int fd,
444467
char *src_buffer, size_t src_len,

pkt-line.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "git-compat-util.h"
55
#include "strbuf.h"
6+
#include "sideband.h"
67

78
/*
89
* Write a packetized stream, where each line is preceded by
@@ -120,6 +121,21 @@ char *packet_read_line_buf(char **src_buf, size_t *src_len, int *size);
120121
*/
121122
ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out);
122123

124+
/*
125+
* Receive multiplexed output stream over git native protocol.
126+
* in_stream is the input stream from the remote, which carries data
127+
* in pkt_line format with band designator. Demultiplex it into out
128+
* and err and return error appropriately. Band #1 carries the
129+
* primary payload. Things coming over band #2 is not necessarily
130+
* error; they are usually informative message on the standard error
131+
* stream, aka "verbose"). A message over band #3 is a signal that
132+
* the remote died unexpectedly. A flush() concludes the stream.
133+
*
134+
* Returns SIDEBAND_FLUSH upon a normal conclusion, and SIDEBAND_PROTOCOL_ERROR
135+
* or SIDEBAND_REMOTE_ERROR if an error occurred.
136+
*/
137+
int recv_sideband(const char *me, int in_stream, int out);
138+
123139
struct packet_reader {
124140
/* source file descriptor */
125141
int fd;

sideband.c

Lines changed: 81 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include "cache.h"
22
#include "color.h"
33
#include "config.h"
4-
#include "pkt-line.h"
54
#include "sideband.h"
65
#include "help.h"
76

@@ -109,109 +108,99 @@ static void maybe_colorize_sideband(struct strbuf *dest, const char *src, int n)
109108
}
110109

111110

112-
/*
113-
* Receive multiplexed output stream over git native protocol.
114-
* in_stream is the input stream from the remote, which carries data
115-
* in pkt_line format with band designator. Demultiplex it into out
116-
* and err and return error appropriately. Band #1 carries the
117-
* primary payload. Things coming over band #2 is not necessarily
118-
* error; they are usually informative message on the standard error
119-
* stream, aka "verbose"). A message over band #3 is a signal that
120-
* the remote died unexpectedly. A flush() concludes the stream.
121-
*/
122-
123111
#define DISPLAY_PREFIX "remote: "
124112

125113
#define ANSI_SUFFIX "\033[K"
126114
#define DUMB_SUFFIX " "
127115

128-
int recv_sideband(const char *me, int in_stream, int out)
116+
int demultiplex_sideband(const char *me, char *buf, int len,
117+
struct strbuf *scratch,
118+
enum sideband_type *sideband_type)
129119
{
130-
const char *suffix;
131-
char buf[LARGE_PACKET_MAX + 1];
132-
struct strbuf outbuf = STRBUF_INIT;
133-
int retval = 0;
134-
135-
if (isatty(2) && !is_terminal_dumb())
136-
suffix = ANSI_SUFFIX;
137-
else
138-
suffix = DUMB_SUFFIX;
139-
140-
while (!retval) {
141-
const char *b, *brk;
142-
int band, len;
143-
len = packet_read(in_stream, NULL, NULL, buf, LARGE_PACKET_MAX, 0);
144-
if (len == 0)
145-
break;
146-
if (len < 1) {
147-
strbuf_addf(&outbuf,
148-
"%s%s: protocol error: no band designator",
149-
outbuf.len ? "\n" : "", me);
150-
retval = SIDEBAND_PROTOCOL_ERROR;
151-
break;
152-
}
153-
band = buf[0] & 0xff;
154-
buf[len] = '\0';
155-
len--;
156-
switch (band) {
157-
case 3:
158-
strbuf_addf(&outbuf, "%s%s", outbuf.len ? "\n" : "",
159-
DISPLAY_PREFIX);
160-
maybe_colorize_sideband(&outbuf, buf + 1, len);
161-
162-
retval = SIDEBAND_REMOTE_ERROR;
163-
break;
164-
case 2:
165-
b = buf + 1;
166-
167-
/*
168-
* Append a suffix to each nonempty line to clear the
169-
* end of the screen line.
170-
*
171-
* The output is accumulated in a buffer and
172-
* each line is printed to stderr using
173-
* write(2) to ensure inter-process atomicity.
174-
*/
175-
while ((brk = strpbrk(b, "\n\r"))) {
176-
int linelen = brk - b;
177-
178-
if (!outbuf.len)
179-
strbuf_addstr(&outbuf, DISPLAY_PREFIX);
180-
if (linelen > 0) {
181-
maybe_colorize_sideband(&outbuf, b, linelen);
182-
strbuf_addstr(&outbuf, suffix);
183-
}
184-
185-
strbuf_addch(&outbuf, *brk);
186-
xwrite(2, outbuf.buf, outbuf.len);
187-
strbuf_reset(&outbuf);
188-
189-
b = brk + 1;
190-
}
120+
static const char *suffix;
121+
const char *b, *brk;
122+
int band;
123+
124+
if (!suffix) {
125+
if (isatty(2) && !is_terminal_dumb())
126+
suffix = ANSI_SUFFIX;
127+
else
128+
suffix = DUMB_SUFFIX;
129+
}
191130

192-
if (*b) {
193-
strbuf_addstr(&outbuf, outbuf.len ?
194-
"" : DISPLAY_PREFIX);
195-
maybe_colorize_sideband(&outbuf, b, strlen(b));
131+
if (len == 0) {
132+
*sideband_type = SIDEBAND_FLUSH;
133+
goto cleanup;
134+
}
135+
if (len < 1) {
136+
strbuf_addf(scratch,
137+
"%s%s: protocol error: no band designator",
138+
scratch->len ? "\n" : "", me);
139+
*sideband_type = SIDEBAND_PROTOCOL_ERROR;
140+
goto cleanup;
141+
}
142+
band = buf[0] & 0xff;
143+
buf[len] = '\0';
144+
len--;
145+
switch (band) {
146+
case 3:
147+
strbuf_addf(scratch, "%s%s", scratch->len ? "\n" : "",
148+
DISPLAY_PREFIX);
149+
maybe_colorize_sideband(scratch, buf + 1, len);
150+
151+
*sideband_type = SIDEBAND_REMOTE_ERROR;
152+
break;
153+
case 2:
154+
b = buf + 1;
155+
156+
/*
157+
* Append a suffix to each nonempty line to clear the
158+
* end of the screen line.
159+
*
160+
* The output is accumulated in a buffer and
161+
* each line is printed to stderr using
162+
* write(2) to ensure inter-process atomicity.
163+
*/
164+
while ((brk = strpbrk(b, "\n\r"))) {
165+
int linelen = brk - b;
166+
167+
if (!scratch->len)
168+
strbuf_addstr(scratch, DISPLAY_PREFIX);
169+
if (linelen > 0) {
170+
maybe_colorize_sideband(scratch, b, linelen);
171+
strbuf_addstr(scratch, suffix);
196172
}
197-
break;
198-
case 1:
199-
write_or_die(out, buf + 1, len);
200-
break;
201-
default:
202-
strbuf_addf(&outbuf, "%s%s: protocol error: bad band #%d",
203-
outbuf.len ? "\n" : "", me, band);
204-
retval = SIDEBAND_PROTOCOL_ERROR;
205-
break;
173+
174+
strbuf_addch(scratch, *brk);
175+
xwrite(2, scratch->buf, scratch->len);
176+
strbuf_reset(scratch);
177+
178+
b = brk + 1;
179+
}
180+
181+
if (*b) {
182+
strbuf_addstr(scratch, scratch->len ?
183+
"" : DISPLAY_PREFIX);
184+
maybe_colorize_sideband(scratch, b, strlen(b));
206185
}
186+
return 0;
187+
case 1:
188+
*sideband_type = SIDEBAND_PRIMARY;
189+
break;
190+
default:
191+
strbuf_addf(scratch, "%s%s: protocol error: bad band #%d",
192+
scratch->len ? "\n" : "", me, band);
193+
*sideband_type = SIDEBAND_PROTOCOL_ERROR;
194+
break;
207195
}
208196

209-
if (outbuf.len) {
210-
strbuf_addch(&outbuf, '\n');
211-
xwrite(2, outbuf.buf, outbuf.len);
197+
cleanup:
198+
if (scratch->len) {
199+
strbuf_addch(scratch, '\n');
200+
xwrite(2, scratch->buf, scratch->len);
212201
}
213-
strbuf_release(&outbuf);
214-
return retval;
202+
strbuf_release(scratch);
203+
return 1;
215204
}
216205

217206
/*

sideband.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
#ifndef SIDEBAND_H
22
#define SIDEBAND_H
33

4-
#define SIDEBAND_PROTOCOL_ERROR -2
5-
#define SIDEBAND_REMOTE_ERROR -1
4+
enum sideband_type {
5+
SIDEBAND_PROTOCOL_ERROR = -2,
6+
SIDEBAND_REMOTE_ERROR = -1,
7+
SIDEBAND_FLUSH = 0,
8+
SIDEBAND_PRIMARY = 1
9+
};
10+
11+
/*
12+
* Inspects a multiplexed packet read from the remote. If this packet is a
13+
* progress packet and thus should not be processed by the caller, returns 0.
14+
* Otherwise, returns 1, releases scratch, and sets sideband_type.
15+
*
16+
* If this packet is SIDEBAND_PROTOCOL_ERROR, SIDEBAND_REMOTE_ERROR, or a
17+
* progress packet, also prints a message to stderr.
18+
*
19+
* scratch must be a struct strbuf allocated by the caller. It is used to store
20+
* progress messages split across multiple packets.
21+
*/
22+
int demultiplex_sideband(const char *me, char *buf, int len,
23+
struct strbuf *scratch,
24+
enum sideband_type *sideband_type);
625

7-
int recv_sideband(const char *me, int in_stream, int out);
826
void send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_max);
927

1028
#endif

0 commit comments

Comments
 (0)