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>
This commit is contained in:
Jonathan Tan 2020-06-10 13:57:21 -07:00 committed by Junio C Hamano
parent cd8402e0fd
commit acaaca7d70

View File

@ -173,13 +173,52 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
return 0;
}
struct output_state {
char buffer[8193];
int used;
};
static int relay_pack_data(int pack_objects_out, struct output_state *os,
int use_sideband)
{
/*
* We keep the last byte to ourselves
* in case we detect broken rev-list, so that we
* can leave the stream corrupted. This is
* unfortunate -- unpack-objects would happily
* accept a valid packdata with trailing garbage,
* so appending garbage after we pass all the
* pack data is not good enough to signal
* breakage to downstream.
*/
ssize_t readsz;
readsz = xread(pack_objects_out, os->buffer + os->used,
sizeof(os->buffer) - os->used);
if (readsz < 0) {
return readsz;
}
os->used += readsz;
if (os->used > 1) {
send_client_data(1, os->buffer, os->used - 1, use_sideband);
os->buffer[0] = os->buffer[os->used - 1];
os->used = 1;
} else {
send_client_data(1, os->buffer, os->used, use_sideband);
os->used = 0;
}
return readsz;
}
static void create_pack_file(struct upload_pack_data *pack_data)
{
struct child_process pack_objects = CHILD_PROCESS_INIT;
char data[8193], progress[128];
struct output_state output_state = { { 0 } };
char progress[128];
char abort_msg[] = "aborting due to possible repository "
"corruption on the remote side.";
int buffered = -1;
ssize_t sz;
int i;
FILE *pipe_fd;
@ -312,40 +351,16 @@ static void create_pack_file(struct upload_pack_data *pack_data)
continue;
}
if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) {
/* Data ready; we keep the last byte to ourselves
* in case we detect broken rev-list, so that we
* can leave the stream corrupted. This is
* unfortunate -- unpack-objects would happily
* accept a valid packdata with trailing garbage,
* so appending garbage after we pass all the
* pack data is not good enough to signal
* breakage to downstream.
*/
char *cp = data;
ssize_t outsz = 0;
if (0 <= buffered) {
*cp++ = buffered;
outsz++;
}
sz = xread(pack_objects.out, cp,
sizeof(data) - outsz);
if (0 < sz)
;
else if (sz == 0) {
int result = relay_pack_data(pack_objects.out,
&output_state,
pack_data->use_sideband);
if (result == 0) {
close(pack_objects.out);
pack_objects.out = -1;
}
else
} else if (result < 0) {
goto fail;
sz += outsz;
if (1 < sz) {
buffered = data[sz-1] & 0xFF;
sz--;
}
else
buffered = -1;
send_client_data(1, data, sz,
pack_data->use_sideband);
}
/*
@ -370,9 +385,8 @@ static void create_pack_file(struct upload_pack_data *pack_data)
}
/* flush the data */
if (0 <= buffered) {
data[0] = buffered;
send_client_data(1, data, 1,
if (output_state.used > 0) {
send_client_data(1, output_state.buffer, output_state.used,
pack_data->use_sideband);
fprintf(stderr, "flushed.\n");
}