#include "cache.h"
#include "commit.h"
-#include "pack.h"
#include "tag.h"
#include "blob.h"
#include "http.h"
char filename[PATH_MAX];
char tmpfile[PATH_MAX];
int local_fileno;
- FILE *local_stream;
enum transfer_state state;
CURLcode curl_result;
char errorstr[CURL_ERROR_SIZE];
static void start_fetch_packed(struct transfer_request *request)
{
- char *url;
struct packed_git *target;
- FILE *packfile;
- char *filename;
- long prev_posn = 0;
- char range[RANGE_HEADER_SIZE];
- struct curl_slist *range_header = NULL;
struct transfer_request *check_request = request_queue_head;
- struct active_request_slot *slot;
+ struct http_pack_request *preq;
target = find_sha1_pack(request->obj->sha1, repo->packs);
if (!target) {
fprintf(stderr, "Fetching pack %s\n", sha1_to_hex(target->sha1));
fprintf(stderr, " which contains %s\n", sha1_to_hex(request->obj->sha1));
- filename = sha1_pack_name(target->sha1);
- snprintf(request->filename, sizeof(request->filename), "%s", filename);
- snprintf(request->tmpfile, sizeof(request->tmpfile),
- "%s.temp", filename);
-
- url = xmalloc(strlen(repo->url) + 64);
- sprintf(url, "%sobjects/pack/pack-%s.pack",
- repo->url, sha1_to_hex(target->sha1));
+ preq = new_http_pack_request(target, repo->url);
+ if (preq == NULL) {
+ release_http_pack_request(preq);
+ repo->can_update_info_refs = 0;
+ return;
+ }
+ preq->lst = &repo->packs;
/* Make sure there isn't another open request for this pack */
while (check_request) {
if (check_request->state == RUN_FETCH_PACKED &&
- !strcmp(check_request->url, url)) {
- free(url);
+ !strcmp(check_request->url, preq->url)) {
+ release_http_pack_request(preq);
release_request(request);
return;
}
check_request = check_request->next;
}
- packfile = fopen(request->tmpfile, "a");
- if (!packfile) {
- fprintf(stderr, "Unable to open local file %s for pack",
- request->tmpfile);
- repo->can_update_info_refs = 0;
- free(url);
- return;
- }
-
- slot = get_active_slot();
- slot->callback_func = process_response;
- slot->callback_data = request;
- request->slot = slot;
- request->local_stream = packfile;
- request->userData = target;
-
- request->url = url;
- curl_easy_setopt(slot->curl, CURLOPT_FILE, packfile);
- 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 = packfile;
-
- /*
- * If there is data present from a previous transfer attempt,
- * resume where it left off
- */
- prev_posn = ftell(packfile);
- if (prev_posn>0) {
- if (push_verbosely)
- fprintf(stderr,
- "Resuming fetch of pack %s at byte %ld\n",
- sha1_to_hex(target->sha1), 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);
- }
+ preq->slot->callback_func = process_response;
+ preq->slot->callback_data = request;
+ request->slot = preq->slot;
+ request->userData = preq;
/* Try to get the request started, abort the request on error */
request->state = RUN_FETCH_PACKED;
- if (!start_active_slot(slot)) {
+ if (!start_active_slot(preq->slot)) {
fprintf(stderr, "Unable to start GET request\n");
+ release_http_pack_request(preq);
repo->can_update_info_refs = 0;
release_request(request);
}
if (request->local_fileno != -1)
close(request->local_fileno);
- if (request->local_stream)
- fclose(request->local_stream);
free(request->url);
free(request);
}
static void finish_request(struct transfer_request *request)
{
struct stat st;
- struct packed_git *target;
- struct packed_git **lst;
- struct active_request_slot *slot;
+ struct http_pack_request *preq;
request->curl_result = request->slot->curl_result;
request->http_code = request->slot->http_code;
- slot = request->slot;
request->slot = NULL;
/* Keep locks active */
start_fetch_packed(request);
} else if (request->state == RUN_FETCH_PACKED) {
+ int fail = 1;
if (request->curl_result != CURLE_OK) {
fprintf(stderr, "Unable to get pack file %s\n%s",
request->url, curl_errorstr);
- repo->can_update_info_refs = 0;
} else {
- off_t pack_size = ftell(request->local_stream);
-
- fclose(request->local_stream);
- request->local_stream = NULL;
- slot->local = NULL;
- if (!move_temp_to_file(request->tmpfile,
- request->filename)) {
- target = (struct packed_git *)request->userData;
- target->pack_size = pack_size;
- lst = &repo->packs;
- while (*lst != target)
- lst = &((*lst)->next);
- *lst = (*lst)->next;
-
- if (!verify_pack(target))
- install_packed_git(target);
- else
- repo->can_update_info_refs = 0;
+ preq = (struct http_pack_request *)request->userData;
+
+ if (preq) {
+ if (finish_http_pack_request(preq) > 0)
+ fail = 0;
+ release_http_pack_request(preq);
}
}
+ if (fail)
+ repo->can_update_info_refs = 0;
release_request(request);
}
}
request->lock = NULL;
request->headers = NULL;
request->local_fileno = -1;
- request->local_stream = NULL;
request->state = NEED_FETCH;
request->next = request_queue_head;
request_queue_head = request;
request->lock = lock;
request->headers = NULL;
request->local_fileno = -1;
- request->local_stream = NULL;
request->state = NEED_PUSH;
request->next = request_queue_head;
request_queue_head = request;