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>
Brandon Williams committed
Oct 16, 2017 at 10:55 UTC
19113a26b667527dc983920bf526b5c938d475bb
4 files changed
+96
cache.h
+2
@@ -452,6 +452,8 @@ static inline enum object_type object_type(unsigned int mode)
452
* ignored.
453
*/
454
#define GIT_PROTOCOL_ENVIRONMENT "GIT_PROTOCOL"
455
+/* HTTP header used to handshake the wire protocol */
456
+#define GIT_PROTOCOL_HEADER "Git-Protocol"
457
458
/*
459
* This environment variable is expected to contain a boolean indicating
http.c
+18
@@ -12,6 +12,7 @@
12
#include "gettext.h"
13
#include "transport.h"
14
#include "packfile.h"
15
+#include "protocol.h"
16
17
static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
18
#if LIBCURL_VERSION_NUM >= 0x070a08
@@ -897,6 +898,21 @@ static void set_from_env(const char **var, const char *envname)
898
*var = val;
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
+
916
void http_init(struct remote *remote, const char *url, int proactive_auth)
917
{
918
char *low_speed_limit;
@@ -927,6 +943,8 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
943
if (remote)
944
var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);
945
946
+ protocol_http_header();
947
+
948
pragma_header = curl_slist_append(http_copy_default_headers(),
949
"Pragma: no-cache");
950
no_pragma_header = curl_slist_append(http_copy_default_headers(),
t/lib-httpd/apache.conf
+7
@@ -67,6 +67,9 @@ LockFile accept.lock
67
<IfModule !mod_unixd.c>
68
LoadModule unixd_module modules/mod_unixd.so
69
</IfModule>
70
+<IfModule !mod_setenvif.c>
71
+ LoadModule setenvif_module modules/mod_setenvif.so
72
+</IfModule>
73
</IfVersion>
74
75
PassEnv GIT_VALGRIND
@@ -76,6 +79,10 @@ PassEnv ASAN_OPTIONS
79
PassEnv GIT_TRACE
80
PassEnv GIT_CONFIG_NOSYSTEM
81
82
+<IfVersion >= 2.4>
83
+ SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0
84
+</IfVersion>
85
+
86
Alias /dumb/ www/
87
Alias /auth/dumb/ www/auth/dumb/
88
t/t5700-protocol-v1.sh
+69
@@ -220,4 +220,73 @@ test_expect_success 'push with ssh:// using protocol v1' '
220
grep "push< version 1" log
221
'
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
+
292
test_done