upload-pack: refactor reading of pack-objects out
Subsequent patches will change how the output of pack-objects is processed, so extract that processing into its own function. Currently, at most 1 character can be buffered (in the "buffered" local variable). One of those patches will require a larger buffer, so replace that "buffered" local variable with a buffer array. Signed-off-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jonathan Tan committed
Jun 10, 2020 at 13:57 UTC
acaaca7d7030bb349441da10bf9ca6917f30cbb2
1 file changed
+49
-35
upload-pack.c
+49
-35
@@ -173,13 +173,52 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
173
return 0;
174
}
175
176
+struct output_state {
177
+ char buffer[8193];
178
+ int used;
179
+};
180
+
181
+static int relay_pack_data(int pack_objects_out, struct output_state *os,
182
+ int use_sideband)
183
+{
184
+ /*
185
+ * We keep the last byte to ourselves
186
+ * in case we detect broken rev-list, so that we
187
+ * can leave the stream corrupted. This is
188
+ * unfortunate -- unpack-objects would happily
189
+ * accept a valid packdata with trailing garbage,
190
+ * so appending garbage after we pass all the
191
+ * pack data is not good enough to signal
192
+ * breakage to downstream.
193
+ */
194
+ ssize_t readsz;
195
+
196
+ readsz = xread(pack_objects_out, os->buffer + os->used,
197
+ sizeof(os->buffer) - os->used);
198
+ if (readsz < 0) {
199
+ return readsz;
200
+ }
201
+ os->used += readsz;
202
+
203
+ if (os->used > 1) {
204
+ send_client_data(1, os->buffer, os->used - 1, use_sideband);
205
+ os->buffer[0] = os->buffer[os->used - 1];
206
+ os->used = 1;
207
+ } else {
208
+ send_client_data(1, os->buffer, os->used, use_sideband);
209
+ os->used = 0;
210
+ }
211
+
212
+ return readsz;
213
+}
214
+
215
static void create_pack_file(struct upload_pack_data *pack_data)
216
{
217
struct child_process pack_objects = CHILD_PROCESS_INIT;
179
- char data[8193], progress[128];
218
+ struct output_state output_state = { { 0 } };
219
+ char progress[128];
220
char abort_msg[] = "aborting due to possible repository "
221
"corruption on the remote side.";
182
- int buffered = -1;
222
ssize_t sz;
223
int i;
224
FILE *pipe_fd;
@@ -312,40 +351,16 @@ static void create_pack_file(struct upload_pack_data *pack_data)
351
continue;
352
}
353
if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) {
315
- /* Data ready; we keep the last byte to ourselves
316
- * in case we detect broken rev-list, so that we
317
- * can leave the stream corrupted. This is
318
- * unfortunate -- unpack-objects would happily
319
- * accept a valid packdata with trailing garbage,
320
- * so appending garbage after we pass all the
321
- * pack data is not good enough to signal
322
- * breakage to downstream.
323
- */
324
- char *cp = data;
325
- ssize_t outsz = 0;
326
- if (0 <= buffered) {
327
- *cp++ = buffered;
328
- outsz++;
329
- }
330
- sz = xread(pack_objects.out, cp,
331
- sizeof(data) - outsz);
332
- if (0 < sz)
333
- ;
334
- else if (sz == 0) {
354
+ int result = relay_pack_data(pack_objects.out,
355
+ &output_state,
356
+ pack_data->use_sideband);
357
+
358
+ if (result == 0) {
359
close(pack_objects.out);
360
pack_objects.out = -1;
337
- }
338
- else
361
+ } else if (result < 0) {
362
goto fail;
340
- sz += outsz;
341
- if (1 < sz) {
342
- buffered = data[sz-1] & 0xFF;
343
- sz--;
363
}
345
- else
346
- buffered = -1;
347
- send_client_data(1, data, sz,
348
- pack_data->use_sideband);
364
}
365
366
/*
@@ -370,9 +385,8 @@ static void create_pack_file(struct upload_pack_data *pack_data)
385
}
386
387
/* flush the data */
373
- if (0 <= buffered) {
374
- data[0] = buffered;
375
- send_client_data(1, data, 1,
388
+ if (output_state.used > 0) {
389
+ send_client_data(1, output_state.buffer, output_state.used,
390
pack_data->use_sideband);
391
fprintf(stderr, "flushed.\n");
392
}