upload-pack: generate packfiles via the object database
When serving a fetch, git-upload-pack(1) spawns git-pack-objects(1) directly to generate the packfile that gets sent to the client. This hard-codes the assumption that the object database is able to serve packfiles via git-pack-objects(1), which is specific to the "files" backend. Convert git-upload-pack(1) to instead use the pack generation interface of the object database. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>main
parent
a316d615da
commit
f0de4ab248
123
upload-pack.c
123
upload-pack.c
|
|
@ -197,11 +197,11 @@ static void send_client_data(int fd, const char *data, ssize_t sz,
|
|||
write_or_die(fd, data, sz);
|
||||
}
|
||||
|
||||
static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
|
||||
static int append_one_shallow(const struct commit_graft *graft, void *cb_data)
|
||||
{
|
||||
FILE *fp = cb_data;
|
||||
struct oid_array *shallows = cb_data;
|
||||
if (graft->nr_parent == -1)
|
||||
fprintf(fp, "--shallow %s\n", oid_to_hex(&graft->oid));
|
||||
oid_array_append(shallows, &graft->oid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -299,7 +299,8 @@ static int relay_pack_data(int pack_objects_out, struct output_state *os,
|
|||
static void create_pack_file(struct upload_pack_data *pack_data,
|
||||
const struct string_list *uri_protocols)
|
||||
{
|
||||
struct child_process pack_objects = CHILD_PROCESS_INIT;
|
||||
struct odb_generate_pack_options opts = ODB_GENERATE_PACK_OPTIONS_INIT;
|
||||
struct odb_pack_generator *generator;
|
||||
struct output_state *output_state = xcalloc(1, sizeof(struct output_state));
|
||||
char progress[128];
|
||||
char abort_msg[] = "aborting due to possible repository "
|
||||
|
|
@ -307,78 +308,42 @@ static void create_pack_file(struct upload_pack_data *pack_data,
|
|||
uint64_t last_sent_ms = 0;
|
||||
ssize_t sz;
|
||||
int i;
|
||||
FILE *pipe_fd;
|
||||
|
||||
if (!pack_data->pack_objects_hook)
|
||||
pack_objects.git_cmd = 1;
|
||||
else {
|
||||
strvec_push(&pack_objects.args, pack_data->pack_objects_hook);
|
||||
strvec_push(&pack_objects.args, "git");
|
||||
pack_objects.use_shell = 1;
|
||||
}
|
||||
|
||||
if (pack_data->shallow_nr) {
|
||||
strvec_push(&pack_objects.args, "--shallow-file");
|
||||
strvec_push(&pack_objects.args, "");
|
||||
for_each_commit_graft(append_one_shallow, &opts.shallows);
|
||||
opts.shallow = 1;
|
||||
}
|
||||
strvec_push(&pack_objects.args, "pack-objects");
|
||||
strvec_push(&pack_objects.args, "--revs");
|
||||
if (pack_data->use_thin_pack)
|
||||
strvec_push(&pack_objects.args, "--thin");
|
||||
|
||||
strvec_push(&pack_objects.args, "--stdout");
|
||||
if (pack_data->shallow_nr)
|
||||
strvec_push(&pack_objects.args, "--shallow");
|
||||
if (!pack_data->no_progress)
|
||||
strvec_push(&pack_objects.args, "--progress");
|
||||
if (pack_data->use_ofs_delta)
|
||||
strvec_push(&pack_objects.args, "--delta-base-offset");
|
||||
if (pack_data->use_include_tag)
|
||||
strvec_push(&pack_objects.args, "--include-tag");
|
||||
if (repo_has_accepted_promisor_remote(the_repository))
|
||||
strvec_push(&pack_objects.args, "--missing=allow-promisor");
|
||||
if (pack_data->filter_options.choice) {
|
||||
const char *spec =
|
||||
expand_list_objects_filter_spec(&pack_data->filter_options);
|
||||
strvec_pushf(&pack_objects.args, "--filter=%s", spec);
|
||||
}
|
||||
if (uri_protocols) {
|
||||
for (i = 0; i < uri_protocols->nr; i++)
|
||||
strvec_pushf(&pack_objects.args, "--uri-protocol=%s",
|
||||
uri_protocols->items[i].string);
|
||||
}
|
||||
|
||||
pack_objects.in = -1;
|
||||
pack_objects.out = -1;
|
||||
pack_objects.err = -1;
|
||||
pack_objects.clean_on_exit = 1;
|
||||
|
||||
if (start_command(&pack_objects))
|
||||
die("git upload-pack: unable to fork git-pack-objects");
|
||||
|
||||
pipe_fd = xfdopen(pack_objects.in, "w");
|
||||
|
||||
if (pack_data->shallow_nr)
|
||||
for_each_commit_graft(write_one_shallow, pipe_fd);
|
||||
|
||||
for (i = 0; i < pack_data->want_obj.nr; i++)
|
||||
fprintf(pipe_fd, "%s\n",
|
||||
oid_to_hex(&pack_data->want_obj.objects[i].item->oid));
|
||||
fprintf(pipe_fd, "--not\n");
|
||||
oid_array_append(&opts.wants,
|
||||
&pack_data->want_obj.objects[i].item->oid);
|
||||
for (i = 0; i < pack_data->have_obj.nr; i++)
|
||||
fprintf(pipe_fd, "%s\n",
|
||||
oid_to_hex(&pack_data->have_obj.objects[i].item->oid));
|
||||
oid_array_append(&opts.haves,
|
||||
&pack_data->have_obj.objects[i].item->oid);
|
||||
for (i = 0; i < pack_data->extra_edge_obj.nr; i++)
|
||||
fprintf(pipe_fd, "%s\n",
|
||||
oid_to_hex(&pack_data->extra_edge_obj.objects[i].item->oid));
|
||||
fprintf(pipe_fd, "\n");
|
||||
fflush(pipe_fd);
|
||||
fclose(pipe_fd);
|
||||
oid_array_append(&opts.haves,
|
||||
&pack_data->extra_edge_obj.objects[i].item->oid);
|
||||
|
||||
/* We read from pack_objects.err to capture stderr output for
|
||||
* progress bar, and pack_objects.out to capture the pack data.
|
||||
opts.thin = pack_data->use_thin_pack;
|
||||
if (!pack_data->no_progress)
|
||||
opts.progress = ODB_GENERATE_PACK_PROGRESS_STANDARD;
|
||||
opts.ofs_delta = pack_data->use_ofs_delta;
|
||||
opts.include_tag = pack_data->use_include_tag;
|
||||
opts.missing_allow_promisor = repo_has_accepted_promisor_remote(the_repository);
|
||||
if (pack_data->filter_options.choice)
|
||||
opts.filter_spec = expand_list_objects_filter_spec(&pack_data->filter_options);
|
||||
opts.uri_protocols = uri_protocols;
|
||||
opts.pack_objects_hook = pack_data->pack_objects_hook;
|
||||
opts.pack_fd = -1;
|
||||
opts.progress_fd = -1;
|
||||
|
||||
if (odb_generate_pack(the_repository->objects, &generator, &opts))
|
||||
die("git upload-pack: unable to generate pack");
|
||||
odb_generate_pack_options_release(&opts);
|
||||
|
||||
/*
|
||||
* We read from generator->err to capture stderr output for the
|
||||
* progress bar, and generator->out to capture the pack data.
|
||||
*/
|
||||
|
||||
while (1) {
|
||||
uint64_t now_ms = getnanotime() / 1000000;
|
||||
struct pollfd pfd[2];
|
||||
|
|
@ -393,14 +358,14 @@ static void create_pack_file(struct upload_pack_data *pack_data,
|
|||
pollsize = 0;
|
||||
pe = pu = -1;
|
||||
|
||||
if (0 <= pack_objects.out) {
|
||||
pfd[pollsize].fd = pack_objects.out;
|
||||
if (0 <= generator->out) {
|
||||
pfd[pollsize].fd = generator->out;
|
||||
pfd[pollsize].events = POLLIN;
|
||||
pu = pollsize;
|
||||
pollsize++;
|
||||
}
|
||||
if (0 <= pack_objects.err) {
|
||||
pfd[pollsize].fd = pack_objects.err;
|
||||
if (0 <= generator->err) {
|
||||
pfd[pollsize].fd = generator->err;
|
||||
pfd[pollsize].events = POLLIN;
|
||||
pe = pollsize;
|
||||
pollsize++;
|
||||
|
|
@ -437,15 +402,15 @@ static void create_pack_file(struct upload_pack_data *pack_data,
|
|||
/* Status ready; we ship that in the side-band
|
||||
* or dump to the standard error.
|
||||
*/
|
||||
sz = xread(pack_objects.err, progress,
|
||||
sz = xread(generator->err, progress,
|
||||
sizeof(progress));
|
||||
if (0 < sz) {
|
||||
send_client_data(2, progress, sz,
|
||||
pack_data->use_sideband);
|
||||
last_sent_ms = now_ms;
|
||||
} else if (sz == 0) {
|
||||
close(pack_objects.err);
|
||||
pack_objects.err = -1;
|
||||
close(generator->err);
|
||||
generator->err = -1;
|
||||
}
|
||||
else
|
||||
goto fail;
|
||||
|
|
@ -455,15 +420,15 @@ static void create_pack_file(struct upload_pack_data *pack_data,
|
|||
|
||||
if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) {
|
||||
bool did_send_data;
|
||||
int result = relay_pack_data(pack_objects.out,
|
||||
int result = relay_pack_data(generator->out,
|
||||
output_state,
|
||||
pack_data->use_sideband,
|
||||
!!uri_protocols,
|
||||
&did_send_data);
|
||||
|
||||
if (result == 0) {
|
||||
close(pack_objects.out);
|
||||
pack_objects.out = -1;
|
||||
close(generator->out);
|
||||
generator->out = -1;
|
||||
} else if (result < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -498,7 +463,7 @@ static void create_pack_file(struct upload_pack_data *pack_data,
|
|||
}
|
||||
}
|
||||
|
||||
if (finish_command(&pack_objects)) {
|
||||
if (odb_pack_generator_finish(generator)) {
|
||||
error("git upload-pack: git-pack-objects died with error.");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue