Skip to content

Commit ed10cb9

Browse files
bmwillgitster
authored andcommitted
serve: introduce git-serve
Introduce git-serve, the base server for protocol version 2. Protocol version 2 is intended to be a replacement for Git's current wire protocol. The intention is that it will be a simpler, less wasteful protocol which can evolve over time. Protocol version 2 improves upon version 1 by eliminating the initial ref advertisement. In its place a server will export a list of capabilities and commands which it supports in a capability advertisement. A client can then request that a particular command be executed by providing a number of capabilities and command specific parameters. At the completion of a command, a client can request that another command be executed or can terminate the connection by sending a flush packet. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 74e7002 commit ed10cb9

File tree

10 files changed

+528
-0
lines changed

10 files changed

+528
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
/git-rm
141141
/git-send-email
142142
/git-send-pack
143+
/git-serve
143144
/git-sh-i18n
144145
/git-sh-i18n--envsubst
145146
/git-sh-setup

Documentation/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ TECH_DOCS += technical/pack-heuristics
7777
TECH_DOCS += technical/pack-protocol
7878
TECH_DOCS += technical/protocol-capabilities
7979
TECH_DOCS += technical/protocol-common
80+
TECH_DOCS += technical/protocol-v2
8081
TECH_DOCS += technical/racy-git
8182
TECH_DOCS += technical/send-pack-pipeline
8283
TECH_DOCS += technical/shallow
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
Git Wire Protocol, Version 2
2+
==============================
3+
4+
This document presents a specification for a version 2 of Git's wire
5+
protocol. Protocol v2 will improve upon v1 in the following ways:
6+
7+
* Instead of multiple service names, multiple commands will be
8+
supported by a single service
9+
* Easily extendable as capabilities are moved into their own section
10+
of the protocol, no longer being hidden behind a NUL byte and
11+
limited by the size of a pkt-line
12+
* Separate out other information hidden behind NUL bytes (e.g. agent
13+
string as a capability and symrefs can be requested using 'ls-refs')
14+
* Reference advertisement will be omitted unless explicitly requested
15+
* ls-refs command to explicitly request some refs
16+
* Designed with http and stateless-rpc in mind. With clear flush
17+
semantics the http remote helper can simply act as a proxy
18+
19+
In protocol v2 communication is command oriented. When first contacting a
20+
server a list of capabilities will advertised. Some of these capabilities
21+
will be commands which a client can request be executed. Once a command
22+
has completed, a client can reuse the connection and request that other
23+
commands be executed.
24+
25+
Packet-Line Framing
26+
---------------------
27+
28+
All communication is done using packet-line framing, just as in v1. See
29+
`Documentation/technical/pack-protocol.txt` and
30+
`Documentation/technical/protocol-common.txt` for more information.
31+
32+
In protocol v2 these special packets will have the following semantics:
33+
34+
* '0000' Flush Packet (flush-pkt) - indicates the end of a message
35+
* '0001' Delimiter Packet (delim-pkt) - separates sections of a message
36+
37+
Initial Client Request
38+
------------------------
39+
40+
In general a client can request to speak protocol v2 by sending
41+
`version=2` through the respective side-channel for the transport being
42+
used which inevitably sets `GIT_PROTOCOL`. More information can be
43+
found in `pack-protocol.txt` and `http-protocol.txt`. In all cases the
44+
response from the server is the capability advertisement.
45+
46+
Git Transport
47+
~~~~~~~~~~~~~~~
48+
49+
When using the git:// transport, you can request to use protocol v2 by
50+
sending "version=2" as an extra parameter:
51+
52+
003egit-upload-pack /project.git\0host=myserver.com\0\0version=2\0
53+
54+
SSH and File Transport
55+
~~~~~~~~~~~~~~~~~~~~~~~~
56+
57+
When using either the ssh:// or file:// transport, the GIT_PROTOCOL
58+
environment variable must be set explicitly to include "version=2".
59+
60+
HTTP Transport
61+
~~~~~~~~~~~~~~~~
62+
63+
When using the http:// or https:// transport a client makes a "smart"
64+
info/refs request as described in `http-protocol.txt` and requests that
65+
v2 be used by supplying "version=2" in the `Git-Protocol` header.
66+
67+
C: Git-Protocol: version=2
68+
C:
69+
C: GET $GIT_URL/info/refs?service=git-upload-pack HTTP/1.0
70+
71+
A v2 server would reply:
72+
73+
S: 200 OK
74+
S: <Some headers>
75+
S: ...
76+
S:
77+
S: 000eversion 2\n
78+
S: <capability-advertisement>
79+
80+
Subsequent requests are then made directly to the service
81+
`$GIT_URL/git-upload-pack`. (This works the same for git-receive-pack).
82+
83+
Capability Advertisement
84+
--------------------------
85+
86+
A server which decides to communicate (based on a request from a client)
87+
using protocol version 2, notifies the client by sending a version string
88+
in its initial response followed by an advertisement of its capabilities.
89+
Each capability is a key with an optional value. Clients must ignore all
90+
unknown keys. Semantics of unknown values are left to the definition of
91+
each key. Some capabilities will describe commands which can be requested
92+
to be executed by the client.
93+
94+
capability-advertisement = protocol-version
95+
capability-list
96+
flush-pkt
97+
98+
protocol-version = PKT-LINE("version 2" LF)
99+
capability-list = *capability
100+
capability = PKT-LINE(key[=value] LF)
101+
102+
key = 1*(ALPHA | DIGIT | "-_")
103+
value = 1*(ALPHA | DIGIT | " -_.,?\/{}[]()<>!@#$%^&*+=:;")
104+
105+
Command Request
106+
-----------------
107+
108+
After receiving the capability advertisement, a client can then issue a
109+
request to select the command it wants with any particular capabilities
110+
or arguments. There is then an optional section where the client can
111+
provide any command specific parameters or queries. Only a single
112+
command can be requested at a time.
113+
114+
request = empty-request | command-request
115+
empty-request = flush-pkt
116+
command-request = command
117+
capability-list
118+
[command-args]
119+
flush-pkt
120+
command = PKT-LINE("command=" key LF)
121+
command-args = delim-pkt
122+
*command-specific-arg
123+
124+
command-specific-args are packet line framed arguments defined by
125+
each individual command.
126+
127+
The server will then check to ensure that the client's request is
128+
comprised of a valid command as well as valid capabilities which were
129+
advertised. If the request is valid the server will then execute the
130+
command. A server MUST wait till it has received the client's entire
131+
request before issuing a response. The format of the response is
132+
determined by the command being executed, but in all cases a flush-pkt
133+
indicates the end of the response.
134+
135+
When a command has finished, and the client has received the entire
136+
response from the server, a client can either request that another
137+
command be executed or can terminate the connection. A client may
138+
optionally send an empty request consisting of just a flush-pkt to
139+
indicate that no more requests will be made.
140+
141+
Capabilities
142+
--------------
143+
144+
There are two different types of capabilities: normal capabilities,
145+
which can be used to to convey information or alter the behavior of a
146+
request, and commands, which are the core actions that a client wants to
147+
perform (fetch, push, etc).
148+
149+
Protocol version 2 is stateless by default. This means that all commands
150+
must only last a single round and be stateless from the perspective of the
151+
server side, unless the client has requested a capability indicating that
152+
state should be maintained by the server. Clients MUST NOT require state
153+
management on the server side in order to function correctly. This
154+
permits simple round-robin load-balancing on the server side, without
155+
needing to worry about state management.
156+
157+
agent
158+
~~~~~~~
159+
160+
The server can advertise the `agent` capability with a value `X` (in the
161+
form `agent=X`) to notify the client that the server is running version
162+
`X`. The client may optionally send its own agent string by including
163+
the `agent` capability with a value `Y` (in the form `agent=Y`) in its
164+
request to the server (but it MUST NOT do so if the server did not
165+
advertise the agent capability). The `X` and `Y` strings may contain any
166+
printable ASCII characters except space (i.e., the byte range 32 < x <
167+
127), and are typically of the form "package/version" (e.g.,
168+
"git/1.8.3.1"). The agent strings are purely informative for statistics
169+
and debugging purposes, and MUST NOT be used to programmatically assume
170+
the presence or absence of particular features.

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,7 @@ LIB_OBJS += revision.o
876876
LIB_OBJS += run-command.o
877877
LIB_OBJS += send-pack.o
878878
LIB_OBJS += sequencer.o
879+
LIB_OBJS += serve.o
879880
LIB_OBJS += server-info.o
880881
LIB_OBJS += setup.o
881882
LIB_OBJS += sha1-array.o
@@ -1009,6 +1010,7 @@ BUILTIN_OBJS += builtin/rev-parse.o
10091010
BUILTIN_OBJS += builtin/revert.o
10101011
BUILTIN_OBJS += builtin/rm.o
10111012
BUILTIN_OBJS += builtin/send-pack.o
1013+
BUILTIN_OBJS += builtin/serve.o
10121014
BUILTIN_OBJS += builtin/shortlog.o
10131015
BUILTIN_OBJS += builtin/show-branch.o
10141016
BUILTIN_OBJS += builtin/show-ref.o

builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
215215
extern int cmd_revert(int argc, const char **argv, const char *prefix);
216216
extern int cmd_rm(int argc, const char **argv, const char *prefix);
217217
extern int cmd_send_pack(int argc, const char **argv, const char *prefix);
218+
extern int cmd_serve(int argc, const char **argv, const char *prefix);
218219
extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
219220
extern int cmd_show(int argc, const char **argv, const char *prefix);
220221
extern int cmd_show_branch(int argc, const char **argv, const char *prefix);

builtin/serve.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include "cache.h"
2+
#include "builtin.h"
3+
#include "parse-options.h"
4+
#include "serve.h"
5+
6+
static char const * const serve_usage[] = {
7+
N_("git serve [<options>]"),
8+
NULL
9+
};
10+
11+
int cmd_serve(int argc, const char **argv, const char *prefix)
12+
{
13+
struct serve_options opts = SERVE_OPTIONS_INIT;
14+
15+
struct option options[] = {
16+
OPT_BOOL(0, "stateless-rpc", &opts.stateless_rpc,
17+
N_("quit after a single request/response exchange")),
18+
OPT_BOOL(0, "advertise-capabilities", &opts.advertise_capabilities,
19+
N_("exit immediately after advertising capabilities")),
20+
OPT_END()
21+
};
22+
23+
/* ignore all unknown cmdline switches for now */
24+
argc = parse_options(argc, argv, prefix, options, serve_usage,
25+
PARSE_OPT_KEEP_DASHDASH |
26+
PARSE_OPT_KEEP_UNKNOWN);
27+
serve(&opts);
28+
29+
return 0;
30+
}

git.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ static struct cmd_struct commands[] = {
461461
{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
462462
{ "rm", cmd_rm, RUN_SETUP },
463463
{ "send-pack", cmd_send_pack, RUN_SETUP },
464+
{ "serve", cmd_serve, RUN_SETUP },
464465
{ "shortlog", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },
465466
{ "show", cmd_show, RUN_SETUP },
466467
{ "show-branch", cmd_show_branch, RUN_SETUP },

0 commit comments

Comments
 (0)