http*: add helper methods for fetching packs
[gitweb.git] / http-push.c
index 7ad3b690bbe696f50bd7bcd28ae1f5e156c4ccb3..8232cf488e39a126c532ba3475099bb018ee83e8 100644 (file)
@@ -1,6 +1,5 @@
 #include "cache.h"
 #include "commit.h"
-#include "pack.h"
 #include "tag.h"
 #include "blob.h"
 #include "http.h"
@@ -119,7 +118,6 @@ struct transfer_request
        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];
@@ -452,16 +450,10 @@ static void start_mkcol(struct transfer_request *request)
 
 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) {
@@ -474,68 +466,35 @@ static void start_fetch_packed(struct transfer_request *request)
        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);
        }
@@ -718,8 +677,6 @@ static void release_request(struct transfer_request *request)
 
        if (request->local_fileno != -1)
                close(request->local_fileno);
-       if (request->local_stream)
-               fclose(request->local_stream);
        free(request->url);
        free(request);
 }
@@ -727,13 +684,10 @@ static void release_request(struct transfer_request *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 */
@@ -821,31 +775,21 @@ static void finish_request(struct transfer_request *request)
                        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);
        }
 }
@@ -900,7 +844,6 @@ static void add_fetch_request(struct object *obj)
        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;
@@ -940,7 +883,6 @@ static int add_send_request(struct object *obj, struct remote_lock *lock)
        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;