X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=http-push.c;h=00e83dcec1d973b069d4c75105aed96634b00994;hb=46068383aa825dfe9026f9255cea07da07e06253;hp=a7e28e345fb303534c4b99189096424bd7d9e887;hpb=7d40f89137b456820d51ebc1cbb3ffbb966e7fec;p=git.git diff --git a/http-push.c b/http-push.c index a7e28e345..00e83dcec 100644 --- a/http-push.c +++ b/http-push.c @@ -1,6 +1,5 @@ #include "cache.h" #include "commit.h" -#include "pack.h" #include "tag.h" #include "blob.h" #include "http.h" @@ -27,7 +26,6 @@ enum XML_Status { #endif #define PREV_BUF_SIZE 4096 -#define RANGE_HEADER_SIZE 30 /* DAV methods */ #define DAV_LOCK "LOCK" @@ -76,8 +74,6 @@ static int pushing; static int aborted; static signed char remote_dir_exists[256]; -static struct curl_slist *no_pragma_header; - static int push_verbosely; static int push_all = MATCH_REFS_NONE; static int force_all; @@ -119,19 +115,10 @@ struct transfer_request struct remote_lock *lock; struct curl_slist *headers; struct buffer buffer; - 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]; long http_code; - unsigned char real_sha1[20]; - git_SHA_CTX c; - z_stream stream; - int zret; - int rename; void *userData; struct active_request_slot *slot; struct transfer_request *next; @@ -206,6 +193,8 @@ static char *xml_entities(char *s) case '&': strbuf_addstr(&buf, "&"); break; + case 0: + return strbuf_detach(&buf, NULL); } s++; } @@ -237,15 +226,6 @@ static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum d return dav_headers; } -static void append_remote_object_url(struct strbuf *buf, const char *url, - const char *hex, - int only_two_digit_prefix) -{ - strbuf_addf(buf, "%sobjects/%.*s/", url, 2, hex); - if (!only_two_digit_prefix) - strbuf_addf(buf, "%s", hex+2); -} - static void finish_request(struct transfer_request *request); static void release_request(struct transfer_request *request); @@ -259,163 +239,29 @@ static void process_response(void *callback_data) #ifdef USE_CURL_MULTI -static char *get_remote_object_url(const char *url, const char *hex, - int only_two_digit_prefix) -{ - struct strbuf buf = STRBUF_INIT; - append_remote_object_url(&buf, url, hex, only_two_digit_prefix); - return strbuf_detach(&buf, NULL); -} - -static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, - void *data) -{ - unsigned char expn[4096]; - size_t size = eltsize * nmemb; - int posn = 0; - struct transfer_request *request = (struct transfer_request *)data; - do { - ssize_t retval = xwrite(request->local_fileno, - (char *) ptr + posn, size - posn); - if (retval < 0) - return posn; - posn += retval; - } while (posn < size); - - request->stream.avail_in = size; - request->stream.next_in = ptr; - do { - request->stream.next_out = expn; - request->stream.avail_out = sizeof(expn); - request->zret = git_inflate(&request->stream, Z_SYNC_FLUSH); - git_SHA1_Update(&request->c, expn, - sizeof(expn) - request->stream.avail_out); - } while (request->stream.avail_in && request->zret == Z_OK); - data_received++; - return size; -} - static void start_fetch_loose(struct transfer_request *request) { - char *hex = sha1_to_hex(request->obj->sha1); - char *filename; - char prevfile[PATH_MAX]; - char *url; - int prevlocal; - unsigned char prev_buf[PREV_BUF_SIZE]; - ssize_t prev_read = 0; - long prev_posn = 0; - char range[RANGE_HEADER_SIZE]; - struct curl_slist *range_header = NULL; struct active_request_slot *slot; + struct http_object_request *obj_req; - filename = sha1_file_name(request->obj->sha1); - snprintf(request->filename, sizeof(request->filename), "%s", filename); - snprintf(request->tmpfile, sizeof(request->tmpfile), - "%s.temp", filename); - - snprintf(prevfile, sizeof(prevfile), "%s.prev", request->filename); - unlink_or_warn(prevfile); - rename(request->tmpfile, prevfile); - unlink_or_warn(request->tmpfile); - - if (request->local_fileno != -1) - error("fd leakage in start: %d", request->local_fileno); - request->local_fileno = open(request->tmpfile, - O_WRONLY | O_CREAT | O_EXCL, 0666); - /* This could have failed due to the "lazy directory creation"; - * try to mkdir the last path component. - */ - if (request->local_fileno < 0 && errno == ENOENT) { - char *dir = strrchr(request->tmpfile, '/'); - if (dir) { - *dir = 0; - mkdir(request->tmpfile, 0777); - *dir = '/'; - } - request->local_fileno = open(request->tmpfile, - O_WRONLY | O_CREAT | O_EXCL, 0666); - } - - if (request->local_fileno < 0) { + obj_req = new_http_object_request(repo->url, request->obj->sha1); + if (obj_req == NULL) { request->state = ABORTED; - error("Couldn't create temporary file %s for %s: %s", - request->tmpfile, request->filename, strerror(errno)); return; } - memset(&request->stream, 0, sizeof(request->stream)); - - git_inflate_init(&request->stream); - - git_SHA1_Init(&request->c); - - url = get_remote_object_url(repo->url, hex, 0); - request->url = xstrdup(url); - - /* If a previous temp file is present, process what was already - fetched. */ - prevlocal = open(prevfile, O_RDONLY); - if (prevlocal != -1) { - do { - prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE); - if (prev_read>0) { - if (fwrite_sha1_file(prev_buf, - 1, - prev_read, - request) == prev_read) { - prev_posn += prev_read; - } else { - prev_read = -1; - } - } - } while (prev_read > 0); - close(prevlocal); - } - unlink_or_warn(prevfile); - - /* Reset inflate/SHA1 if there was an error reading the previous temp - file; also rewind to the beginning of the local file. */ - if (prev_read == -1) { - memset(&request->stream, 0, sizeof(request->stream)); - git_inflate_init(&request->stream); - git_SHA1_Init(&request->c); - if (prev_posn>0) { - prev_posn = 0; - lseek(request->local_fileno, 0, SEEK_SET); - ftruncate(request->local_fileno, 0); - } - } - - slot = get_active_slot(); + slot = obj_req->slot; slot->callback_func = process_response; slot->callback_data = request; request->slot = slot; - - curl_easy_setopt(slot->curl, CURLOPT_FILE, request); - curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file); - curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr); - curl_easy_setopt(slot->curl, CURLOPT_URL, url); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header); - - /* If we have successfully processed data from a previous fetch - attempt, only fetch the data we don't already have. */ - if (prev_posn>0) { - if (push_verbosely) - fprintf(stderr, - "Resuming fetch of object %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); - } + request->userData = obj_req; /* Try to get the request started, abort the request on error */ request->state = RUN_FETCH_LOOSE; if (!start_active_slot(slot)) { fprintf(stderr, "Unable to start GET request\n"); repo->can_update_info_refs = 0; + release_http_object_request(obj_req); release_request(request); } } @@ -449,16 +295,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) { @@ -471,66 +311,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); } @@ -711,19 +520,14 @@ static void release_request(struct transfer_request *request) entry->next = entry->next->next; } - 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 http_pack_request *preq; + struct http_object_request *obj_req; request->curl_result = request->slot->curl_result; request->http_code = request->slot->http_code; @@ -778,76 +582,46 @@ static void finish_request(struct transfer_request *request) aborted = 1; } } else if (request->state == RUN_FETCH_LOOSE) { - close(request->local_fileno); request->local_fileno = -1; + obj_req = (struct http_object_request *)request->userData; - if (request->curl_result != CURLE_OK && - request->http_code != 416) { - if (stat(request->tmpfile, &st) == 0) { - if (st.st_size == 0) - unlink_or_warn(request->tmpfile); - } - } else { - if (request->http_code == 416) - warning("requested range invalid; we may already have all the data."); - - git_inflate_end(&request->stream); - git_SHA1_Final(request->real_sha1, &request->c); - if (request->zret != Z_STREAM_END) { - unlink_or_warn(request->tmpfile); - } else if (hashcmp(request->obj->sha1, request->real_sha1)) { - unlink_or_warn(request->tmpfile); - } else { - request->rename = - move_temp_to_file( - request->tmpfile, - request->filename); - if (request->rename == 0) { - request->obj->flags |= (LOCAL | REMOTE); - } - } - } + if (finish_http_object_request(obj_req) == 0) + if (obj_req->rename == 0) + request->obj->flags |= (LOCAL | REMOTE); /* Try fetching packed if necessary */ - if (request->obj->flags & LOCAL) + if (request->obj->flags & LOCAL) { + release_http_object_request(obj_req); release_request(request); - else + } else 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; - 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); } } #ifdef USE_CURL_MULTI +static int is_running_queue; static int fill_active_slot(void *unused) { struct transfer_request *request; - if (aborted) + if (aborted || !is_running_queue) return 0; for (request = request_queue_head; request; request = request->next) { @@ -890,8 +664,6 @@ static void add_fetch_request(struct object *obj) request->url = NULL; 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; @@ -930,8 +702,6 @@ static int add_send_request(struct object *obj, struct remote_lock *lock) request->url = NULL; 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; @@ -944,176 +714,23 @@ static int add_send_request(struct object *obj, struct remote_lock *lock) return 1; } -static int fetch_index(unsigned char *sha1) -{ - char *hex = 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) { - free(url); - return error("Unable to verify pack %s is available", - hex); - } - } else { - free(url); - return error("Unable to start request"); - } - - if (has_pack_index(sha1)) { - free(url); - return 0; - } - - 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) { - free(url); - return error("Unable to open local file %s for pack index", - tmpfile); - } - - 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) { - free(url); - fclose(indexfile); - return error("Unable to get pack index %s\n%s", url, - curl_errorstr); - } - } else { - free(url); - fclose(indexfile); - return error("Unable to start request"); - } - - free(url); - fclose(indexfile); - - return move_temp_to_file(tmpfile, filename); -} - -static int setup_index(unsigned char *sha1) -{ - struct packed_git *new_pack; - - if (fetch_index(sha1)) - return -1; - - new_pack = parse_pack_index(sha1); - new_pack->next = repo->packs; - repo->packs = new_pack; - return 0; -} - static int fetch_indices(void) { - unsigned char sha1[20]; - char *url; - struct strbuf buffer = STRBUF_INIT; - char *data; - int i = 0; - - struct active_request_slot *slot; - struct slot_results results; + int ret; if (push_verbosely) fprintf(stderr, "Getting pack list\n"); - url = xmalloc(strlen(repo->url) + 20); - sprintf(url, "%sobjects/info/packs", repo->url); - - 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) { - 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; - } - default: - while (data[i] != '\n') - i++; - } - i++; + switch (http_get_info_packs(repo->url, &repo->packs)) { + case HTTP_OK: + case HTTP_MISSING_TARGET: + ret = 0; + break; + default: + ret = -1; } - strbuf_release(&buffer); - return 0; + return ret; } static void one_remote_object(const char *hex) @@ -1976,29 +1593,22 @@ static void update_remote_info_refs(struct remote_lock *lock) static int remote_exists(const char *path) { char *url = xmalloc(strlen(repo->url) + strlen(path) + 1); - struct active_request_slot *slot; - struct slot_results results; - int ret = -1; + int ret; sprintf(url, "%s%s", repo->url, path); - 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.http_code == 404) - ret = 0; - else if (results.curl_result == CURLE_OK) - ret = 1; - else - fprintf(stderr, "HEAD HTTP error %ld\n", results.http_code); - } else { - fprintf(stderr, "Unable to start HEAD request\n"); + switch (http_get_strbuf(url, NULL, 0)) { + case HTTP_OK: + ret = 1; + break; + case HTTP_MISSING_TARGET: + ret = 0; + break; + case HTTP_ERROR: + http_error(url, HTTP_ERROR); + default: + ret = -1; } - free(url); return ret; } @@ -2007,27 +1617,13 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1) { char *url; struct strbuf buffer = STRBUF_INIT; - struct active_request_slot *slot; - struct slot_results results; url = xmalloc(strlen(repo->url) + strlen(path) + 1); sprintf(url, "%s%s", repo->url, path); - 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_HTTPHEADER, NULL); - curl_easy_setopt(slot->curl, CURLOPT_URL, url); - if (start_active_slot(slot)) { - run_active_slot(slot); - if (results.curl_result != CURLE_OK) { - die("Couldn't get %s for remote symref\n%s", - url, curl_errorstr); - } - } else { - die("Unable to start remote symref request"); - } + if (http_get_strbuf(url, &buffer, 0) != HTTP_OK) + die("Couldn't get %s for remote symref\n%s", url, + curl_errorstr); free(url); free(*symref); @@ -2156,6 +1752,25 @@ static int delete_remote_branch(char *pattern, int force) return 0; } +static void run_request_queue(void) +{ +#ifdef USE_CURL_MULTI + is_running_queue = 1; + fill_active_slots(); + add_fill_function(NULL, fill_active_slot); +#endif + do { + finish_all_active_slots(); +#ifdef USE_CURL_MULTI + fill_active_slots(); +#endif + } while (request_queue_head && !aborted); + +#ifdef USE_CURL_MULTI + is_running_queue = 0; +#endif +} + int main(int argc, char **argv) { struct transfer_request *request; @@ -2200,6 +1815,7 @@ int main(int argc, char **argv) } if (!strcmp(arg, "--verbose")) { push_verbosely = 1; + http_is_verbose = 1; continue; } if (!strcmp(arg, "-d")) { @@ -2249,8 +1865,6 @@ int main(int argc, char **argv) remote->url[remote->url_nr++] = repo->url; http_init(remote); - no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:"); - if (repo->url && repo->url[strlen(repo->url)-1] != '/') { rewritten_url = xmalloc(strlen(repo->url)+2); strcpy(rewritten_url, repo->url); @@ -2260,6 +1874,10 @@ int main(int argc, char **argv) repo->url = rewritten_url; } +#ifdef USE_CURL_MULTI + is_running_queue = 0; +#endif + /* Verify DAV compliance/lock support */ if (!locking_available()) { rc = 1; @@ -2289,6 +1907,7 @@ int main(int argc, char **argv) local_refs = get_local_heads(); fprintf(stderr, "Fetching remote heads...\n"); get_dav_remote_heads(); + run_request_queue(); /* Remove a remote branch if -d or -D was specified */ if (delete_branch) { @@ -2417,16 +2036,8 @@ int main(int argc, char **argv) if (objects_to_send) fprintf(stderr, " sending %d objects\n", objects_to_send); -#ifdef USE_CURL_MULTI - fill_active_slots(); - add_fill_function(NULL, fill_active_slot); -#endif - do { - finish_all_active_slots(); -#ifdef USE_CURL_MULTI - fill_active_slots(); -#endif - } while (request_queue_head && !aborted); + + run_request_queue(); /* Update the remote branch if all went well */ if (aborted || !update_remote(ref->new_sha1, ref_lock)) @@ -2455,8 +2066,6 @@ int main(int argc, char **argv) unlock_remote(info_ref_lock); free(repo); - curl_slist_free_all(no_pragma_header); - http_cleanup(); request = request_queue_head;