Merge branch 'jt/cdn-offload'

The "fetch/clone" protocol has been updated to allow the server to
instruct the clients to grab pre-packaged packfile(s) in addition
to the packed object data coming over the wire.

* jt/cdn-offload:
  upload-pack: fix a sparse '0 as NULL pointer' warning
  upload-pack: send part of packfile response as uri
  fetch-pack: support more than one pack lockfile
  upload-pack: refactor reading of pack-objects out
  Documentation: add Packfile URIs design doc
  Documentation: order protocol v2 sections
  http-fetch: support fetching packfiles by URL
  http-fetch: refactor into function
  http: refactor finish_http_pack_request()
  http: use --stdin when indexing dumb HTTP pack
This commit is contained in:
Junio C Hamano
2020-06-25 12:27:47 -07:00
19 changed files with 765 additions and 182 deletions

92
http.c
View File

@ -2261,70 +2261,74 @@ void release_http_pack_request(struct http_pack_request *preq)
int finish_http_pack_request(struct http_pack_request *preq)
{
struct packed_git **lst;
struct packed_git *p = preq->target;
char *tmp_idx;
size_t len;
struct child_process ip = CHILD_PROCESS_INIT;
close_pack_index(p);
int tmpfile_fd;
int ret = 0;
fclose(preq->packfile);
preq->packfile = NULL;
lst = preq->lst;
tmpfile_fd = xopen(preq->tmpfile.buf, O_RDONLY);
argv_array_push(&ip.args, "index-pack");
argv_array_push(&ip.args, "--stdin");
ip.git_cmd = 1;
ip.in = tmpfile_fd;
if (preq->generate_keep) {
argv_array_pushf(&ip.args, "--keep=git %"PRIuMAX,
(uintmax_t)getpid());
ip.out = 0;
} else {
ip.no_stdout = 1;
}
if (run_command(&ip)) {
ret = -1;
goto cleanup;
}
cleanup:
close(tmpfile_fd);
unlink(preq->tmpfile.buf);
return ret;
}
void http_install_packfile(struct packed_git *p,
struct packed_git **list_to_remove_from)
{
struct packed_git **lst = list_to_remove_from;
while (*lst != p)
lst = &((*lst)->next);
*lst = (*lst)->next;
if (!strip_suffix(preq->tmpfile.buf, ".pack.temp", &len))
BUG("pack tmpfile does not end in .pack.temp?");
tmp_idx = xstrfmt("%.*s.idx.temp", (int)len, preq->tmpfile.buf);
argv_array_push(&ip.args, "index-pack");
argv_array_pushl(&ip.args, "-o", tmp_idx, NULL);
argv_array_push(&ip.args, preq->tmpfile.buf);
ip.git_cmd = 1;
ip.no_stdin = 1;
ip.no_stdout = 1;
if (run_command(&ip)) {
unlink(preq->tmpfile.buf);
unlink(tmp_idx);
free(tmp_idx);
return -1;
}
unlink(sha1_pack_index_name(p->hash));
if (finalize_object_file(preq->tmpfile.buf, sha1_pack_name(p->hash))
|| finalize_object_file(tmp_idx, sha1_pack_index_name(p->hash))) {
free(tmp_idx);
return -1;
}
install_packed_git(the_repository, p);
free(tmp_idx);
return 0;
}
struct http_pack_request *new_http_pack_request(
struct packed_git *target, const char *base_url)
const unsigned char *packed_git_hash, const char *base_url) {
struct strbuf buf = STRBUF_INIT;
end_url_with_slash(&buf, base_url);
strbuf_addf(&buf, "objects/pack/pack-%s.pack",
hash_to_hex(packed_git_hash));
return new_direct_http_pack_request(packed_git_hash,
strbuf_detach(&buf, NULL));
}
struct http_pack_request *new_direct_http_pack_request(
const unsigned char *packed_git_hash, char *url)
{
off_t prev_posn = 0;
struct strbuf buf = STRBUF_INIT;
struct http_pack_request *preq;
preq = xcalloc(1, sizeof(*preq));
strbuf_init(&preq->tmpfile, 0);
preq->target = target;
end_url_with_slash(&buf, base_url);
strbuf_addf(&buf, "objects/pack/pack-%s.pack",
hash_to_hex(target->hash));
preq->url = strbuf_detach(&buf, NULL);
preq->url = url;
strbuf_addf(&preq->tmpfile, "%s.temp", sha1_pack_name(target->hash));
strbuf_addf(&preq->tmpfile, "%s.temp", sha1_pack_name(packed_git_hash));
preq->packfile = fopen(preq->tmpfile.buf, "a");
if (!preq->packfile) {
error("Unable to open local file %s for pack",
@ -2348,7 +2352,7 @@ struct http_pack_request *new_http_pack_request(
if (http_is_verbose)
fprintf(stderr,
"Resuming fetch of pack %s at byte %"PRIuMAX"\n",
hash_to_hex(target->hash),
hash_to_hex(packed_git_hash),
(uintmax_t)prev_posn);
http_opt_request_remainder(preq->slot->curl, prev_posn);
}