@@ -102,14 +102,52 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
102
102
return 0 ;
103
103
}
104
104
105
+ struct output_state {
106
+ char buffer [8193 ];
107
+ int used ;
108
+ };
109
+
110
+ static int relay_pack_data (int pack_objects_out , struct output_state * os )
111
+ {
112
+ /*
113
+ * We keep the last byte to ourselves
114
+ * in case we detect broken rev-list, so that we
115
+ * can leave the stream corrupted. This is
116
+ * unfortunate -- unpack-objects would happily
117
+ * accept a valid packdata with trailing garbage,
118
+ * so appending garbage after we pass all the
119
+ * pack data is not good enough to signal
120
+ * breakage to downstream.
121
+ */
122
+ ssize_t readsz ;
123
+
124
+ readsz = xread (pack_objects_out , os -> buffer + os -> used ,
125
+ sizeof (os -> buffer ) - os -> used );
126
+ if (readsz < 0 ) {
127
+ return readsz ;
128
+ }
129
+ os -> used += readsz ;
130
+
131
+ if (os -> used > 1 ) {
132
+ send_client_data (1 , os -> buffer , os -> used - 1 );
133
+ os -> buffer [0 ] = os -> buffer [os -> used - 1 ];
134
+ os -> used = 1 ;
135
+ } else {
136
+ send_client_data (1 , os -> buffer , os -> used );
137
+ os -> used = 0 ;
138
+ }
139
+
140
+ return readsz ;
141
+ }
142
+
105
143
static void create_pack_file (const struct object_array * have_obj ,
106
144
const struct object_array * want_obj )
107
145
{
108
146
struct child_process pack_objects = CHILD_PROCESS_INIT ;
109
- char data [8193 ], progress [128 ];
147
+ struct output_state output_state = {0 };
148
+ char progress [128 ];
110
149
char abort_msg [] = "aborting due to possible repository "
111
150
"corruption on the remote side." ;
112
- int buffered = -1 ;
113
151
ssize_t sz ;
114
152
int i ;
115
153
FILE * pipe_fd ;
@@ -239,39 +277,15 @@ static void create_pack_file(const struct object_array *have_obj,
239
277
continue ;
240
278
}
241
279
if (0 <= pu && (pfd [pu ].revents & (POLLIN |POLLHUP ))) {
242
- /* Data ready; we keep the last byte to ourselves
243
- * in case we detect broken rev-list, so that we
244
- * can leave the stream corrupted. This is
245
- * unfortunate -- unpack-objects would happily
246
- * accept a valid packdata with trailing garbage,
247
- * so appending garbage after we pass all the
248
- * pack data is not good enough to signal
249
- * breakage to downstream.
250
- */
251
- char * cp = data ;
252
- ssize_t outsz = 0 ;
253
- if (0 <= buffered ) {
254
- * cp ++ = buffered ;
255
- outsz ++ ;
256
- }
257
- sz = xread (pack_objects .out , cp ,
258
- sizeof (data ) - outsz );
259
- if (0 < sz )
260
- ;
261
- else if (sz == 0 ) {
280
+ int result = relay_pack_data (pack_objects .out ,
281
+ & output_state );
282
+
283
+ if (result == 0 ) {
262
284
close (pack_objects .out );
263
285
pack_objects .out = -1 ;
264
- }
265
- else
286
+ } else if (result < 0 ) {
266
287
goto fail ;
267
- sz += outsz ;
268
- if (1 < sz ) {
269
- buffered = data [sz - 1 ] & 0xFF ;
270
- sz -- ;
271
288
}
272
- else
273
- buffered = -1 ;
274
- send_client_data (1 , data , sz );
275
289
}
276
290
277
291
/*
@@ -296,9 +310,8 @@ static void create_pack_file(const struct object_array *have_obj,
296
310
}
297
311
298
312
/* flush the data */
299
- if (0 <= buffered ) {
300
- data [0 ] = buffered ;
301
- send_client_data (1 , data , 1 );
313
+ if (output_state .used > 0 ) {
314
+ send_client_data (1 , output_state .buffer , output_state .used );
302
315
fprintf (stderr , "flushed.\n" );
303
316
}
304
317
if (use_sideband )
0 commit comments