@@ -173,13 +173,52 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
173173 return 0 ;
174174}
175175
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+
176215static void create_pack_file (struct upload_pack_data * pack_data )
177216{
178217 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 ];
180220 char abort_msg [] = "aborting due to possible repository "
181221 "corruption on the remote side." ;
182- int buffered = -1 ;
183222 ssize_t sz ;
184223 int i ;
185224 FILE * pipe_fd ;
@@ -312,40 +351,16 @@ static void create_pack_file(struct upload_pack_data *pack_data)
312351 continue ;
313352 }
314353 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 ) {
335359 close (pack_objects .out );
336360 pack_objects .out = -1 ;
337- }
338- else
361+ } else if (result < 0 ) {
339362 goto fail ;
340- sz += outsz ;
341- if (1 < sz ) {
342- buffered = data [sz - 1 ] & 0xFF ;
343- sz -- ;
344363 }
345- else
346- buffered = -1 ;
347- send_client_data (1 , data , sz ,
348- pack_data -> use_sideband );
349364 }
350365
351366 /*
@@ -370,9 +385,8 @@ static void create_pack_file(struct upload_pack_data *pack_data)
370385 }
371386
372387 /* 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 ,
376390 pack_data -> use_sideband );
377391 fprintf (stderr , "flushed.\n" );
378392 }
0 commit comments