From: Junio C Hamano Date: Tue, 20 Nov 2012 18:30:17 +0000 (-0800) Subject: Merge branch 'jk/maint-http-half-auth-fetch' X-Git-Tag: v1.8.1-rc0~54 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/a9bb4e55a3a552a705f8a6222e4523ed27bb7cc8?hp=-c Merge branch 'jk/maint-http-half-auth-fetch' Fixes fetch from servers that ask for auth only during the actual packing phase. This is not really a recommended configuration, but it cleans up the code at the same time. * jk/maint-http-half-auth-fetch: remote-curl: retry failed requests for auth even with gzip remote-curl: hoist gzip buffer size to top of post_rpc --- a9bb4e55a3a552a705f8a6222e4523ed27bb7cc8 diff --combined remote-curl.c index 278fecdd9b,fac2befd86..d8b3600bdd --- a/remote-curl.c +++ b/remote-curl.c @@@ -95,16 -95,15 +95,16 @@@ static struct discovery* discover_refs( struct strbuf buffer = STRBUF_INIT; struct discovery *last = last_discovery; char *refs_url; - int http_ret, is_http = 0, proto_git_candidate = 1; + int http_ret, maybe_smart = 0; if (last && !strcmp(service, last->service)) return last; free_discovery(last); strbuf_addf(&buffer, "%sinfo/refs", url); - if (!prefixcmp(url, "http://") || !prefixcmp(url, "https://")) { - is_http = 1; + if ((!prefixcmp(url, "http://") || !prefixcmp(url, "https://")) && + git_env_bool("GIT_SMART_HTTP", 1)) { + maybe_smart = 1; if (!strchr(url, '?')) strbuf_addch(&buffer, '?'); else @@@ -114,6 -113,19 +114,6 @@@ refs_url = strbuf_detach(&buffer, NULL); http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE); - - /* try again with "plain" url (no ? or & appended) */ - if (http_ret != HTTP_OK && http_ret != HTTP_NOAUTH) { - free(refs_url); - strbuf_reset(&buffer); - - proto_git_candidate = 0; - strbuf_addf(&buffer, "%sinfo/refs", url); - refs_url = strbuf_detach(&buffer, NULL); - - http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE); - } - switch (http_ret) { case HTTP_OK: break; @@@ -132,7 -144,8 +132,7 @@@ last->buf_alloc = strbuf_detach(&buffer, &last->len); last->buf = last->buf_alloc; - if (is_http && proto_git_candidate - && 5 <= last->len && last->buf[4] == '#') { + if (maybe_smart && 5 <= last->len && last->buf[4] == '#') { /* smart HTTP response; validate that the service * pkt-line matches our request. */ @@@ -380,7 -393,7 +380,7 @@@ static int probe_rpc(struct rpc_state * curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0); curl_easy_setopt(slot->curl, CURLOPT_POST, 1); curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url); - curl_easy_setopt(slot->curl, CURLOPT_ENCODING, ""); + curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL); curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000"); curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers); @@@ -400,6 -413,7 +400,7 @@@ static int post_rpc(struct rpc_state *r struct curl_slist *headers = NULL; int use_gzip = rpc->gzip_request; char *gzip_body = NULL; + size_t gzip_size; int err, large_request = 0; /* Try to load the entire request, if we can fit it into the @@@ -441,7 -455,7 +442,7 @@@ retry curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0); curl_easy_setopt(slot->curl, CURLOPT_POST, 1); curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url); - curl_easy_setopt(slot->curl, CURLOPT_ENCODING, ""); + curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip"); if (large_request) { /* The request body is large and the size cannot be predicted. @@@ -460,24 -474,32 +461,32 @@@ fflush(stderr); } + } else if (gzip_body) { + /* + * If we are looping to retry authentication, then the previous + * run will have set up the headers and gzip buffer already, + * and we just need to send it. + */ + curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body); + curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size); + } else if (use_gzip && 1024 < rpc->len) { /* The client backend isn't giving us compressed data so * we can try to deflate it ourselves, this may save on. * the transfer time. */ - size_t size; git_zstream stream; int ret; memset(&stream, 0, sizeof(stream)); git_deflate_init_gzip(&stream, Z_BEST_COMPRESSION); - size = git_deflate_bound(&stream, rpc->len); - gzip_body = xmalloc(size); + gzip_size = git_deflate_bound(&stream, rpc->len); + gzip_body = xmalloc(gzip_size); stream.next_in = (unsigned char *)rpc->buf; stream.avail_in = rpc->len; stream.next_out = (unsigned char *)gzip_body; - stream.avail_out = size; + stream.avail_out = gzip_size; ret = git_deflate(&stream, Z_FINISH); if (ret != Z_STREAM_END) @@@ -487,16 -509,16 +496,16 @@@ if (ret != Z_OK) die("cannot deflate request; zlib end error %d", ret); - size = stream.total_out; + gzip_size = stream.total_out; headers = curl_slist_append(headers, "Content-Encoding: gzip"); curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body); - curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, size); + curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size); if (options.verbosity > 1) { fprintf(stderr, "POST %s (gzip %lu to %lu bytes)\n", rpc->service_name, - (unsigned long)rpc->len, (unsigned long)size); + (unsigned long)rpc->len, (unsigned long)gzip_size); fflush(stderr); } } else { @@@ -517,7 -539,7 +526,7 @@@ curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc); err = run_slot(slot); - if (err == HTTP_REAUTH && !large_request && !use_gzip) + if (err == HTTP_REAUTH && !large_request) goto retry; if (err != HTTP_OK) err = -1; diff --combined t/lib-httpd/apache.conf index 49d5d877ce,15a3c71555..fe76e84b74 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@@ -42,9 -42,6 +42,9 @@@ ErrorLog error.lo +PassEnv GIT_VALGRIND +PassEnv GIT_VALGRIND_OPTIONS + Alias /dumb/ www/ Alias /auth/dumb/ www/auth/dumb/ @@@ -63,7 -60,7 +63,7 @@@ ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1 - Options None + Options FollowSymlinks Options ExecCGI @@@ -99,6 -96,13 +99,13 @@@ SSLEngine O Require valid-user + + AuthType Basic + AuthName "git-auth" + AuthUserFile passwd + Require valid-user + + LoadModule dav_module modules/mod_dav.so LoadModule dav_fs_module modules/mod_dav_fs.so diff --combined t/t5551-http-fetch.sh index 5060879d6d,5f174da3c7..c5cd2e348c --- a/t/t5551-http-fetch.sh +++ b/t/t5551-http-fetch.sh @@@ -32,14 -32,13 +32,14 @@@ setup_askpass_helpe cat >exp < GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 > Accept: */* +> Accept-Encoding: gzip > Pragma: no-cache < HTTP/1.1 200 OK < Pragma: no-cache < Cache-Control: no-cache, max-age=0, must-revalidate < Content-Type: application/x-git-upload-pack-advertisement > POST /smart/repo.git/git-upload-pack HTTP/1.1 -> Accept-Encoding: deflate, gzip +> Accept-Encoding: gzip > Content-Type: application/x-git-upload-pack-request > Accept: application/x-git-upload-pack-result > Content-Length: xxx @@@ -130,24 -129,27 +130,39 @@@ test_expect_success 'clone from auth-on test_cmp expect actual ' + test_expect_success 'clone from auth-only-for-objects repository' ' + echo two >expect && + set_askpass user@host && + git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth && + expect_askpass both user@host && + git --git-dir=half-auth log -1 --format=%s >actual && + test_cmp expect actual + ' + + test_expect_success 'no-op half-auth fetch does not require a password' ' + set_askpass wrong && + git --git-dir=half-auth fetch && + expect_askpass none + ' + +test_expect_success 'disable dumb http on server' ' + git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \ + config http.getanyfile false +' + +test_expect_success 'GIT_SMART_HTTP can disable smart http' ' + (GIT_SMART_HTTP=0 && + export GIT_SMART_HTTP && + cd clone && + test_must_fail git fetch) +' + test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE test_expect_success EXPENSIVE 'create 50,000 tags in the repo' ' ( cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && - for i in `seq 50000` + for i in `test_seq 50000` do echo "commit refs/heads/too-many-refs" echo "mark :$i" @@@ -163,7 -165,7 +178,7 @@@ done | git fast-import --export-marks=marks && # now assign tags to all the dangling commits we created above - tag=$(perl -e "print \"bla\" x 30") && + tag=$("$PERL_PATH" -e "print \"bla\" x 30") && sed -e "s/^:\(.\+\) \(.\+\)$/\2 refs\/tags\/$tag-\1/" >packed-refs ) '