Skip to content

Commit a8d662e

Browse files
jonathantanmygitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6ad09e3 commit a8d662e

File tree

1 file changed

+47
-34
lines changed

1 file changed

+47
-34
lines changed

upload-pack.c

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,52 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
102102
return 0;
103103
}
104104

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+
105143
static void create_pack_file(const struct object_array *have_obj,
106144
const struct object_array *want_obj)
107145
{
108146
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];
110149
char abort_msg[] = "aborting due to possible repository "
111150
"corruption on the remote side.";
112-
int buffered = -1;
113151
ssize_t sz;
114152
int i;
115153
FILE *pipe_fd;
@@ -239,39 +277,15 @@ static void create_pack_file(const struct object_array *have_obj,
239277
continue;
240278
}
241279
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) {
262284
close(pack_objects.out);
263285
pack_objects.out = -1;
264-
}
265-
else
286+
} else if (result < 0) {
266287
goto fail;
267-
sz += outsz;
268-
if (1 < sz) {
269-
buffered = data[sz-1] & 0xFF;
270-
sz--;
271288
}
272-
else
273-
buffered = -1;
274-
send_client_data(1, data, sz);
275289
}
276290

277291
/*
@@ -296,9 +310,8 @@ static void create_pack_file(const struct object_array *have_obj,
296310
}
297311

298312
/* 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);
302315
fprintf(stderr, "flushed.\n");
303316
}
304317
if (use_sideband)

0 commit comments

Comments
 (0)