diff --git a/sub-process.c b/sub-process.c index 3cef42b088..33bd789618 100644 --- a/sub-process.c +++ b/sub-process.c @@ -49,6 +49,30 @@ int subprocess_read_status(int fd, struct strbuf *status) return (len < 0) ? len : 0; } +int subprocess_read_status_gently(int fd, struct strbuf *status) +{ + for (;;) { + int pktlen = -1; + enum packet_read_status rs; + const char *value; + + rs = packet_read_with_status(fd, NULL, NULL, packet_buffer, + sizeof(packet_buffer), &pktlen, + PACKET_READ_CHOMP_NEWLINE | + PACKET_READ_GENTLE_ON_EOF | + PACKET_READ_GENTLE_ON_READ_ERROR); + if (rs == PACKET_READ_FLUSH) + return 0; + if (rs != PACKET_READ_NORMAL || !pktlen) + return -1; + if (skip_prefix(packet_buffer, "status=", &value)) { + /* the last "status=" line wins */ + strbuf_reset(status); + strbuf_addstr(status, value); + } + } +} + void subprocess_stop_command(struct subprocess_entry *entry) { if (!entry) diff --git a/sub-process.h b/sub-process.h index 45f1b8e5e3..8655b38897 100644 --- a/sub-process.h +++ b/sub-process.h @@ -101,4 +101,14 @@ int subprocess_handshake(struct subprocess_entry *entry, int subprocess_read_status(int fd, struct strbuf *status); +/* + * Like subprocess_read_status(), but a malformed status section fails + * instead of dying: a truncated or malformed packet, and an empty + * packet where a status line or the terminating flush belongs, return + * -1 and leave the stream unusable. subprocess_read_status() cannot + * tell an empty packet from the flush that ends the section, and dies + * on a framing error inside packet_read_line_gently(). + */ +int subprocess_read_status_gently(int fd, struct strbuf *status); + #endif