Git fork

http: tell server that the client understands v1

Tell a server that protocol v1 can be used by sending the http header
'Git-Protocol' with 'version=1' indicating this.

Also teach the apache http server to pass through the 'Git-Protocol'
header as an environment variable 'GIT_PROTOCOL'.

Signed-off-by: Brandon Williams <bmwill@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Brandon Williams and committed by
Junio C Hamano
19113a26 0c2f0d27

+96
+2
cache.h
··· 452 452 * ignored. 453 453 */ 454 454 #define GIT_PROTOCOL_ENVIRONMENT "GIT_PROTOCOL" 455 + /* HTTP header used to handshake the wire protocol */ 456 + #define GIT_PROTOCOL_HEADER "Git-Protocol" 455 457 456 458 /* 457 459 * This environment variable is expected to contain a boolean indicating
+18
http.c
··· 12 12 #include "gettext.h" 13 13 #include "transport.h" 14 14 #include "packfile.h" 15 + #include "protocol.h" 15 16 16 17 static struct trace_key trace_curl = TRACE_KEY_INIT(CURL); 17 18 #if LIBCURL_VERSION_NUM >= 0x070a08 ··· 897 898 *var = val; 898 899 } 899 900 901 + static void protocol_http_header(void) 902 + { 903 + if (get_protocol_version_config() > 0) { 904 + struct strbuf protocol_header = STRBUF_INIT; 905 + 906 + strbuf_addf(&protocol_header, GIT_PROTOCOL_HEADER ": version=%d", 907 + get_protocol_version_config()); 908 + 909 + 910 + extra_http_headers = curl_slist_append(extra_http_headers, 911 + protocol_header.buf); 912 + strbuf_release(&protocol_header); 913 + } 914 + } 915 + 900 916 void http_init(struct remote *remote, const char *url, int proactive_auth) 901 917 { 902 918 char *low_speed_limit; ··· 926 942 927 943 if (remote) 928 944 var_override(&http_proxy_authmethod, remote->http_proxy_authmethod); 945 + 946 + protocol_http_header(); 929 947 930 948 pragma_header = curl_slist_append(http_copy_default_headers(), 931 949 "Pragma: no-cache");
+7
t/lib-httpd/apache.conf
··· 67 67 <IfModule !mod_unixd.c> 68 68 LoadModule unixd_module modules/mod_unixd.so 69 69 </IfModule> 70 + <IfModule !mod_setenvif.c> 71 + LoadModule setenvif_module modules/mod_setenvif.so 72 + </IfModule> 70 73 </IfVersion> 71 74 72 75 PassEnv GIT_VALGRIND ··· 75 78 PassEnv ASAN_OPTIONS 76 79 PassEnv GIT_TRACE 77 80 PassEnv GIT_CONFIG_NOSYSTEM 81 + 82 + <IfVersion >= 2.4> 83 + SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0 84 + </IfVersion> 78 85 79 86 Alias /dumb/ www/ 80 87 Alias /auth/dumb/ www/auth/dumb/
+69
t/t5700-protocol-v1.sh
··· 220 220 grep "push< version 1" log 221 221 ' 222 222 223 + # Test protocol v1 with 'http://' transport 224 + # 225 + . "$TEST_DIRECTORY"/lib-httpd.sh 226 + start_httpd 227 + 228 + test_expect_success 'create repo to be served by http:// transport' ' 229 + git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && 230 + git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" config http.receivepack true && 231 + test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one 232 + ' 233 + 234 + test_expect_success 'clone with http:// using protocol v1' ' 235 + GIT_TRACE_PACKET=1 GIT_TRACE_CURL=1 git -c protocol.version=1 \ 236 + clone "$HTTPD_URL/smart/http_parent" http_child 2>log && 237 + 238 + git -C http_child log -1 --format=%s >actual && 239 + git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" log -1 --format=%s >expect && 240 + test_cmp expect actual && 241 + 242 + # Client requested to use protocol v1 243 + grep "Git-Protocol: version=1" log && 244 + # Server responded using protocol v1 245 + grep "git< version 1" log 246 + ' 247 + 248 + test_expect_success 'fetch with http:// using protocol v1' ' 249 + test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two && 250 + 251 + GIT_TRACE_PACKET=1 git -C http_child -c protocol.version=1 \ 252 + fetch 2>log && 253 + 254 + git -C http_child log -1 --format=%s origin/master >actual && 255 + git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" log -1 --format=%s >expect && 256 + test_cmp expect actual && 257 + 258 + # Server responded using protocol v1 259 + grep "git< version 1" log 260 + ' 261 + 262 + test_expect_success 'pull with http:// using protocol v1' ' 263 + GIT_TRACE_PACKET=1 git -C http_child -c protocol.version=1 \ 264 + pull 2>log && 265 + 266 + git -C http_child log -1 --format=%s >actual && 267 + git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" log -1 --format=%s >expect && 268 + test_cmp expect actual && 269 + 270 + # Server responded using protocol v1 271 + grep "git< version 1" log 272 + ' 273 + 274 + test_expect_success 'push with http:// using protocol v1' ' 275 + test_commit -C http_child three && 276 + 277 + # Push to another branch, as the target repository has the 278 + # master branch checked out and we cannot push into it. 279 + GIT_TRACE_PACKET=1 git -C http_child -c protocol.version=1 \ 280 + push origin HEAD:client_branch && #2>log && 281 + 282 + git -C http_child log -1 --format=%s >actual && 283 + git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" log -1 --format=%s client_branch >expect && 284 + test_cmp expect actual && 285 + 286 + # Server responded using protocol v1 287 + grep "git< version 1" log 288 + ' 289 + 290 + stop_httpd 291 + 223 292 test_done