Skip to content

Commit cabb41d

Browse files
committed
Merge branch 'jk/http-server-protocol-versions'
Taking advantage of the CGI interface, http-backend has been updated to enable protocol v2 automatically when the other side asks for it. * jk/http-server-protocol-versions: docs/protocol-v2: point readers transport config discussion docs/git: discuss server-side config for GIT_PROTOCOL docs/http-backend: mention v2 protocol http-backend: handle HTTP_GIT_PROTOCOL CGI variable t5551: test v2-to-v0 http protocol fallback
2 parents b5866ed + 1b421e7 commit cabb41d

File tree

7 files changed

+73
-4
lines changed

7 files changed

+73
-4
lines changed

Documentation/git-http-backend.txt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ A simple CGI program to serve the contents of a Git repository to Git
1616
clients accessing the repository over http:// and https:// protocols.
1717
The program supports clients fetching using both the smart HTTP protocol
1818
and the backwards-compatible dumb HTTP protocol, as well as clients
19-
pushing using the smart HTTP protocol.
19+
pushing using the smart HTTP protocol. It also supports Git's
20+
more-efficient "v2" protocol if properly configured; see the
21+
discussion of `GIT_PROTOCOL` in the ENVIRONMENT section below.
2022

2123
It verifies that the directory has the magic file
2224
"git-daemon-export-ok", and it will refuse to export any Git directory
@@ -77,6 +79,18 @@ Apache 2.x::
7779
SetEnv GIT_PROJECT_ROOT /var/www/git
7880
SetEnv GIT_HTTP_EXPORT_ALL
7981
ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
82+
83+
# This is not strictly necessary using Apache and a modern version of
84+
# git-http-backend, as the webserver will pass along the header in the
85+
# environment as HTTP_GIT_PROTOCOL, and http-backend will copy that into
86+
# GIT_PROTOCOL. But you may need this line (or something similar if you
87+
# are using a different webserver), or if you want to support older Git
88+
# versions that did not do that copying.
89+
#
90+
# Having the webserver set up GIT_PROTOCOL is perfectly fine even with
91+
# modern versions (and will take precedence over HTTP_GIT_PROTOCOL,
92+
# which means it can be used to override the client's request).
93+
SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0
8094
----------------------------------------------------------------
8195
+
8296
To enable anonymous read access but authenticated write access,
@@ -264,6 +278,16 @@ a repository with an extremely large number of refs. The value can be
264278
specified with a unit (e.g., `100M` for 100 megabytes). The default is
265279
10 megabytes.
266280

281+
Clients may probe for optional protocol capabilities (like the v2
282+
protocol) using the `Git-Protocol` HTTP header. In order to support
283+
these, the contents of that header must appear in the `GIT_PROTOCOL`
284+
environment variable. Most webservers will pass this header to the CGI
285+
via the `HTTP_GIT_PROTOCOL` variable, and `git-http-backend` will
286+
automatically copy that to `GIT_PROTOCOL`. However, some webservers may
287+
be more selective about which headers they'll pass, in which case they
288+
need to be configured explicitly (see the mention of `Git-Protocol` in
289+
the Apache config from the earlier EXAMPLES section).
290+
267291
The backend process sets GIT_COMMITTER_NAME to '$REMOTE_USER' and
268292
GIT_COMMITTER_EMAIL to '$\{REMOTE_USER}@http.$\{REMOTE_ADDR\}',
269293
ensuring that any reflogs created by 'git-receive-pack' contain some

Documentation/git-upload-pack.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ OPTIONS
4848
<directory>::
4949
The repository to sync from.
5050

51+
ENVIRONMENT
52+
-----------
53+
54+
`GIT_PROTOCOL`::
55+
Internal variable used for handshaking the wire protocol. Server
56+
admins may need to configure some transports to allow this
57+
variable to be passed. See the discussion in linkgit:git[1].
58+
5159
SEE ALSO
5260
--------
5361
linkgit:gitnamespaces[7]

Documentation/git.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,21 @@ for full details.
894894
Contains a colon ':' separated list of keys with optional values
895895
'key[=value]'. Presence of unknown keys and values must be
896896
ignored.
897+
+
898+
Note that servers may need to be configured to allow this variable to
899+
pass over some transports. It will be propagated automatically when
900+
accessing local repositories (i.e., `file://` or a filesystem path), as
901+
well as over the `git://` protocol. For git-over-http, it should work
902+
automatically in most configurations, but see the discussion in
903+
linkgit:git-http-backend[1]. For git-over-ssh, the ssh server may need
904+
to be configured to allow clients to pass this variable (e.g., by using
905+
`AcceptEnv GIT_PROTOCOL` with OpenSSH).
906+
+
907+
This configuration is optional. If the variable is not propagated, then
908+
clients will fall back to the original "v0" protocol (but may miss out
909+
on some performance improvements or features). This variable currently
910+
only affects clones and fetches; it is not yet used for pushes (but may
911+
be in the future).
897912

