@@ -173,13 +173,52 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
173
173
return 0 ;
174
174
}
175
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
+
176
215
static void create_pack_file (struct upload_pack_data * pack_data )
177
216
{
178
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 ];
180
220
char abort_msg [] = "aborting due to possible repository "
181
221
"corruption on the remote side." ;
182
- int buffered = -1 ;
183
222
ssize_t sz ;
184
223
int i ;
185
224
FILE * pipe_fd ;
@@ -312,40 +351,16 @@ static void create_pack_file(struct upload_pack_data *pack_data)
312
351
continue ;
313
352
}
314
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 ) {
335
359
close (pack_objects .out );
336
360
pack_objects .out = -1 ;
337
- }
338
- else
361
+ } else if (result < 0 ) {
339
362
goto fail ;
340
- sz += outsz ;
341
- if (1 < sz ) {
342
- buffered = data [sz - 1 ] & 0xFF ;
343
- sz -- ;
344
363
}
345
- else
346
- buffered = -1 ;
347
- send_client_data (1 , data , sz ,
348
- pack_data -> use_sideband );
349
364
}
350
365
351
366
/*
@@ -370,9 +385,8 @@ static void create_pack_file(struct upload_pack_data *pack_data)
370
385
}
371
386
372
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 ,
376
390
pack_data -> use_sideband );
377
391
fprintf (stderr , "flushed.\n" );
378
392
}
0 commit comments