diff options
Diffstat (limited to 'http.c')
-rw-r--r-- | http.c | 385 |
1 files changed, 212 insertions, 173 deletions
@@ -1,8 +1,10 @@ #include "http.h" #include "pack.h" #include "sideband.h" +#include "run-command.h" +#include "url.h" +#include "credential.h" -int data_received; int active_requests; int http_is_verbose; size_t http_post_buffer = 16 * LARGE_PACKET_MAX; @@ -39,7 +41,10 @@ static long curl_low_speed_limit = -1; static long curl_low_speed_time = -1; static int curl_ftp_no_epsv; static const char *curl_http_proxy; -static char *user_name, *user_pass; +static const char *curl_cookie_file; +static struct credential http_auth = CREDENTIAL_INIT; +static int http_proactive_auth; +static const char *user_agent; #if LIBCURL_VERSION_NUM >= 0x071700 /* Use CURLOPT_KEYPASSWD as is */ @@ -49,7 +54,7 @@ static char *user_name, *user_pass; #define CURLOPT_KEYPASSWD CURLOPT_SSLCERTPASSWD #endif -static char *ssl_cert_password; +static struct credential cert_auth = CREDENTIAL_INIT; static int ssl_cert_password_required; static struct curl_slist *pragma_header; @@ -57,7 +62,7 @@ static struct curl_slist *no_pragma_header; static struct active_request_slot *active_queue_head; -size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_) +size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_) { size_t size = eltsize * nmemb; struct buffer *buffer = buffer_; @@ -89,19 +94,17 @@ curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp) } #endif -size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, void *buffer_) +size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_) { size_t size = eltsize * nmemb; struct strbuf *buffer = buffer_; strbuf_add(buffer, ptr, size); - data_received++; return size; } -size_t fwrite_null(const void *ptr, size_t eltsize, size_t nmemb, void *strbuf) +size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf) { - data_received++; return eltsize * nmemb; } @@ -188,6 +191,9 @@ static int http_options(const char *var, const char *value, void *cb) if (!strcmp("http.proxy", var)) return git_config_string(&curl_http_proxy, var, value); + if (!strcmp("http.cookiefile", var)) + return git_config_string(&curl_cookie_file, var, value); + if (!strcmp("http.postbuffer", var)) { http_post_buffer = git_config_int(var, value); if (http_post_buffer < LARGE_PACKET_MAX) @@ -195,36 +201,44 @@ static int http_options(const char *var, const char *value, void *cb) return 0; } + if (!strcmp("http.useragent", var)) + return git_config_string(&user_agent, var, value); + /* Fall back on the default ones */ return git_default_config(var, value, cb); } static void init_curl_http_auth(CURL *result) { - if (user_name) { - struct strbuf up = STRBUF_INIT; - if (!user_pass) - user_pass = xstrdup(getpass("Password: ")); - strbuf_addf(&up, "%s:%s", user_name, user_pass); - curl_easy_setopt(result, CURLOPT_USERPWD, - strbuf_detach(&up, NULL)); + if (!http_auth.username) + return; + + credential_fill(&http_auth); + +#if LIBCURL_VERSION_NUM >= 0x071301 + curl_easy_setopt(result, CURLOPT_USERNAME, http_auth.username); + curl_easy_setopt(result, CURLOPT_PASSWORD, http_auth.password); +#else + { + static struct strbuf up = STRBUF_INIT; + strbuf_reset(&up); + strbuf_addf(&up, "%s:%s", + http_auth.username, http_auth.password); + curl_easy_setopt(result, CURLOPT_USERPWD, up.buf); } +#endif } static int has_cert_password(void) { - if (ssl_cert_password != NULL) - return 1; if (ssl_cert == NULL || ssl_cert_password_required != 1) return 0; - /* Only prompt the user once. */ - ssl_cert_password_required = -1; - ssl_cert_password = getpass("Certificate Password: "); - if (ssl_cert_password != NULL) { - ssl_cert_password = xstrdup(ssl_cert_password); - return 1; - } else - return 0; + if (!cert_auth.password) { + cert_auth.protocol = xstrdup("cert"); + cert_auth.path = xstrdup(ssl_cert); + credential_fill(&cert_auth); + } + return 1; } static CURL *get_curl_handle(void) @@ -248,12 +262,13 @@ static CURL *get_curl_handle(void) curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_ANY); #endif - init_curl_http_auth(result); + if (http_proactive_auth) + init_curl_http_auth(result); if (ssl_cert != NULL) curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert); if (has_cert_password()) - curl_easy_setopt(result, CURLOPT_KEYPASSWD, ssl_cert_password); + curl_easy_setopt(result, CURLOPT_KEYPASSWD, cert_auth.password); #if LIBCURL_VERSION_NUM >= 0x070903 if (ssl_key != NULL) curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key); @@ -274,61 +289,29 @@ static CURL *get_curl_handle(void) } curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1); +#if LIBCURL_VERSION_NUM >= 0x071301 + curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); +#elif LIBCURL_VERSION_NUM >= 0x071101 + curl_easy_setopt(result, CURLOPT_POST301, 1); +#endif if (getenv("GIT_CURL_VERBOSE")) curl_easy_setopt(result, CURLOPT_VERBOSE, 1); - curl_easy_setopt(result, CURLOPT_USERAGENT, GIT_USER_AGENT); + curl_easy_setopt(result, CURLOPT_USERAGENT, + user_agent ? user_agent : GIT_HTTP_USER_AGENT); if (curl_ftp_no_epsv) curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0); - if (curl_http_proxy) + if (curl_http_proxy) { curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy); + curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY); + } return result; } -static void http_auth_init(const char *url) -{ - char *at, *colon, *cp, *slash; - int len; - - cp = strstr(url, "://"); - if (!cp) - return; - - /* - * Ok, the URL looks like "proto://something". Which one? - * "proto://<user>:<pass>@<host>/...", - * "proto://<user>@<host>/...", or just - * "proto://<host>/..."? - */ - cp += 3; - at = strchr(cp, '@'); - colon = strchr(cp, ':'); - slash = strchrnul(cp, '/'); - if (!at || slash <= at) - return; /* No credentials */ - if (!colon || at <= colon) { - /* Only username */ - len = at - cp; - user_name = xmalloc(len + 1); - memcpy(user_name, cp, len); - user_name[len] = '\0'; - user_pass = NULL; - } else { - len = colon - cp; - user_name = xmalloc(len + 1); - memcpy(user_name, cp, len); - user_name[len] = '\0'; - len = at - (colon + 1); - user_pass = xmalloc(len + 1); - memcpy(user_pass, colon + 1, len); - user_pass[len] = '\0'; - } -} - static void set_from_env(const char **var, const char *envname) { const char *val = getenv(envname); @@ -336,7 +319,7 @@ static void set_from_env(const char **var, const char *envname) *var = val; } -void http_init(struct remote *remote) +void http_init(struct remote *remote, const char *url, int proactive_auth) { char *low_speed_limit; char *low_speed_time; @@ -347,6 +330,8 @@ void http_init(struct remote *remote) curl_global_init(CURL_GLOBAL_ALL); + http_proactive_auth = proactive_auth; + if (remote && remote->http_proxy) curl_http_proxy = xstrdup(remote->http_proxy); @@ -379,6 +364,8 @@ void http_init(struct remote *remote) #endif set_from_env(&ssl_cainfo, "GIT_SSL_CAINFO"); + set_from_env(&user_agent, "GIT_HTTP_USER_AGENT"); + low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT"); if (low_speed_limit != NULL) curl_low_speed_limit = strtol(low_speed_limit, NULL, 10); @@ -398,11 +385,11 @@ void http_init(struct remote *remote) if (getenv("GIT_CURL_FTP_NO_EPSV")) curl_ftp_no_epsv = 1; - if (remote && remote->url && remote->url[0]) { - http_auth_init(remote->url[0]); + if (url) { + credential_from_url(&http_auth, url); if (!ssl_cert_password_required && getenv("GIT_SSL_CERT_PASSWORD_PROTECTED") && - !prefixcmp(remote->url[0], "https://")) + !prefixcmp(url, "https://")) ssl_cert_password_required = 1; } @@ -448,10 +435,10 @@ void http_cleanup(void) curl_http_proxy = NULL; } - if (ssl_cert_password != NULL) { - memset(ssl_cert_password, 0, strlen(ssl_cert_password)); - free(ssl_cert_password); - ssl_cert_password = NULL; + if (cert_auth.password != NULL) { + memset(cert_auth.password, 0, strlen(cert_auth.password)); + free(cert_auth.password); + cert_auth.password = NULL; } ssl_cert_password_required = 0; } @@ -503,18 +490,21 @@ struct active_request_slot *get_active_slot(void) active_requests++; slot->in_use = 1; - slot->local = NULL; slot->results = NULL; slot->finished = NULL; slot->callback_data = NULL; slot->callback_func = NULL; + curl_easy_setopt(slot->curl, CURLOPT_COOKIEFILE, curl_cookie_file); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header); curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr); curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, NULL); curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, NULL); curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, NULL); + curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, NULL); curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0); curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); + if (http_auth.password) + init_curl_http_auth(slot->curl); return slot; } @@ -605,8 +595,6 @@ void step_active_slots(void) void run_active_slot(struct active_request_slot *slot) { #ifdef USE_CURL_MULTI - long last_pos = 0; - long current_pos; fd_set readfds; fd_set writefds; fd_set excfds; @@ -616,25 +604,33 @@ void run_active_slot(struct active_request_slot *slot) slot->finished = &finished; while (!finished) { - data_received = 0; step_active_slots(); - if (!data_received && slot->local != NULL) { - current_pos = ftell(slot->local); - if (current_pos > last_pos) - data_received++; - last_pos = current_pos; - } + if (slot->in_use) { +#if LIBCURL_VERSION_NUM >= 0x070f04 + long curl_timeout; + curl_multi_timeout(curlm, &curl_timeout); + if (curl_timeout == 0) { + continue; + } else if (curl_timeout == -1) { + select_timeout.tv_sec = 0; + select_timeout.tv_usec = 50000; + } else { + select_timeout.tv_sec = curl_timeout / 1000; + select_timeout.tv_usec = (curl_timeout % 1000) * 1000; + } +#else + select_timeout.tv_sec = 0; + select_timeout.tv_usec = 50000; +#endif - if (slot->in_use && !data_received) { - max_fd = 0; + max_fd = -1; FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&excfds); - select_timeout.tv_sec = 0; - select_timeout.tv_usec = 50000; - select(max_fd, &readfds, &writefds, - &excfds, &select_timeout); + curl_multi_fdset(curlm, &readfds, &writefds, &excfds, &max_fd); + + select(max_fd+1, &readfds, &writefds, &excfds, &select_timeout); } } #else @@ -712,21 +708,6 @@ static inline int needs_quote(int ch) return 1; } -static inline int hex(int v) -{ - if (v < 10) - return '0' + v; - else - return 'A' + v - 10; -} - -static void end_url_with_slash(struct strbuf *buf, const char *url) -{ - strbuf_addstr(buf, url); - if (buf->len && buf->buf[buf->len - 1] != '/') - strbuf_addstr(buf, "/"); -} - static char *quote_ref_url(const char *base, const char *ref) { struct strbuf buf = STRBUF_INIT; @@ -794,7 +775,6 @@ static int http_request(const char *url, void *result, int target, int options) headers = curl_slist_append(headers, buf.buf); strbuf_reset(&buf); } - slot->local = result; } else curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer); @@ -815,27 +795,52 @@ static int http_request(const char *url, void *result, int target, int options) ret = HTTP_OK; else if (missing_target(&results)) ret = HTTP_MISSING_TARGET; - else + else if (results.http_code == 401) { + if (http_auth.username && http_auth.password) { + credential_reject(&http_auth); + ret = HTTP_NOAUTH; + } else { + credential_fill(&http_auth); + init_curl_http_auth(slot->curl); + ret = HTTP_REAUTH; + } + } else { + if (!curl_errorstr[0]) + strlcpy(curl_errorstr, + curl_easy_strerror(results.curl_result), + sizeof(curl_errorstr)); ret = HTTP_ERROR; + } } else { error("Unable to start HTTP request for %s", url); ret = HTTP_START_FAILED; } - slot->local = NULL; curl_slist_free_all(headers); strbuf_release(&buf); + if (ret == HTTP_OK) + credential_approve(&http_auth); + return ret; } +static int http_request_reauth(const char *url, void *result, int target, + int options) +{ + int ret = http_request(url, result, target, options); + if (ret != HTTP_REAUTH) + return ret; + return http_request(url, result, target, options); +} + int http_get_strbuf(const char *url, struct strbuf *result, int options) { - return http_request(url, result, HTTP_REQUEST_STRBUF, options); + return http_request_reauth(url, result, HTTP_REQUEST_STRBUF, options); } /* - * Downloads an url and stores the result in the given file. + * Downloads a URL and stores the result in the given file. * * If a previous interrupted download is detected (i.e. a previous temporary * file is still around) the download is resumed. @@ -854,7 +859,7 @@ static int http_get_file(const char *url, const char *filename, int options) goto cleanup; } - ret = http_request(url, result, HTTP_REQUEST_FILE, options); + ret = http_request_reauth(url, result, HTTP_REQUEST_FILE, options); fclose(result); if ((ret == HTTP_OK) && move_temp_to_file(tmpfile.buf, filename)) @@ -868,7 +873,7 @@ int http_error(const char *url, int ret) { /* http_request has already handled HTTP_START_FAILED. */ if (ret != HTTP_START_FAILED) - error("%s while accessing %s\n", curl_errorstr, url); + error("%s while accessing %s", curl_errorstr, url); return ret; } @@ -896,47 +901,67 @@ int http_fetch_ref(const char *base, struct ref *ref) } /* Helpers for fetching packs */ -static int fetch_pack_index(unsigned char *sha1, const char *base_url) +static char *fetch_pack_index(unsigned char *sha1, const char *base_url) { - int ret = 0; - char *hex = xstrdup(sha1_to_hex(sha1)); - char *filename; - char *url = NULL; + char *url, *tmp; struct strbuf buf = STRBUF_INIT; - if (has_pack_index(sha1)) { - ret = 0; - goto cleanup; - } - if (http_is_verbose) - fprintf(stderr, "Getting index for pack %s\n", hex); + fprintf(stderr, "Getting index for pack %s\n", sha1_to_hex(sha1)); end_url_with_slash(&buf, base_url); - strbuf_addf(&buf, "objects/pack/pack-%s.idx", hex); + strbuf_addf(&buf, "objects/pack/pack-%s.idx", sha1_to_hex(sha1)); url = strbuf_detach(&buf, NULL); - filename = sha1_pack_index_name(sha1); - if (http_get_file(url, filename, 0) != HTTP_OK) - ret = error("Unable to get pack index %s\n", url); + strbuf_addf(&buf, "%s.temp", sha1_pack_index_name(sha1)); + tmp = strbuf_detach(&buf, NULL); + + if (http_get_file(url, tmp, 0) != HTTP_OK) { + error("Unable to get pack index %s", url); + free(tmp); + tmp = NULL; + } -cleanup: - free(hex); free(url); - return ret; + return tmp; } static int fetch_and_setup_pack_index(struct packed_git **packs_head, unsigned char *sha1, const char *base_url) { struct packed_git *new_pack; + char *tmp_idx = NULL; + int ret; - if (fetch_pack_index(sha1, base_url)) + if (has_pack_index(sha1)) { + new_pack = parse_pack_index(sha1, NULL); + if (!new_pack) + return -1; /* parse_pack_index() already issued error message */ + goto add_pack; + } + + tmp_idx = fetch_pack_index(sha1, base_url); + if (!tmp_idx) return -1; - new_pack = parse_pack_index(sha1); - if (!new_pack) + new_pack = parse_pack_index(sha1, tmp_idx); + if (!new_pack) { + unlink(tmp_idx); + free(tmp_idx); + return -1; /* parse_pack_index() already issued error message */ + } + + ret = verify_pack_index(new_pack); + if (!ret) { + close_pack_index(new_pack); + ret = move_temp_to_file(tmp_idx, sha1_pack_index_name(sha1)); + } + free(tmp_idx); + if (ret) + return -1; + +add_pack: new_pack->next = *packs_head; *packs_head = new_pack; return 0; @@ -988,7 +1013,6 @@ void release_http_pack_request(struct http_pack_request *preq) if (preq->packfile != NULL) { fclose(preq->packfile); preq->packfile = NULL; - preq->slot->local = NULL; } if (preq->range_header != NULL) { curl_slist_free_all(preq->range_header); @@ -1000,54 +1024,76 @@ void release_http_pack_request(struct http_pack_request *preq) int finish_http_pack_request(struct http_pack_request *preq) { - int ret; struct packed_git **lst; + struct packed_git *p = preq->target; + char *tmp_idx; + struct child_process ip; + const char *ip_argv[8]; - preq->target->pack_size = ftell(preq->packfile); + close_pack_index(p); - if (preq->packfile != NULL) { - fclose(preq->packfile); - preq->packfile = NULL; - preq->slot->local = NULL; - } - - ret = move_temp_to_file(preq->tmpfile, preq->filename); - if (ret) - return ret; + fclose(preq->packfile); + preq->packfile = NULL; lst = preq->lst; - while (*lst != preq->target) + while (*lst != p) lst = &((*lst)->next); *lst = (*lst)->next; - if (verify_pack(preq->target)) + tmp_idx = xstrdup(preq->tmpfile); + strcpy(tmp_idx + strlen(tmp_idx) - strlen(".pack.temp"), + ".idx.temp"); + + ip_argv[0] = "index-pack"; + ip_argv[1] = "-o"; + ip_argv[2] = tmp_idx; + ip_argv[3] = preq->tmpfile; + ip_argv[4] = NULL; + + memset(&ip, 0, sizeof(ip)); + ip.argv = ip_argv; + ip.git_cmd = 1; + ip.no_stdin = 1; + ip.no_stdout = 1; + + if (run_command(&ip)) { + unlink(preq->tmpfile); + unlink(tmp_idx); + free(tmp_idx); + return -1; + } + + unlink(sha1_pack_index_name(p->sha1)); + + if (move_temp_to_file(preq->tmpfile, sha1_pack_name(p->sha1)) + || move_temp_to_file(tmp_idx, sha1_pack_index_name(p->sha1))) { + free(tmp_idx); return -1; - install_packed_git(preq->target); + } + install_packed_git(p); + free(tmp_idx); return 0; } struct http_pack_request *new_http_pack_request( struct packed_git *target, const char *base_url) { - char *filename; long prev_posn = 0; char range[RANGE_HEADER_SIZE]; struct strbuf buf = STRBUF_INIT; struct http_pack_request *preq; - preq = xmalloc(sizeof(*preq)); + preq = xcalloc(1, sizeof(*preq)); preq->target = target; - preq->range_header = NULL; end_url_with_slash(&buf, base_url); strbuf_addf(&buf, "objects/pack/pack-%s.pack", sha1_to_hex(target->sha1)); preq->url = strbuf_detach(&buf, NULL); - filename = sha1_pack_name(target->sha1); - snprintf(preq->filename, sizeof(preq->filename), "%s", filename); - snprintf(preq->tmpfile, sizeof(preq->tmpfile), "%s.temp", filename); + snprintf(preq->tmpfile, sizeof(preq->tmpfile), "%s.temp", + sha1_pack_name(target->sha1)); preq->packfile = fopen(preq->tmpfile, "a"); if (!preq->packfile) { error("Unable to open local file %s for pack", @@ -1056,7 +1102,6 @@ struct http_pack_request *new_http_pack_request( } preq->slot = get_active_slot(); - preq->slot->local = preq->packfile; curl_easy_setopt(preq->slot->curl, CURLOPT_FILE, preq->packfile); curl_easy_setopt(preq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite); curl_easy_setopt(preq->slot->curl, CURLOPT_URL, preq->url); @@ -1082,14 +1127,13 @@ struct http_pack_request *new_http_pack_request( return preq; abort: - free(filename); free(preq->url); free(preq); return NULL; } /* Helpers for fetching objects (loose) */ -static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, +static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb, void *data) { unsigned char expn[4096]; @@ -1106,7 +1150,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, } while (posn < size); freq->stream.avail_in = size; - freq->stream.next_in = ptr; + freq->stream.next_in = (void *)ptr; do { freq->stream.next_out = expn; freq->stream.avail_out = sizeof(expn); @@ -1114,7 +1158,6 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, git_SHA1_Update(&freq->c, expn, sizeof(expn) - freq->stream.avail_out); } while (freq->stream.avail_in && freq->zret == Z_OK); - data_received++; return size; } @@ -1125,19 +1168,18 @@ struct http_object_request *new_http_object_request(const char *base_url, char *filename; char prevfile[PATH_MAX]; int prevlocal; - unsigned char prev_buf[PREV_BUF_SIZE]; + 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 http_object_request *freq; - freq = xmalloc(sizeof(*freq)); + freq = xcalloc(1, sizeof(*freq)); hashcpy(freq->sha1, sha1); freq->localfile = -1; filename = sha1_file_name(sha1); - snprintf(freq->filename, sizeof(freq->filename), "%s", filename); snprintf(freq->tmpfile, sizeof(freq->tmpfile), "%s.temp", filename); @@ -1166,13 +1208,11 @@ struct http_object_request *new_http_object_request(const char *base_url, } if (freq->localfile < 0) { - error("Couldn't create temporary file %s for %s: %s", - freq->tmpfile, freq->filename, strerror(errno)); + error("Couldn't create temporary file %s: %s", + freq->tmpfile, strerror(errno)); goto abort; } - memset(&freq->stream, 0, sizeof(freq->stream)); - git_inflate_init(&freq->stream); git_SHA1_Init(&freq->c); @@ -1214,8 +1254,8 @@ struct http_object_request *new_http_object_request(const char *base_url, prev_posn = 0; lseek(freq->localfile, 0, SEEK_SET); if (ftruncate(freq->localfile, 0) < 0) { - error("Couldn't truncate temporary file %s for %s: %s", - freq->tmpfile, freq->filename, strerror(errno)); + error("Couldn't truncate temporary file %s: %s", + freq->tmpfile, strerror(errno)); goto abort; } } @@ -1247,7 +1287,6 @@ struct http_object_request *new_http_object_request(const char *base_url, return freq; abort: - free(filename); free(freq->url); free(freq); return NULL; @@ -1291,7 +1330,7 @@ int finish_http_object_request(struct http_object_request *freq) return -1; } freq->rename = - move_temp_to_file(freq->tmpfile, freq->filename); + move_temp_to_file(freq->tmpfile, sha1_file_name(freq->sha1)); return freq->rename; } |