projects
/
git.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Make http-push smarter about creating remote dirs
[git.git]
/
http-fetch.c
diff --git
a/http-fetch.c
b/http-fetch.c
index
40bd0b4
..
ea8af1b
100644
(file)
--- a/
http-fetch.c
+++ b/
http-fetch.c
@@
-25,6
+25,7
@@
#define PREV_BUF_SIZE 4096
#define RANGE_HEADER_SIZE 30
#define PREV_BUF_SIZE 4096
#define RANGE_HEADER_SIZE 30
+static int got_alternates = 0;
static int active_requests = 0;
static int data_received;
static int active_requests = 0;
static int data_received;
@@
-85,6
+86,7
@@
struct active_request_slot
int in_use;
int done;
CURLcode curl_result;
int in_use;
int done;
CURLcode curl_result;
+ long http_code;
struct active_request_slot *next;
};
struct active_request_slot *next;
};
@@
-100,6
+102,8
@@
static char *ssl_key = NULL;
static char *ssl_capath = NULL;
#endif
static char *ssl_cainfo = NULL;
static char *ssl_capath = NULL;
#endif
static char *ssl_cainfo = NULL;
+static long curl_low_speed_limit = -1;
+static long curl_low_speed_time = -1;
struct buffer
{
struct buffer
{
@@
-158,6
+162,17
@@
static int http_options(const char *var, const char *value)
}
#endif
}
#endif
+ if (!strcmp("http.lowspeedlimit", var)) {
+ if (curl_low_speed_limit == -1)
+ curl_low_speed_limit = (long)git_config_int(var, value);
+ return 0;
+ }
+ if (!strcmp("http.lowspeedtime", var)) {
+ if (curl_low_speed_time == -1)
+ curl_low_speed_time = (long)git_config_int(var, value);
+ return 0;
+ }
+
/* Fall back on the default ones */
return git_default_config(var, value);
}
/* Fall back on the default ones */
return git_default_config(var, value);
}
@@
-219,11
+234,12
@@
static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
}
#ifdef USE_CURL_MULTI
}
#ifdef USE_CURL_MULTI
-
void process_curl_messages(
);
-
void process_request_queue(
);
+
static void process_curl_messages(void
);
+
static void process_request_queue(void
);
#endif
#endif
+static int fetch_alternates(char *base);
-static CURL* get_curl_handle()
+static CURL* get_curl_handle(
void
)
{
CURL* result = curl_easy_init();
{
CURL* result = curl_easy_init();
@@
-246,10
+262,17
@@
static CURL* get_curl_handle()
curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
curl_easy_setopt(result, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
curl_easy_setopt(result, CURLOPT_FAILONERROR, 1);
+ if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
+ curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
+ curl_low_speed_limit);
+ curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME,
+ curl_low_speed_time);
+ }
+
return result;
}
return result;
}
-st
ruct active_request_slot *get_active_slot(
)
+st
atic struct active_request_slot *get_active_slot(void
)
{
struct active_request_slot *slot = active_queue_head;
struct active_request_slot *newslot;
{
struct active_request_slot *slot = active_queue_head;
struct active_request_slot *newslot;
@@
-271,11
+294,7
@@
struct active_request_slot *get_active_slot()
}
if (slot == NULL) {
newslot = xmalloc(sizeof(*newslot));
}
if (slot == NULL) {
newslot = xmalloc(sizeof(*newslot));
-#ifdef NO_CURL_EASY_DUPHANDLE
- newslot->curl = get_curl_handle();
-#else
- newslot->curl = curl_easy_duphandle(curl_default);
-#endif
+ newslot->curl = NULL;
newslot->in_use = 0;
newslot->next = NULL;
newslot->in_use = 0;
newslot->next = NULL;
@@
-291,6
+310,14
@@
struct active_request_slot *get_active_slot()
slot = newslot;
}
slot = newslot;
}
+ if (slot->curl == NULL) {
+#ifdef NO_CURL_EASY_DUPHANDLE
+ slot->curl = get_curl_handle();
+#else
+ slot->curl = curl_easy_duphandle(curl_default);
+#endif
+ }
+
active_requests++;
slot->in_use = 1;
slot->done = 0;
active_requests++;
slot->in_use = 1;
slot->done = 0;
@@
-302,7
+329,7
@@
struct active_request_slot *get_active_slot()
return slot;
}
return slot;
}
-int start_active_slot(struct active_request_slot *slot)
+
static
int start_active_slot(struct active_request_slot *slot)
{
#ifdef USE_CURL_MULTI
CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl);
{
#ifdef USE_CURL_MULTI
CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl);
@@
-317,7
+344,7
@@
int start_active_slot(struct active_request_slot *slot)
return 1;
}
return 1;
}
-void run_active_slot(struct active_request_slot *slot)
+
static
void run_active_slot(struct active_request_slot *slot)
{
#ifdef USE_CURL_MULTI
int num_transfers;
{
#ifdef USE_CURL_MULTI
int num_transfers;
@@
-365,7
+392,7
@@
void run_active_slot(struct active_request_slot *slot)
#endif
}
#endif
}
-void start_request(struct transfer_request *request)
+
static
void start_request(struct transfer_request *request)
{
char *hex = sha1_to_hex(request->sha1);
char prevfile[PATH_MAX];
{
char *hex = sha1_to_hex(request->sha1);
char prevfile[PATH_MAX];
@@
-491,14
+518,19
@@
void start_request(struct transfer_request *request)
request->state = ACTIVE;
}
request->state = ACTIVE;
}
-void finish_request(struct transfer_request *request)
+
static
void finish_request(struct transfer_request *request)
{
{
+ struct stat st;
+
fchmod(request->local, 0444);
close(request->local);
if (request->http_code == 416) {
fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
} else if (request->curl_result != CURLE_OK) {
fchmod(request->local, 0444);
close(request->local);
if (request->http_code == 416) {
fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
} else if (request->curl_result != CURLE_OK) {
+ if (stat(request->tmpfile, &st) == 0)
+ if (st.st_size == 0)
+ unlink(request->tmpfile);
return;
}
return;
}
@@
-519,7
+551,7
@@
void finish_request(struct transfer_request *request)
pull_say("got %s\n", sha1_to_hex(request->sha1));
}
pull_say("got %s\n", sha1_to_hex(request->sha1));
}
-void release_request(struct transfer_request *request)
+
static
void release_request(struct transfer_request *request)
{
struct transfer_request *entry = request_queue_head;
{
struct transfer_request *entry = request_queue_head;
@@
-537,7
+569,7
@@
void release_request(struct transfer_request *request)
}
#ifdef USE_CURL_MULTI
}
#ifdef USE_CURL_MULTI
-void process_curl_messages()
+void process_curl_messages(
void
)
{
int num_messages;
struct active_request_slot *slot;
{
int num_messages;
struct active_request_slot *slot;
@@
-546,6
+578,7
@@
void process_curl_messages()
while (curl_message != NULL) {
if (curl_message->msg == CURLMSG_DONE) {
while (curl_message != NULL) {
if (curl_message->msg == CURLMSG_DONE) {
+ int curl_result = curl_message->data.result;
slot = active_queue_head;
while (slot != NULL &&
slot->curl != curl_message->easy_handle)
slot = active_queue_head;
while (slot != NULL &&
slot->curl != curl_message->easy_handle)
@@
-555,7
+588,10
@@
void process_curl_messages()
active_requests--;
slot->done = 1;
slot->in_use = 0;
active_requests--;
slot->done = 1;
slot->in_use = 0;
- slot->curl_result = curl_message->data.result;
+ slot->curl_result = curl_result;
+ curl_easy_getinfo(slot->curl,
+ CURLINFO_HTTP_CODE,
+ &slot->http_code);
request = request_queue_head;
while (request != NULL &&
request->slot != slot)
request = request_queue_head;
while (request != NULL &&
request->slot != slot)
@@
-564,21
+600,21
@@
void process_curl_messages()
fprintf(stderr, "Received DONE message for unknown request!\n");
}
if (request != NULL) {
fprintf(stderr, "Received DONE message for unknown request!\n");
}
if (request != NULL) {
- request->curl_result =
- curl_message->data.result;
- curl_easy_getinfo(slot->curl,
- CURLINFO_HTTP_CODE,
- &request->http_code);
+ request->curl_result = curl_result;
+ request->http_code = slot->http_code;
request->slot = NULL;
request->slot = NULL;
+ request->state = COMPLETE;
/* Use alternates if necessary */
/* Use alternates if necessary */
- if (request->http_code == 404 &&
- request->repo->next != NULL) {
- request->repo = request->repo->next;
- start_request(request);
+ if (request->http_code == 404) {
+ fetch_alternates(alt->base);
+ if (request->repo->next != NULL) {
+ request->repo =
+ request->repo->next;
+ start_request(request);
+ }
} else {
finish_request(request);
} else {
finish_request(request);
- request->state = COMPLETE;
}
}
} else {
}
}
} else {
@@
-589,9
+625,10
@@
void process_curl_messages()
}
}
}
}
-void process_request_queue()
+void process_request_queue(
void
)
{
struct transfer_request *request = request_queue_head;
{
struct transfer_request *request = request_queue_head;
+ struct active_request_slot *slot = active_queue_head;
int num_transfers;
while (active_requests < max_requests && request != NULL) {
int num_transfers;
while (active_requests < max_requests && request != NULL) {
@@
-604,6
+641,14
@@
void process_request_queue()
}
request = request->next;
}
}
request = request->next;
}
+
+ while (slot != NULL) {
+ if (!slot->in_use && slot->curl != NULL) {
+ curl_easy_cleanup(slot->curl);
+ slot->curl = NULL;
+ }
+ slot = slot->next;
+ }
}
#endif
}
#endif
@@
-732,6
+777,9
@@
static int fetch_alternates(char *base)
struct active_request_slot *slot;
struct active_request_slot *slot;
+ if (got_alternates)
+ return 0;
+
data = xmalloc(4096);
buffer.size = 4096;
buffer.posn = 0;
data = xmalloc(4096);
buffer.size = 4096;
buffer.posn = 0;
@@
-764,6
+812,8
@@
static int fetch_alternates(char *base)
run_active_slot(slot);
if (slot->curl_result != CURLE_OK) {
free(buffer.buffer);
run_active_slot(slot);
if (slot->curl_result != CURLE_OK) {
free(buffer.buffer);
+ if (slot->http_code == 404)
+ got_alternates = 1;
return 0;
}
}
return 0;
}
}
@@
-835,6
+885,7
@@
static int fetch_alternates(char *base)
i = posn + 1;
}
i = posn + 1;
}
+ got_alternates = 1;
free(buffer.buffer);
return ret;
}
free(buffer.buffer);
return ret;
}
@@
-1010,8
+1061,8
@@
static int fetch_object(struct alt_base *repo, unsigned char *sha1)
}
#ifdef USE_CURL_MULTI
}
#ifdef USE_CURL_MULTI
- int num_transfers;
while (request->state == WAITING) {
while (request->state == WAITING) {
+ int num_transfers;
curl_multi_perform(curlm, &num_transfers);
if (num_transfers < active_requests) {
process_curl_messages();
curl_multi_perform(curlm, &num_transfers);
if (num_transfers < active_requests) {
process_curl_messages();
@@
-1026,16
+1077,16
@@
static int fetch_object(struct alt_base *repo, unsigned char *sha1)
run_active_slot(request->slot);
#ifndef USE_CURL_MULTI
request->curl_result = request->slot->curl_result;
run_active_slot(request->slot);
#ifndef USE_CURL_MULTI
request->curl_result = request->slot->curl_result;
- curl_easy_getinfo(request->slot->curl,
- CURLINFO_HTTP_CODE,
- &request->http_code);
+ request->http_code = request->slot->http_code;
request->slot = NULL;
/* Use alternates if necessary */
request->slot = NULL;
/* Use alternates if necessary */
- if (request->http_code == 404 &&
- request->repo->next != NULL) {
- request->repo = request->repo->next;
- start_request(request);
+ if (request->http_code == 404) {
+ fetch_alternates(alt->base);
+ if (request->repo->next != NULL) {
+ request->repo = request->repo->next;
+ start_request(request);
+ }
} else {
finish_request(request);
request->state = COMPLETE;
} else {
finish_request(request);
request->state = COMPLETE;
@@
-1049,7
+1100,12
@@
static int fetch_object(struct alt_base *repo, unsigned char *sha1)
}
if (request->curl_result != CURLE_OK && request->http_code != 416) {
}
if (request->curl_result != CURLE_OK && request->http_code != 416) {
- ret = error("%s", request->errorstr);
+ if (request->http_code == 404)
+ ret = -1; /* Be silent, it is probably in a pack. */
+ else
+ ret = error("%s (curl_result = %d, http_code = %ld, sha1 = %s)",
+ request->errorstr, request->curl_result,
+ request->http_code, hex);
release_request(request);
return ret;
}
release_request(request);
return ret;
}
@@
-1086,6
+1142,7
@@
int fetch(unsigned char *sha1)
while (altbase) {
if (!fetch_pack(altbase, sha1))
return 0;
while (altbase) {
if (!fetch_pack(altbase, sha1))
return 0;
+ fetch_alternates(alt->base);
altbase = altbase->next;
}
return error("Unable to find %s under %s\n", sha1_to_hex(sha1),
altbase = altbase->next;
}
return error("Unable to find %s under %s\n", sha1_to_hex(sha1),
@@
-1175,6
+1232,10
@@
int main(int argc, char **argv)
char *url;
int arg = 1;
struct active_request_slot *slot;
char *url;
int arg = 1;
struct active_request_slot *slot;
+ char *low_speed_limit;
+ char *low_speed_time;
+ char *wait_url;
+ int rc = 0;
while (arg < argc && argv[arg][0] == '-') {
if (argv[arg][1] == 't') {
while (arg < argc && argv[arg][0] == '-') {
if (argv[arg][1] == 't') {
@@
-1205,9
+1266,11
@@
int main(int argc, char **argv)
curl_global_init(CURL_GLOBAL_ALL);
#ifdef USE_CURL_MULTI
curl_global_init(CURL_GLOBAL_ALL);
#ifdef USE_CURL_MULTI
- char *http_max_requests = getenv("GIT_HTTP_MAX_REQUESTS");
- if (http_max_requests != NULL)
- max_requests = atoi(http_max_requests);
+ {
+ char *http_max_requests = getenv("GIT_HTTP_MAX_REQUESTS");
+ if (http_max_requests != NULL)
+ max_requests = atoi(http_max_requests);
+ }
curlm = curl_multi_init();
if (curlm == NULL) {
curlm = curl_multi_init();
if (curlm == NULL) {
@@
-1228,6
+1291,13
@@
int main(int argc, char **argv)
#endif
ssl_cainfo = getenv("GIT_SSL_CAINFO");
#endif
ssl_cainfo = getenv("GIT_SSL_CAINFO");
+ low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
+ if (low_speed_limit != NULL)
+ curl_low_speed_limit = strtol(low_speed_limit, NULL, 10);
+ low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME");
+ if (low_speed_time != NULL)
+ curl_low_speed_time = strtol(low_speed_time, NULL, 10);
+
git_config(http_options);
if (curl_ssl_verify == -1)
git_config(http_options);
if (curl_ssl_verify == -1)
@@
-1251,10
+1321,9
@@
int main(int argc, char **argv)
alt->got_indices = 0;
alt->packs = NULL;
alt->next = NULL;
alt->got_indices = 0;
alt->packs = NULL;
alt->next = NULL;
- fetch_alternates(alt->base);
if (pull(commit_id))
if (pull(commit_id))
- r
eturn
1;
+ r
c =
1;
curl_slist_free_all(pragma_header);
curl_slist_free_all(no_pragma_header);
curl_slist_free_all(pragma_header);
curl_slist_free_all(no_pragma_header);
@@
-1264,12
+1333,22
@@
int main(int argc, char **argv)
#endif
slot = active_queue_head;
while (slot != NULL) {
#endif
slot = active_queue_head;
while (slot != NULL) {
- curl_easy_cleanup(slot->curl);
+ if (slot->in_use) {
+ if (get_verbosely) {
+ curl_easy_getinfo(slot->curl,
+ CURLINFO_EFFECTIVE_URL,
+ &wait_url);
+ fprintf(stderr, "Waiting for %s\n", wait_url);
+ }
+ run_active_slot(slot);
+ }
+ if (slot->curl != NULL)
+ curl_easy_cleanup(slot->curl);
slot = slot->next;
}
#ifdef USE_CURL_MULTI
curl_multi_cleanup(curlm);
#endif
curl_global_cleanup();
slot = slot->next;
}
#ifdef USE_CURL_MULTI
curl_multi_cleanup(curlm);
#endif
curl_global_cleanup();
- return
0
;
+ return
rc
;
}
}