898913
`GIT_OPTIONAL_LOCKS`::
899914
If set to `0`, Git will complete any requested operation without

Documentation/technical/protocol-v2.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ Initial Client Request
4242
In general a client can request to speak protocol v2 by sending
4343
`version=2` through the respective side-channel for the transport being
4444
used which inevitably sets `GIT_PROTOCOL`. More information can be
45-
found in `pack-protocol.txt` and `http-protocol.txt`. In all cases the
45+
found in `pack-protocol.txt` and `http-protocol.txt`, as well as the
46+
`GIT_PROTOCOL` definition in `git.txt`. In all cases the
4647
response from the server is the capability advertisement.
4748

4849
Git Transport
@@ -58,6 +59,8 @@ SSH and File Transport
5859

5960
When using either the ssh:// or file:// transport, the GIT_PROTOCOL
6061
environment variable must be set explicitly to include "version=2".
62+
The server may need to be configured to allow this environment variable
63+
to pass.
6164

6265
HTTP Transport
6366
~~~~~~~~~~~~~~
@@ -84,6 +87,9 @@ Subsequent requests are then made directly to the service
8487
Uses the `--http-backend-info-refs` option to
8588
linkgit:git-upload-pack[1].
8689

90+
The server may need to be configured to pass this header's contents via
91+
the `GIT_PROTOCOL` variable. See the discussion in `git-http-backend.txt`.
92+
8793
Capability Advertisement
8894
------------------------
8995

http-backend.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,7 @@ static int bad_request(struct strbuf *hdr, const struct service_cmd *c)
739739
int cmd_main(int argc, const char **argv)
740740
{
741741
char *method = getenv("REQUEST_METHOD");
742+
const char *proto_header;
742743
char *dir;
743744
struct service_cmd *cmd = NULL;
744745
char *cmd_arg = NULL;
@@ -789,6 +790,9 @@ int cmd_main(int argc, const char **argv)
789790
http_config();
790791
max_request_buffer = git_env_ulong("GIT_HTTP_MAX_REQUEST_BUFFER",
791792
max_request_buffer);
793+
proto_header = getenv("HTTP_GIT_PROTOCOL");
794+
if (proto_header)
795+
setenv(GIT_PROTOCOL_ENVIRONMENT, proto_header, 0);
792796

793797
cmd->imp(&hdr, cmd_arg);
794798
return 0;

t/lib-httpd/apache.conf

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ PassEnv GIT_TRACE
8181
PassEnv GIT_CONFIG_NOSYSTEM
8282
PassEnv GIT_TEST_SIDEBAND_ALL
8383

84-
SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0
85-
8684
Alias /dumb/ www/
8785
Alias /auth/dumb/ www/auth/dumb/
8886

@@ -117,6 +115,11 @@ Alias /auth/dumb/ www/auth/dumb/
117115
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
118116
SetEnv GIT_HTTP_EXPORT_ALL
119117
</LocationMatch>
118+
<LocationMatch /smart_v0/>
119+
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
120+
SetEnv GIT_HTTP_EXPORT_ALL
121+
SetEnv GIT_PROTOCOL
122+
</LocationMatch>
120123
ScriptAlias /smart/incomplete_length/git-upload-pack incomplete-length-upload-pack-v2-http.sh/
121124
ScriptAlias /smart/incomplete_body/git-upload-pack incomplete-body-upload-pack-v2-http.sh/
122125
ScriptAliasMatch /error_git_upload_pack/(.*)/git-upload-pack error.sh/

t/t5551-http-fetch-smart.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,4 +558,13 @@ test_expect_success 'http auth forgets bogus credentials' '
558558
expect_askpass both user@host
559559
'
560560

561+
test_expect_success 'client falls back from v2 to v0 to match server' '
562+
GIT_TRACE_PACKET=$PWD/trace \
563+
GIT_TEST_PROTOCOL_VERSION=2 \
564+
git clone $HTTPD_URL/smart_v0/repo.git repo-v0 &&
565+
# check for v0; there the HEAD symref is communicated in the capability
566+
# line; v2 uses a different syntax on each ref advertisement line
567+
grep symref=HEAD:refs/heads/ trace
568+
'
569+
561570
test_done

0 commit comments

Comments
 (0)