diff options
Diffstat (limited to 'remote-curl.c')
| -rw-r--r-- | remote-curl.c | 90 |
1 files changed, 57 insertions, 33 deletions
diff --git a/remote-curl.c b/remote-curl.c index 0b6d7815fd..4adcf25ed6 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "git-curl-compat.h" #include "config.h" @@ -58,9 +60,9 @@ struct options { static struct options options; static struct string_list cas_options = STRING_LIST_INIT_DUP; -static int set_option(const char *name, const char *value) +static int set_option(const char *name, size_t namelen, const char *value) { - if (!strcmp(name, "verbosity")) { + if (!strncmp(name, "verbosity", namelen)) { char *end; int v = strtol(value, &end, 10); if (value == end || *end) @@ -68,7 +70,7 @@ static int set_option(const char *name, const char *value) options.verbosity = v; return 0; } - else if (!strcmp(name, "progress")) { + else if (!strncmp(name, "progress", namelen)) { if (!strcmp(value, "true")) options.progress = 1; else if (!strcmp(value, "false")) @@ -77,7 +79,7 @@ static int set_option(const char *name, const char *value) return -1; return 0; } - else if (!strcmp(name, "depth")) { + else if (!strncmp(name, "depth", namelen)) { char *end; unsigned long v = strtoul(value, &end, 10); if (value == end || *end) @@ -85,15 +87,15 @@ static int set_option(const char *name, const char *value) options.depth = v; return 0; } - else if (!strcmp(name, "deepen-since")) { + else if (!strncmp(name, "deepen-since", namelen)) { options.deepen_since = xstrdup(value); return 0; } - else if (!strcmp(name, "deepen-not")) { + else if (!strncmp(name, "deepen-not", namelen)) { string_list_append(&options.deepen_not, value); return 0; } - else if (!strcmp(name, "deepen-relative")) { + else if (!strncmp(name, "deepen-relative", namelen)) { if (!strcmp(value, "true")) options.deepen_relative = 1; else if (!strcmp(value, "false")) @@ -102,7 +104,7 @@ static int set_option(const char *name, const char *value) return -1; return 0; } - else if (!strcmp(name, "followtags")) { + else if (!strncmp(name, "followtags", namelen)) { if (!strcmp(value, "true")) options.followtags = 1; else if (!strcmp(value, "false")) @@ -111,7 +113,7 @@ static int set_option(const char *name, const char *value) return -1; return 0; } - else if (!strcmp(name, "dry-run")) { + else if (!strncmp(name, "dry-run", namelen)) { if (!strcmp(value, "true")) options.dry_run = 1; else if (!strcmp(value, "false")) @@ -120,7 +122,7 @@ static int set_option(const char *name, const char *value) return -1; return 0; } - else if (!strcmp(name, "check-connectivity")) { + else if (!strncmp(name, "check-connectivity", namelen)) { if (!strcmp(value, "true")) options.check_self_contained_and_connected = 1; else if (!strcmp(value, "false")) @@ -129,7 +131,7 @@ static int set_option(const char *name, const char *value) return -1; return 0; } - else if (!strcmp(name, "cas")) { + else if (!strncmp(name, "cas", namelen)) { struct strbuf val = STRBUF_INIT; strbuf_addstr(&val, "--force-with-lease="); if (*value != '"') @@ -139,7 +141,7 @@ static int set_option(const char *name, const char *value) string_list_append(&cas_options, val.buf); strbuf_release(&val); return 0; - } else if (!strcmp(name, TRANS_OPT_FORCE_IF_INCLUDES)) { + } else if (!strncmp(name, TRANS_OPT_FORCE_IF_INCLUDES, namelen)) { if (!strcmp(value, "true")) options.force_if_includes = 1; else if (!strcmp(value, "false")) @@ -147,7 +149,7 @@ static int set_option(const char *name, const char *value) else return -1; return 0; - } else if (!strcmp(name, "cloning")) { + } else if (!strncmp(name, "cloning", namelen)) { if (!strcmp(value, "true")) options.cloning = 1; else if (!strcmp(value, "false")) @@ -155,7 +157,7 @@ static int set_option(const char *name, const char *value) else return -1; return 0; - } else if (!strcmp(name, "update-shallow")) { + } else if (!strncmp(name, "update-shallow", namelen)) { if (!strcmp(value, "true")) options.update_shallow = 1; else if (!strcmp(value, "false")) @@ -163,7 +165,7 @@ static int set_option(const char *name, const char *value) else return -1; return 0; - } else if (!strcmp(name, "pushcert")) { + } else if (!strncmp(name, "pushcert", namelen)) { if (!strcmp(value, "true")) options.push_cert = SEND_PACK_PUSH_CERT_ALWAYS; else if (!strcmp(value, "false")) @@ -173,7 +175,7 @@ static int set_option(const char *name, const char *value) else return -1; return 0; - } else if (!strcmp(name, "atomic")) { + } else if (!strncmp(name, "atomic", namelen)) { if (!strcmp(value, "true")) options.atomic = 1; else if (!strcmp(value, "false")) @@ -181,7 +183,7 @@ static int set_option(const char *name, const char *value) else return -1; return 0; - } else if (!strcmp(name, "push-option")) { + } else if (!strncmp(name, "push-option", namelen)) { if (*value != '"') string_list_append(&options.push_options, value); else { @@ -192,7 +194,7 @@ static int set_option(const char *name, const char *value) strbuf_detach(&unquoted, NULL)); } return 0; - } else if (!strcmp(name, "family")) { + } else if (!strncmp(name, "family", namelen)) { if (!strcmp(value, "ipv4")) git_curl_ipresolve = CURL_IPRESOLVE_V4; else if (!strcmp(value, "ipv6")) @@ -202,16 +204,16 @@ static int set_option(const char *name, const char *value) else return -1; return 0; - } else if (!strcmp(name, "from-promisor")) { + } else if (!strncmp(name, "from-promisor", namelen)) { options.from_promisor = 1; return 0; - } else if (!strcmp(name, "refetch")) { + } else if (!strncmp(name, "refetch", namelen)) { options.refetch = 1; return 0; - } else if (!strcmp(name, "filter")) { + } else if (!strncmp(name, "filter", namelen)) { options.filter = xstrdup(value); return 0; - } else if (!strcmp(name, "object-format")) { + } else if (!strncmp(name, "object-format", namelen)) { options.object_format = 1; if (strcmp(value, "true")) die(_("unknown value for object-format: %s"), value); @@ -266,12 +268,23 @@ static struct ref *parse_git_refs(struct discovery *heads, int for_push) return list; } +/* + * Try to detect the hash algorithm used by the remote repository when using + * the dumb HTTP transport. As dumb transports cannot tell us the object hash + * directly have to derive it from the advertised ref lengths. + */ static const struct git_hash_algo *detect_hash_algo(struct discovery *heads) { const char *p = memchr(heads->buf, '\t', heads->len); int algo; + + /* + * In case the remote has no refs we have no way to reliably determine + * the object hash used by that repository. In that case we simply fall + * back to SHA1, which may or may not be correct. + */ if (!p) - return the_hash_algo; + return &hash_algos[GIT_HASH_SHA1]; algo = hash_algo_by_length((p - heads->buf) / 2); if (algo == GIT_HASH_UNKNOWN) @@ -295,6 +308,12 @@ static struct ref *parse_info_refs(struct discovery *heads) "is this a git repository?", transport_anonymize_url(url.buf)); + /* + * Set the repository's hash algo to whatever we have just detected. + * This ensures that we can correctly parse the remote references. + */ + repo_set_hash_algo(the_repository, hash_algo_by_ptr(options.hash_algo)); + data = heads->buf; start = NULL; mid = data; @@ -889,7 +908,7 @@ static curl_off_t xcurl_off_t(size_t len) static int post_rpc(struct rpc_state *rpc, int stateless_connect, int flush_received) { struct active_request_slot *slot; - struct curl_slist *headers = http_copy_default_headers(); + struct curl_slist *headers = NULL; int use_gzip = rpc->gzip_request; char *gzip_body = NULL; size_t gzip_size = 0; @@ -922,20 +941,24 @@ static int post_rpc(struct rpc_state *rpc, int stateless_connect, int flush_rece do { err = probe_rpc(rpc, &results); if (err == HTTP_REAUTH) - credential_fill(&http_auth); + credential_fill(&http_auth, 0); } while (err == HTTP_REAUTH); if (err != HTTP_OK) return -1; - if (results.auth_avail & CURLAUTH_GSSNEGOTIATE) + if (results.auth_avail & CURLAUTH_GSSNEGOTIATE || http_auth.authtype) needs_100_continue = 1; } +retry: + headers = http_copy_default_headers(); headers = curl_slist_append(headers, rpc->hdr_content_type); headers = curl_slist_append(headers, rpc->hdr_accept); headers = curl_slist_append(headers, needs_100_continue ? "Expect: 100-continue" : "Expect:"); + headers = http_append_auth_header(&http_auth, headers); + /* Add Accept-Language header */ if (rpc->hdr_accept_language) headers = curl_slist_append(headers, rpc->hdr_accept_language); @@ -944,7 +967,6 @@ static int post_rpc(struct rpc_state *rpc, int stateless_connect, int flush_rece if (rpc->protocol_header) headers = curl_slist_append(headers, rpc->protocol_header); -retry: slot = get_active_slot(); curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0); @@ -1041,7 +1063,8 @@ retry: rpc->any_written = 0; err = run_slot(slot, NULL); if (err == HTTP_REAUTH && !large_request) { - credential_fill(&http_auth); + credential_fill(&http_auth, 0); + curl_slist_free_all(headers); goto retry; } if (err != HTTP_OK) @@ -1553,7 +1576,7 @@ int cmd_main(int argc, const char **argv) if (argc > 2) { end_url_with_slash(&url, argv[2]); } else { - end_url_with_slash(&url, remote->url[0]); + end_url_with_slash(&url, remote->url.v[0]); } http_init(remote, url.buf, 0); @@ -1584,15 +1607,16 @@ int cmd_main(int argc, const char **argv) parse_push(&buf); } else if (skip_prefix(buf.buf, "option ", &arg)) { - char *value = strchr(arg, ' '); + const char *value = strchrnul(arg, ' '); + size_t arglen = value - arg; int result; - if (value) - *value++ = '\0'; + if (*value) + value++; /* skip over SP */ else value = "true"; - result = set_option(arg, value); + result = set_option(arg, arglen, value); if (!result) printf("ok\n"); else if (result < 0) |
