|
1 | 1 | #include "cache.h"
|
2 | 2 | #include "color.h"
|
3 | 3 | #include "config.h"
|
4 |
| -#include "pkt-line.h" |
5 | 4 | #include "sideband.h"
|
6 | 5 | #include "help.h"
|
7 | 6 |
|
@@ -109,109 +108,99 @@ static void maybe_colorize_sideband(struct strbuf *dest, const char *src, int n)
|
109 | 108 | }
|
110 | 109 |
|
111 | 110 |
|
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 |
| - |
123 | 111 | #define DISPLAY_PREFIX "remote: "
|
124 | 112 |
|
125 | 113 | #define ANSI_SUFFIX "\033[K"
|
126 | 114 | #define DUMB_SUFFIX " "
|
127 | 115 |
|
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) |
129 | 119 | {
|
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 | + } |
191 | 130 |
|
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); |
196 | 172 | }
|
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)); |
206 | 185 | }
|
| 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; |
207 | 195 | }
|
208 | 196 |
|
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); |
212 | 201 | }
|
213 |
| - strbuf_release(&outbuf); |
214 |
| - return retval; |
| 202 | + strbuf_release(scratch); |
| 203 | + return 1; |
215 | 204 | }
|
216 | 205 |
|
217 | 206 | /*
|
|
0 commit comments