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 <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
bc2e795cea
commit
fbd76cd450
23
pkt-line.c
23
pkt-line.c
@ -439,6 +439,29 @@ ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out)
|
|||||||
return sb_out->len - orig_len;
|
return sb_out->len - orig_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int recv_sideband(const char *me, int in_stream, int out)
|
||||||
|
{
|
||||||
|
char buf[LARGE_PACKET_MAX + 1];
|
||||||
|
int len;
|
||||||
|
struct strbuf scratch = STRBUF_INIT;
|
||||||
|
enum sideband_type sideband_type;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
len = packet_read(in_stream, NULL, NULL, buf, LARGE_PACKET_MAX,
|
||||||
|
0);
|
||||||
|
if (!demultiplex_sideband(me, buf, len, &scratch,
|
||||||
|
&sideband_type))
|
||||||
|
continue;
|
||||||
|
switch (sideband_type) {
|
||||||
|
case SIDEBAND_PRIMARY:
|
||||||
|
write_or_die(out, buf + 1, len - 1);
|
||||||
|
break;
|
||||||
|
default: /* errors: message already written */
|
||||||
|
return sideband_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Packet Reader Functions */
|
/* Packet Reader Functions */
|
||||||
void packet_reader_init(struct packet_reader *reader, int fd,
|
void packet_reader_init(struct packet_reader *reader, int fd,
|
||||||
char *src_buffer, size_t src_len,
|
char *src_buffer, size_t src_len,
|
||||||
|
16
pkt-line.h
16
pkt-line.h
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "git-compat-util.h"
|
#include "git-compat-util.h"
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
|
#include "sideband.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write a packetized stream, where each line is preceded by
|
* 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);
|
|||||||
*/
|
*/
|
||||||
ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out);
|
ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Receive multiplexed output stream over git native protocol.
|
||||||
|
* in_stream is the input stream from the remote, which carries data
|
||||||
|
* in pkt_line format with band designator. Demultiplex it into out
|
||||||
|
* and err and return error appropriately. Band #1 carries the
|
||||||
|
* primary payload. Things coming over band #2 is not necessarily
|
||||||
|
* error; they are usually informative message on the standard error
|
||||||
|
* stream, aka "verbose"). A message over band #3 is a signal that
|
||||||
|
* the remote died unexpectedly. A flush() concludes the stream.
|
||||||
|
*
|
||||||
|
* Returns SIDEBAND_FLUSH upon a normal conclusion, and SIDEBAND_PROTOCOL_ERROR
|
||||||
|
* or SIDEBAND_REMOTE_ERROR if an error occurred.
|
||||||
|
*/
|
||||||
|
int recv_sideband(const char *me, int in_stream, int out);
|
||||||
|
|
||||||
struct packet_reader {
|
struct packet_reader {
|
||||||
/* source file descriptor */
|
/* source file descriptor */
|
||||||
int fd;
|
int fd;
|
||||||
|
177
sideband.c
177
sideband.c
@ -1,7 +1,6 @@
|
|||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "pkt-line.h"
|
|
||||||
#include "sideband.h"
|
#include "sideband.h"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
|
|
||||||
@ -109,109 +108,99 @@ static void maybe_colorize_sideband(struct strbuf *dest, const char *src, int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Receive multiplexed output stream over git native protocol.
|
|
||||||
* in_stream is the input stream from the remote, which carries data
|
|
||||||
* in pkt_line format with band designator. Demultiplex it into out
|
|
||||||
* and err and return error appropriately. Band #1 carries the
|
|
||||||
* primary payload. Things coming over band #2 is not necessarily
|
|
||||||
* error; they are usually informative message on the standard error
|
|
||||||
* stream, aka "verbose"). A message over band #3 is a signal that
|
|
||||||
* the remote died unexpectedly. A flush() concludes the stream.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define DISPLAY_PREFIX "remote: "
|
#define DISPLAY_PREFIX "remote: "
|
||||||
|
|
||||||
#define ANSI_SUFFIX "\033[K"
|
#define ANSI_SUFFIX "\033[K"
|
||||||
#define DUMB_SUFFIX " "
|
#define DUMB_SUFFIX " "
|
||||||
|
|
||||||
int recv_sideband(const char *me, int in_stream, int out)
|
int demultiplex_sideband(const char *me, char *buf, int len,
|
||||||
|
struct strbuf *scratch,
|
||||||
|
enum sideband_type *sideband_type)
|
||||||
{
|
{
|
||||||
const char *suffix;
|
static const char *suffix;
|
||||||
char buf[LARGE_PACKET_MAX + 1];
|
const char *b, *brk;
|
||||||
struct strbuf outbuf = STRBUF_INIT;
|
int band;
|
||||||
int retval = 0;
|
|
||||||
|
|
||||||
if (isatty(2) && !is_terminal_dumb())
|
if (!suffix) {
|
||||||
suffix = ANSI_SUFFIX;
|
if (isatty(2) && !is_terminal_dumb())
|
||||||
else
|
suffix = ANSI_SUFFIX;
|
||||||
suffix = DUMB_SUFFIX;
|
else
|
||||||
|
suffix = DUMB_SUFFIX;
|
||||||
while (!retval) {
|
|
||||||
const char *b, *brk;
|
|
||||||
int band, len;
|
|
||||||
len = packet_read(in_stream, NULL, NULL, buf, LARGE_PACKET_MAX, 0);
|
|
||||||
if (len == 0)
|
|
||||||
break;
|
|
||||||
if (len < 1) {
|
|
||||||
strbuf_addf(&outbuf,
|
|
||||||
"%s%s: protocol error: no band designator",
|
|
||||||
outbuf.len ? "\n" : "", me);
|
|
||||||
retval = SIDEBAND_PROTOCOL_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
band = buf[0] & 0xff;
|
|
||||||
buf[len] = '\0';
|
|
||||||
len--;
|
|
||||||
switch (band) {
|
|
||||||
case 3:
|
|
||||||
strbuf_addf(&outbuf, "%s%s", outbuf.len ? "\n" : "",
|
|
||||||
DISPLAY_PREFIX);
|
|
||||||
maybe_colorize_sideband(&outbuf, buf + 1, len);
|
|
||||||
|
|
||||||
retval = SIDEBAND_REMOTE_ERROR;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
b = buf + 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Append a suffix to each nonempty line to clear the
|
|
||||||
* end of the screen line.
|
|
||||||
*
|
|
||||||
* The output is accumulated in a buffer and
|
|
||||||
* each line is printed to stderr using
|
|
||||||
* write(2) to ensure inter-process atomicity.
|
|
||||||
*/
|
|
||||||
while ((brk = strpbrk(b, "\n\r"))) {
|
|
||||||
int linelen = brk - b;
|
|
||||||
|
|
||||||
if (!outbuf.len)
|
|
||||||
strbuf_addstr(&outbuf, DISPLAY_PREFIX);
|
|
||||||
if (linelen > 0) {
|
|
||||||
maybe_colorize_sideband(&outbuf, b, linelen);
|
|
||||||
strbuf_addstr(&outbuf, suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
strbuf_addch(&outbuf, *brk);
|
|
||||||
xwrite(2, outbuf.buf, outbuf.len);
|
|
||||||
strbuf_reset(&outbuf);
|
|
||||||
|
|
||||||
b = brk + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*b) {
|
|
||||||
strbuf_addstr(&outbuf, outbuf.len ?
|
|
||||||
"" : DISPLAY_PREFIX);
|
|
||||||
maybe_colorize_sideband(&outbuf, b, strlen(b));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
write_or_die(out, buf + 1, len);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
strbuf_addf(&outbuf, "%s%s: protocol error: bad band #%d",
|
|
||||||
outbuf.len ? "\n" : "", me, band);
|
|
||||||
retval = SIDEBAND_PROTOCOL_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outbuf.len) {
|
if (len == 0) {
|
||||||
strbuf_addch(&outbuf, '\n');
|
*sideband_type = SIDEBAND_FLUSH;
|
||||||
xwrite(2, outbuf.buf, outbuf.len);
|
goto cleanup;
|
||||||
}
|
}
|
||||||
strbuf_release(&outbuf);
|
if (len < 1) {
|
||||||
return retval;
|
strbuf_addf(scratch,
|
||||||
|
"%s%s: protocol error: no band designator",
|
||||||
|
scratch->len ? "\n" : "", me);
|
||||||
|
*sideband_type = SIDEBAND_PROTOCOL_ERROR;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
band = buf[0] & 0xff;
|
||||||
|
buf[len] = '\0';
|
||||||
|
len--;
|
||||||
|
switch (band) {
|
||||||
|
case 3:
|
||||||
|
strbuf_addf(scratch, "%s%s", scratch->len ? "\n" : "",
|
||||||
|
DISPLAY_PREFIX);
|
||||||
|
maybe_colorize_sideband(scratch, buf + 1, len);
|
||||||
|
|
||||||
|
*sideband_type = SIDEBAND_REMOTE_ERROR;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
b = buf + 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Append a suffix to each nonempty line to clear the
|
||||||
|
* end of the screen line.
|
||||||
|
*
|
||||||
|
* The output is accumulated in a buffer and
|
||||||
|
* each line is printed to stderr using
|
||||||
|
* write(2) to ensure inter-process atomicity.
|
||||||
|
*/
|
||||||
|
while ((brk = strpbrk(b, "\n\r"))) {
|
||||||
|
int linelen = brk - b;
|
||||||
|
|
||||||
|
if (!scratch->len)
|
||||||
|
strbuf_addstr(scratch, DISPLAY_PREFIX);
|
||||||
|
if (linelen > 0) {
|
||||||
|
maybe_colorize_sideband(scratch, b, linelen);
|
||||||
|
strbuf_addstr(scratch, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
strbuf_addch(scratch, *brk);
|
||||||
|
xwrite(2, scratch->buf, scratch->len);
|
||||||
|
strbuf_reset(scratch);
|
||||||
|
|
||||||
|
b = brk + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*b) {
|
||||||
|
strbuf_addstr(scratch, scratch->len ?
|
||||||
|
"" : DISPLAY_PREFIX);
|
||||||
|
maybe_colorize_sideband(scratch, b, strlen(b));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case 1:
|
||||||
|
*sideband_type = SIDEBAND_PRIMARY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strbuf_addf(scratch, "%s%s: protocol error: bad band #%d",
|
||||||
|
scratch->len ? "\n" : "", me, band);
|
||||||
|
*sideband_type = SIDEBAND_PROTOCOL_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (scratch->len) {
|
||||||
|
strbuf_addch(scratch, '\n');
|
||||||
|
xwrite(2, scratch->buf, scratch->len);
|
||||||
|
}
|
||||||
|
strbuf_release(scratch);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
24
sideband.h
24
sideband.h
@ -1,10 +1,28 @@
|
|||||||
#ifndef SIDEBAND_H
|
#ifndef SIDEBAND_H
|
||||||
#define SIDEBAND_H
|
#define SIDEBAND_H
|
||||||
|
|
||||||
#define SIDEBAND_PROTOCOL_ERROR -2
|
enum sideband_type {
|
||||||
#define SIDEBAND_REMOTE_ERROR -1
|
SIDEBAND_PROTOCOL_ERROR = -2,
|
||||||
|
SIDEBAND_REMOTE_ERROR = -1,
|
||||||
|
SIDEBAND_FLUSH = 0,
|
||||||
|
SIDEBAND_PRIMARY = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inspects a multiplexed packet read from the remote. If this packet is a
|
||||||
|
* progress packet and thus should not be processed by the caller, returns 0.
|
||||||
|
* Otherwise, returns 1, releases scratch, and sets sideband_type.
|
||||||
|
*
|
||||||
|
* If this packet is SIDEBAND_PROTOCOL_ERROR, SIDEBAND_REMOTE_ERROR, or a
|
||||||
|
* progress packet, also prints a message to stderr.
|
||||||
|
*
|
||||||
|
* scratch must be a struct strbuf allocated by the caller. It is used to store
|
||||||
|
* progress messages split across multiple packets.
|
||||||
|
*/
|
||||||
|
int demultiplex_sideband(const char *me, char *buf, int len,
|
||||||
|
struct strbuf *scratch,
|
||||||
|
enum sideband_type *sideband_type);
|
||||||
|
|
||||||
int recv_sideband(const char *me, int in_stream, int out);
|
|
||||||
void send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_max);
|
void send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_max);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user