http*: add http_get_info_packs
http-push.c and http-walker.c no longer have to use fetch_index or setup_index; they simply need to use http_get_info_packs, a new http method, in their fetch_indices implementations. Move fetch_index() and rename to fetch_pack_index() in http.c; this method is not meant to be used outside of http.c. It invokes end_url_with_slash with base_url; apart from that change, the code is identical. Move setup_index() and rename to fetch_and_setup_pack_index() in http.c; this method is not meant to be used outside of http.c. Do not immediately set ret to 0 in http-walker.c::fetch_indices(); instead do it in the HTTP_MISSING_TARGET case, to make it clear that the HTTP_OK and HTTP_MISSING_TARGET cases both return 0. Signed-off-by: Tay Ray Chuan <rctay89@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
9af5abd993
commit
b8caac2b8a
175
http-push.c
175
http-push.c
@ -953,184 +953,23 @@ static int add_send_request(struct object *obj, struct remote_lock *lock)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fetch_index(unsigned char *sha1)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
char *hex = xstrdup(sha1_to_hex(sha1));
|
|
||||||
char *filename;
|
|
||||||
char *url;
|
|
||||||
char tmpfile[PATH_MAX];
|
|
||||||
long prev_posn = 0;
|
|
||||||
char range[RANGE_HEADER_SIZE];
|
|
||||||
struct curl_slist *range_header = NULL;
|
|
||||||
|
|
||||||
FILE *indexfile;
|
|
||||||
struct active_request_slot *slot;
|
|
||||||
struct slot_results results;
|
|
||||||
|
|
||||||
/* Don't use the index if the pack isn't there */
|
|
||||||
url = xmalloc(strlen(repo->url) + 64);
|
|
||||||
sprintf(url, "%sobjects/pack/pack-%s.pack", repo->url, hex);
|
|
||||||
slot = get_active_slot();
|
|
||||||
slot->results = &results;
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
|
|
||||||
if (start_active_slot(slot)) {
|
|
||||||
run_active_slot(slot);
|
|
||||||
if (results.curl_result != CURLE_OK) {
|
|
||||||
ret = error("Unable to verify pack %s is available",
|
|
||||||
hex);
|
|
||||||
goto cleanup_pack;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = error("Unable to start request");
|
|
||||||
goto cleanup_pack;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_pack_index(sha1)) {
|
|
||||||
ret = 0;
|
|
||||||
goto cleanup_pack;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (push_verbosely)
|
|
||||||
fprintf(stderr, "Getting index for pack %s\n", hex);
|
|
||||||
|
|
||||||
sprintf(url, "%sobjects/pack/pack-%s.idx", repo->url, hex);
|
|
||||||
|
|
||||||
filename = sha1_pack_index_name(sha1);
|
|
||||||
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
|
|
||||||
indexfile = fopen(tmpfile, "a");
|
|
||||||
if (!indexfile) {
|
|
||||||
ret = error("Unable to open local file %s for pack index",
|
|
||||||
tmpfile);
|
|
||||||
goto cleanup_pack;
|
|
||||||
}
|
|
||||||
|
|
||||||
slot = get_active_slot();
|
|
||||||
slot->results = &results;
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
|
|
||||||
slot->local = indexfile;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If there is data present from a previous transfer attempt,
|
|
||||||
* resume where it left off
|
|
||||||
*/
|
|
||||||
prev_posn = ftell(indexfile);
|
|
||||||
if (prev_posn>0) {
|
|
||||||
if (push_verbosely)
|
|
||||||
fprintf(stderr,
|
|
||||||
"Resuming fetch of index for pack %s at byte %ld\n",
|
|
||||||
hex, prev_posn);
|
|
||||||
sprintf(range, "Range: bytes=%ld-", prev_posn);
|
|
||||||
range_header = curl_slist_append(range_header, range);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start_active_slot(slot)) {
|
|
||||||
run_active_slot(slot);
|
|
||||||
if (results.curl_result != CURLE_OK) {
|
|
||||||
ret = error("Unable to get pack index %s\n%s", url,
|
|
||||||
curl_errorstr);
|
|
||||||
goto cleanup_index;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = error("Unable to start request");
|
|
||||||
goto cleanup_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = move_temp_to_file(tmpfile, filename);
|
|
||||||
|
|
||||||
cleanup_index:
|
|
||||||
fclose(indexfile);
|
|
||||||
slot->local = NULL;
|
|
||||||
cleanup_pack:
|
|
||||||
free(url);
|
|
||||||
free(hex);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int setup_index(unsigned char *sha1)
|
|
||||||
{
|
|
||||||
struct packed_git *new_pack;
|
|
||||||
|
|
||||||
if (fetch_index(sha1))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
new_pack = parse_pack_index(sha1);
|
|
||||||
if (!new_pack)
|
|
||||||
return -1; /* parse_pack_index() already issued error message */
|
|
||||||
new_pack->next = repo->packs;
|
|
||||||
repo->packs = new_pack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fetch_indices(void)
|
static int fetch_indices(void)
|
||||||
{
|
{
|
||||||
unsigned char sha1[20];
|
int ret;
|
||||||
char *url;
|
|
||||||
struct strbuf buffer = STRBUF_INIT;
|
|
||||||
char *data;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
struct active_request_slot *slot;
|
|
||||||
struct slot_results results;
|
|
||||||
|
|
||||||
if (push_verbosely)
|
if (push_verbosely)
|
||||||
fprintf(stderr, "Getting pack list\n");
|
fprintf(stderr, "Getting pack list\n");
|
||||||
|
|
||||||
url = xmalloc(strlen(repo->url) + 20);
|
switch (http_get_info_packs(repo->url, &repo->packs)) {
|
||||||
sprintf(url, "%sobjects/info/packs", repo->url);
|
case HTTP_OK:
|
||||||
|
case HTTP_MISSING_TARGET:
|
||||||
slot = get_active_slot();
|
ret = 0;
|
||||||
slot->results = &results;
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
|
|
||||||
if (start_active_slot(slot)) {
|
|
||||||
run_active_slot(slot);
|
|
||||||
if (results.curl_result != CURLE_OK) {
|
|
||||||
strbuf_release(&buffer);
|
|
||||||
free(url);
|
|
||||||
if (results.http_code == 404)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return error("%s", curl_errorstr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
strbuf_release(&buffer);
|
|
||||||
free(url);
|
|
||||||
return error("Unable to start request");
|
|
||||||
}
|
|
||||||
free(url);
|
|
||||||
|
|
||||||
data = buffer.buf;
|
|
||||||
while (i < buffer.len) {
|
|
||||||
switch (data[i]) {
|
|
||||||
case 'P':
|
|
||||||
i++;
|
|
||||||
if (i + 52 < buffer.len &&
|
|
||||||
!prefixcmp(data + i, " pack-") &&
|
|
||||||
!prefixcmp(data + i + 46, ".pack\n")) {
|
|
||||||
get_sha1_hex(data + i + 6, sha1);
|
|
||||||
setup_index(sha1);
|
|
||||||
i += 51;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
while (data[i] != '\n')
|
ret = -1;
|
||||||
i++;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strbuf_release(&buffer);
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void one_remote_object(const char *hex)
|
static void one_remote_object(const char *hex)
|
||||||
|
180
http-walker.c
180
http-walker.c
@ -368,124 +368,6 @@ static void prefetch(struct walker *walker, unsigned char *sha1)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fetch_index(struct walker *walker, struct alt_base *repo, unsigned char *sha1)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
char *hex = xstrdup(sha1_to_hex(sha1));
|
|
||||||
char *filename;
|
|
||||||
char *url;
|
|
||||||
char tmpfile[PATH_MAX];
|
|
||||||
long prev_posn = 0;
|
|
||||||
char range[RANGE_HEADER_SIZE];
|
|
||||||
struct curl_slist *range_header = NULL;
|
|
||||||
|
|
||||||
FILE *indexfile;
|
|
||||||
struct active_request_slot *slot;
|
|
||||||
struct slot_results results;
|
|
||||||
|
|
||||||
/* Don't use the index if the pack isn't there */
|
|
||||||
url = xmalloc(strlen(repo->base) + 64);
|
|
||||||
sprintf(url, "%s/objects/pack/pack-%s.pack", repo->base, hex);
|
|
||||||
slot = get_active_slot();
|
|
||||||
slot->results = &results;
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
|
|
||||||
if (start_active_slot(slot)) {
|
|
||||||
run_active_slot(slot);
|
|
||||||
if (results.curl_result != CURLE_OK) {
|
|
||||||
ret = error("Unable to verify pack %s is available",
|
|
||||||
hex);
|
|
||||||
goto cleanup_pack;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = error("Unable to start request");
|
|
||||||
goto cleanup_pack;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_pack_index(sha1)) {
|
|
||||||
ret = 0;
|
|
||||||
goto cleanup_pack;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (walker->get_verbosely)
|
|
||||||
fprintf(stderr, "Getting index for pack %s\n", hex);
|
|
||||||
|
|
||||||
sprintf(url, "%s/objects/pack/pack-%s.idx", repo->base, hex);
|
|
||||||
|
|
||||||
filename = sha1_pack_index_name(sha1);
|
|
||||||
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
|
|
||||||
indexfile = fopen(tmpfile, "a");
|
|
||||||
if (!indexfile) {
|
|
||||||
ret = error("Unable to open local file %s for pack index",
|
|
||||||
tmpfile);
|
|
||||||
goto cleanup_pack;
|
|
||||||
}
|
|
||||||
|
|
||||||
slot = get_active_slot();
|
|
||||||
slot->results = &results;
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
|
|
||||||
slot->local = indexfile;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If there is data present from a previous transfer attempt,
|
|
||||||
* resume where it left off
|
|
||||||
*/
|
|
||||||
prev_posn = ftell(indexfile);
|
|
||||||
if (prev_posn>0) {
|
|
||||||
if (walker->get_verbosely)
|
|
||||||
fprintf(stderr,
|
|
||||||
"Resuming fetch of index for pack %s at byte %ld\n",
|
|
||||||
hex, prev_posn);
|
|
||||||
sprintf(range, "Range: bytes=%ld-", prev_posn);
|
|
||||||
range_header = curl_slist_append(range_header, range);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start_active_slot(slot)) {
|
|
||||||
run_active_slot(slot);
|
|
||||||
if (results.curl_result != CURLE_OK) {
|
|
||||||
ret = error("Unable to get pack index %s\n%s", url,
|
|
||||||
curl_errorstr);
|
|
||||||
goto cleanup_index;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = error("Unable to start request");
|
|
||||||
goto cleanup_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = move_temp_to_file(tmpfile, filename);
|
|
||||||
|
|
||||||
cleanup_index:
|
|
||||||
fclose(indexfile);
|
|
||||||
slot->local = NULL;
|
|
||||||
cleanup_pack:
|
|
||||||
free(url);
|
|
||||||
free(hex);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int setup_index(struct walker *walker, struct alt_base *repo, unsigned char *sha1)
|
|
||||||
{
|
|
||||||
struct packed_git *new_pack;
|
|
||||||
if (has_pack_file(sha1))
|
|
||||||
return 0; /* don't list this as something we can get */
|
|
||||||
|
|
||||||
if (fetch_index(walker, repo, sha1))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
new_pack = parse_pack_index(sha1);
|
|
||||||
if (!new_pack)
|
|
||||||
return -1; /* parse_pack_index() already issued error message */
|
|
||||||
new_pack->next = repo->packs;
|
|
||||||
repo->packs = new_pack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void process_alternates_response(void *callback_data)
|
static void process_alternates_response(void *callback_data)
|
||||||
{
|
{
|
||||||
struct alternates_request *alt_req =
|
struct alternates_request *alt_req =
|
||||||
@ -684,15 +566,7 @@ static void fetch_alternates(struct walker *walker, const char *base)
|
|||||||
|
|
||||||
static int fetch_indices(struct walker *walker, struct alt_base *repo)
|
static int fetch_indices(struct walker *walker, struct alt_base *repo)
|
||||||
{
|
{
|
||||||
unsigned char sha1[20];
|
int ret;
|
||||||
char *url;
|
|
||||||
struct strbuf buffer = STRBUF_INIT;
|
|
||||||
char *data;
|
|
||||||
int i = 0;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
struct active_request_slot *slot;
|
|
||||||
struct slot_results results;
|
|
||||||
|
|
||||||
if (repo->got_indices)
|
if (repo->got_indices)
|
||||||
return 0;
|
return 0;
|
||||||
@ -700,57 +574,17 @@ static int fetch_indices(struct walker *walker, struct alt_base *repo)
|
|||||||
if (walker->get_verbosely)
|
if (walker->get_verbosely)
|
||||||
fprintf(stderr, "Getting pack list for %s\n", repo->base);
|
fprintf(stderr, "Getting pack list for %s\n", repo->base);
|
||||||
|
|
||||||
url = xmalloc(strlen(repo->base) + 21);
|
switch (http_get_info_packs(repo->base, &repo->packs)) {
|
||||||
sprintf(url, "%s/objects/info/packs", repo->base);
|
case HTTP_OK:
|
||||||
|
case HTTP_MISSING_TARGET:
|
||||||
slot = get_active_slot();
|
|
||||||
slot->results = &results;
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
|
||||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
|
|
||||||
if (start_active_slot(slot)) {
|
|
||||||
run_active_slot(slot);
|
|
||||||
if (results.curl_result != CURLE_OK) {
|
|
||||||
if (missing_target(&results)) {
|
|
||||||
repo->got_indices = 1;
|
repo->got_indices = 1;
|
||||||
goto cleanup;
|
ret = 0;
|
||||||
} else {
|
|
||||||
repo->got_indices = 0;
|
|
||||||
ret = error("%s", curl_errorstr);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
repo->got_indices = 0;
|
|
||||||
ret = error("Unable to start request");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = buffer.buf;
|
|
||||||
while (i < buffer.len) {
|
|
||||||
switch (data[i]) {
|
|
||||||
case 'P':
|
|
||||||
i++;
|
|
||||||
if (i + 52 <= buffer.len &&
|
|
||||||
!prefixcmp(data + i, " pack-") &&
|
|
||||||
!prefixcmp(data + i + 46, ".pack\n")) {
|
|
||||||
get_sha1_hex(data + i + 6, sha1);
|
|
||||||
setup_index(walker, repo, sha1);
|
|
||||||
i += 51;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
while (i < buffer.len && data[i] != '\n')
|
repo->got_indices = 0;
|
||||||
i++;
|
ret = -1;
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
repo->got_indices = 1;
|
|
||||||
cleanup:
|
|
||||||
strbuf_release(&buffer);
|
|
||||||
free(url);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
164
http.c
164
http.c
@ -790,3 +790,167 @@ int http_fetch_ref(const char *base, struct ref *ref)
|
|||||||
free(url);
|
free(url);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helpers for fetching packs */
|
||||||
|
static int fetch_pack_index(unsigned char *sha1, const char *base_url)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
char *hex = xstrdup(sha1_to_hex(sha1));
|
||||||
|
char *filename;
|
||||||
|
char *url;
|
||||||
|
char tmpfile[PATH_MAX];
|
||||||
|
long prev_posn = 0;
|
||||||
|
char range[RANGE_HEADER_SIZE];
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
struct curl_slist *range_header = NULL;
|
||||||
|
|
||||||
|
FILE *indexfile;
|
||||||
|
struct active_request_slot *slot;
|
||||||
|
struct slot_results results;
|
||||||
|
|
||||||
|
/* Don't use the index if the pack isn't there */
|
||||||
|
end_url_with_slash(&buf, base_url);
|
||||||
|
strbuf_addf(&buf, "objects/pack/pack-%s.pack", hex);
|
||||||
|
url = strbuf_detach(&buf, 0);
|
||||||
|
|
||||||
|
slot = get_active_slot();
|
||||||
|
slot->results = &results;
|
||||||
|
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
||||||
|
curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
|
||||||
|
if (start_active_slot(slot)) {
|
||||||
|
run_active_slot(slot);
|
||||||
|
if (results.curl_result != CURLE_OK) {
|
||||||
|
ret = error("Unable to verify pack %s is available",
|
||||||
|
hex);
|
||||||
|
goto cleanup_pack;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = error("Unable to start request");
|
||||||
|
goto cleanup_pack;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_pack_index(sha1)) {
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup_pack;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (http_is_verbose)
|
||||||
|
fprintf(stderr, "Getting index for pack %s\n", hex);
|
||||||
|
|
||||||
|
end_url_with_slash(&buf, base_url);
|
||||||
|
strbuf_addf(&buf, "objects/pack/pack-%s.idx", hex);
|
||||||
|
url = strbuf_detach(&buf, NULL);
|
||||||
|
|
||||||
|
filename = sha1_pack_index_name(sha1);
|
||||||
|
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
|
||||||
|
indexfile = fopen(tmpfile, "a");
|
||||||
|
if (!indexfile) {
|
||||||
|
ret = error("Unable to open local file %s for pack index",
|
||||||
|
tmpfile);
|
||||||
|
goto cleanup_pack;
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = get_active_slot();
|
||||||
|
slot->results = &results;
|
||||||
|
curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
|
||||||
|
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
|
||||||
|
curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
|
||||||
|
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
|
||||||
|
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
|
||||||
|
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
|
||||||
|
slot->local = indexfile;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is data present from a previous transfer attempt,
|
||||||
|
* resume where it left off
|
||||||
|
*/
|
||||||
|
prev_posn = ftell(indexfile);
|
||||||
|
if (prev_posn>0) {
|
||||||
|
if (http_is_verbose)
|
||||||
|
fprintf(stderr,
|
||||||
|
"Resuming fetch of index for pack %s at byte %ld\n",
|
||||||
|
hex, prev_posn);
|
||||||
|
sprintf(range, "Range: bytes=%ld-", prev_posn);
|
||||||
|
range_header = curl_slist_append(range_header, range);
|
||||||
|
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_active_slot(slot)) {
|
||||||
|
run_active_slot(slot);
|
||||||
|
if (results.curl_result != CURLE_OK) {
|
||||||
|
ret = error("Unable to get pack index %s\n%s",
|
||||||
|
url, curl_errorstr);
|
||||||
|
goto cleanup_index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = error("Unable to start request");
|
||||||
|
goto cleanup_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = move_temp_to_file(tmpfile, filename);
|
||||||
|
|
||||||
|
cleanup_index:
|
||||||
|
fclose(indexfile);
|
||||||
|
slot->local = NULL;
|
||||||
|
cleanup_pack:
|
||||||
|
free(hex);
|
||||||
|
free(url);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fetch_and_setup_pack_index(struct packed_git **packs_head,
|
||||||
|
unsigned char *sha1, const char *base_url)
|
||||||
|
{
|
||||||
|
struct packed_git *new_pack;
|
||||||
|
|
||||||
|
if (fetch_pack_index(sha1, base_url))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
new_pack = parse_pack_index(sha1);
|
||||||
|
if (!new_pack)
|
||||||
|
return -1; /* parse_pack_index() already issued error message */
|
||||||
|
new_pack->next = *packs_head;
|
||||||
|
*packs_head = new_pack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_get_info_packs(const char *base_url, struct packed_git **packs_head)
|
||||||
|
{
|
||||||
|
int ret = 0, i = 0;
|
||||||
|
char *url, *data;
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
unsigned char sha1[20];
|
||||||
|
|
||||||
|
end_url_with_slash(&buf, base_url);
|
||||||
|
strbuf_addstr(&buf, "objects/info/packs");
|
||||||
|
url = strbuf_detach(&buf, NULL);
|
||||||
|
|
||||||
|
ret = http_get_strbuf(url, &buf, HTTP_NO_CACHE);
|
||||||
|
if (ret != HTTP_OK)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
data = buf.buf;
|
||||||
|
while (i < buf.len) {
|
||||||
|
switch (data[i]) {
|
||||||
|
case 'P':
|
||||||
|
i++;
|
||||||
|
if (i + 52 <= buf.len &&
|
||||||
|
!prefixcmp(data + i, " pack-") &&
|
||||||
|
!prefixcmp(data + i + 46, ".pack\n")) {
|
||||||
|
get_sha1_hex(data + i + 6, sha1);
|
||||||
|
fetch_and_setup_pack_index(packs_head, sha1,
|
||||||
|
base_url);
|
||||||
|
i += 51;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
while (i < buf.len && data[i] != '\n')
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
free(url);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
4
http.h
4
http.h
@ -146,4 +146,8 @@ int http_error(const char *url, int ret);
|
|||||||
|
|
||||||
extern int http_fetch_ref(const char *base, struct ref *ref);
|
extern int http_fetch_ref(const char *base, struct ref *ref);
|
||||||
|
|
||||||
|
/* Helpers for fetching packs */
|
||||||
|
extern int http_get_info_packs(const char *base_url,
|
||||||
|
struct packed_git **packs_head);
|
||||||
|
|
||||||
#endif /* HTTP_H */
|
#endif /* HTTP_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user