git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v4 12/35] serve: introduce git-serve

From
BWBrandon Williams <bmwill@google.com>
Date
Feb 28, 2018, 23:22 UTC
Message-ID
<20180228232252.102167-13-bmwill@google.com>
In-Reply-To
<20180228232252.102167-1-bmwill@google.com>
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>
---
 .gitignore                              |   1 +
 Documentation/technical/protocol-v2.txt | 171 ++++++++++++++++
 Makefile                                |   2 +
 builtin.h                               |   1 +
 builtin/serve.c                         |  30 +++
 git.c                                   |   1 +
 serve.c                                 | 250 ++++++++++++++++++++++++
 serve.h                                 |  15 ++
 t/t5701-git-serve.sh                    |  60 ++++++
 9 files changed, 531 insertions(+)
 create mode 100644 Documentation/technical/protocol-v2.txt
 create mode 100644 builtin/serve.c
 create mode 100644 serve.c
 create mode 100644 serve.h
 create mode 100755 t/t5701-git-serve.sh
diff --git a/.gitignore b/.gitignore
index 833ef3b0b..2d0450c26 100644
--- a/.gitignore
+++ b/.gitignore
@@ -140,6 +140,7 @@
 /git-rm
 /git-send-email
 /git-send-pack
+/git-serve
 /git-sh-i18n
 /git-sh-i18n--envsubst
 /git-sh-setup
diff --git a/Documentation/technical/protocol-v2.txt b/Documentation/technical/protocol-v2.txt
new file mode 100644
index 000000000..b02eefc21
--- /dev/null
+++ b/Documentation/technical/protocol-v2.txt
@@ -0,0 +1,171 @@
+ Git Wire Protocol, Version 2
+==============================
+
+This document presents a specification for a version 2 of Git's wire
+protocol.  Protocol v2 will improve upon v1 in the following ways:
+
+  * Instead of multiple service names, multiple commands will be
+    supported by a single service
+  * Easily extendable as capabilities are moved into their own section
+    of the protocol, no longer being hidden behind a NUL byte and
+    limited by the size of a pkt-line
+  * Separate out other information hidden behind NUL bytes (e.g. agent
+    string as a capability and symrefs can be requested using 'ls-refs')
+  * Reference advertisement will be omitted unless explicitly requested
+  * ls-refs command to explicitly request some refs
+  * Designed with http and stateless-rpc in mind.  With clear flush
+    semantics the http remote helper can simply act as a proxy
+
+ Detailed Design
+=================
+
+In protocol v2 communication is command oriented.  When first contacting a
+server a list of capabilities will advertised.  Some of these capabilities
+will be commands which a client can request be executed.  Once a command
+has completed, a client can reuse the connection and request that other
+commands be executed.
+
+ Packet-Line Framing
+---------------------
+
+All communication is done using packet-line framing, just as in v1.  See
+`Documentation/technical/pack-protocol.txt` and
+`Documentation/technical/protocol-common.txt` for more information.
+
+In protocol v2 these special packets will have the following semantics:
+
+  * '0000' Flush Packet (flush-pkt) - indicates the end of a message
+  * '0001' Delimiter Packet (delim-pkt) - separates sections of a message
+
+ Initial Client Request
+------------------------
+
+In general a client can request to speak protocol v2 by sending
+`version=2` through the respective side-channel for the transport being
+used which inevitably sets `GIT_PROTOCOL`.  More information can be
+found in `pack-protocol.txt` and `http-protocol.txt`.  In all cases the
+response from the server is the capability advertisement.
+
+ Git Transport
+~~~~~~~~~~~~~~~
+
+When using the git:// transport, you can request to use protocol v2 by
+sending "version=2" as an extra parameter:
+
+   003egit-upload-pack /project.git\0host=myserver.com\0\0version=2\0
+
+ SSH and File Transport
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+When using either the ssh:// or file:// transport, the GIT_PROTOCOL
+environment variable must be set explicitly to include "version=2".
+
+ HTTP Transport
+~~~~~~~~~~~~~~~~
+
+When using the http:// or https:// transport a client makes a "smart"
+info/refs request as described in `http-protocol.txt` and requests that
+v2 be used by supplying "version=2" in the `Git-Protocol` header.
+
+   C: Git-Protocol: version=2
+   C:
+   C: GET $GIT_URL/info/refs?service=git-upload-pack HTTP/1.0
+
+A v2 server would reply:
+
+   S: 200 OK
+   S: <Some headers>
+   S: ...
+   S:
+   S: 000eversion 2\n
+   S: <capability-advertisement>
+
+Subsequent requests are then made directly to the service
+`$GIT_URL/git-upload-pack`. (This works the same for git-receive-pack).
+
+ Capability Advertisement
+--------------------------
+
+A server which decides to communicate (based on a request from a client)
+using protocol version 2, notifies the client by sending a version string
+in its initial response followed by an advertisement of its capabilities.
+Each capability is a key with an optional value.  Clients must ignore all
+unknown keys.  Semantics of unknown values are left to the definition of
+each key.  Some capabilities will describe commands which can be requested
+to be executed by the client.
+
+    capability-advertisement = protocol-version
+			       capability-list
+			       flush-pkt
+
+    protocol-version = PKT-LINE("version 2" LF)
+    capability-list = *capability
+    capability = PKT-LINE(key[=value] LF)
+
+    key = 1*(ALPHA | DIGIT | "-_")
+    value = 1*(ALPHA | DIGIT | " -_.,?\/{}[]()<>!@#$%^&*+=:;")
+
+ Command Request
+-----------------
+
+After receiving the capability advertisement, a client can then issue a
+request to select the command it wants with any particular capabilities
+or arguments.  There is then an optional section where the client can
+provide any command specific parameters or queries.  Only a single
+command can be requested at a time.
+
+    request = empty-request | command-request
+    empty-request = flush-pkt
+    command-request = command
+		      capability-list
+		      (command-args)
+		      flush-pkt
+    command = PKT-LINE("command=" key LF)
+    command-args = delim-pkt
+		   *PKT-Line(arg LF)
+    arg = 1*(ALPHA | DIGIT | " -_.,?\/{}[]()<>!@#$%^&*+=:;")
+
+The server will then check to ensure that the client's request is
+comprised of a valid command as well as valid capabilities which were
+advertised.  If the request is valid the server will then execute the
+command.  A server MUST wait till it has received the client's entire
+request before issuing a response.  The format of the response is
+determined by the command being executed, but in all cases a flush-pkt
+indicates the end of the response.
+
+When a command has finished, and the client has received the entire
+response from the server, a client can either request that another
+command be executed or can terminate the connection.  A client may
+optionally send an empty request consisting of just a flush-pkt to
+indicate that no more requests will be made.
+
+ Capabilities
+~~~~~~~~~~~~~~
+
+There are two different types of capabilities: normal capabilities,
+which can be used to to convey information or alter the behavior of a
+request, and commands, which are the core actions that a client wants to
+perform (fetch, push, etc).
+
+All commands must only last a single round and be stateless from the
+perspective of the server side.  All state MUST be retained and managed
+by the client process.  This permits simple round-robin load-balancing
+on the server side, without needing to worry about state management.
+
+Clients MUST NOT require state management on the server side in order to
+function correctly.
+
+ agent
+-------
+
+The server can advertise the `agent` capability with a value `X` (in the
+form `agent=X`) to notify the client that the server is running version
+`X`.  The client may optionally send its own agent string by including
+the `agent` capability with a value `Y` (in the form `agent=Y`) in its
+request to the server (but it MUST NOT do so if the server did not
+advertise the agent capability). The `X` and `Y` strings may contain any
+printable ASCII characters except space (i.e., the byte range 32 < x <
+127), and are typically of the form "package/version" (e.g.,
+"git/1.8.3.1"). The agent strings are purely informative for statistics
+and debugging purposes, and MUST NOT be used to programmatically assume
+the presence or absence of particular features.
diff --git a/Makefile b/Makefile
index 3b849c060..18c255428 100644
--- a/Makefile
+++ b/Makefile
@@ -881,6 +881,7 @@ LIB_OBJS += revision.o
 LIB_OBJS += run-command.o
 LIB_OBJS += send-pack.o
 LIB_OBJS += sequencer.o
+LIB_OBJS += serve.o
 LIB_OBJS += server-info.o
 LIB_OBJS += setup.o
 LIB_OBJS += sha1-array.o
@@ -1014,6 +1015,7 @@ BUILTIN_OBJS += builtin/rev-parse.o
 BUILTIN_OBJS += builtin/revert.o
 BUILTIN_OBJS += builtin/rm.o
 BUILTIN_OBJS += builtin/send-pack.o
+BUILTIN_OBJS += builtin/serve.o
 BUILTIN_OBJS += builtin/shortlog.o
 BUILTIN_OBJS += builtin/show-branch.o
 BUILTIN_OBJS += builtin/show-ref.o
diff --git a/builtin.h b/builtin.h
index f332a1257..3f3fdfc28 100644
--- a/builtin.h
+++ b/builtin.h
@@ -215,6 +215,7 @@ extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
 extern int cmd_revert(int argc, const char **argv, const char *prefix);
 extern int cmd_rm(int argc, const char **argv, const char *prefix);
 extern int cmd_send_pack(int argc, const char **argv, const char *prefix);
+extern int cmd_serve(int argc, const char **argv, const char *prefix);
 extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
 extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
diff --git a/builtin/serve.c b/builtin/serve.c
new file mode 100644
index 000000000..d3fd240bb
--- /dev/null
+++ b/builtin/serve.c
@@ -0,0 +1,30 @@
+#include "cache.h"
+#include "builtin.h"
+#include "parse-options.h"
+#include "serve.h"
+
+static char const * const serve_usage[] = {
+	N_("git serve [<options>]"),
+	NULL
+};
+
+int cmd_serve(int argc, const char **argv, const char *prefix)
+{
+	struct serve_options opts = SERVE_OPTIONS_INIT;
+
+	struct option options[] = {
+		OPT_BOOL(0, "stateless-rpc", &opts.stateless_rpc,
+			 N_("quit after a single request/response exchange")),
+		OPT_BOOL(0, "advertise-capabilities", &opts.advertise_capabilities,
+			 N_("exit immediately after advertising capabilities")),
+		OPT_END()
+	};
+
+	/* ignore all unknown cmdline switches for now */
+	argc = parse_options(argc, argv, prefix, options, serve_usage,
+			     PARSE_OPT_KEEP_DASHDASH |
+			     PARSE_OPT_KEEP_UNKNOWN);
+	serve(&opts);
+
+	return 0;
+}
diff --git a/git.c b/git.c
index f71073dc8..f85d682b6 100644
--- a/git.c
+++ b/git.c
@@ -461,6 +461,7 @@ static struct cmd_struct commands[] = {
 	{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
 	{ "rm", cmd_rm, RUN_SETUP },
 	{ "send-pack", cmd_send_pack, RUN_SETUP },
+	{ "serve", cmd_serve, RUN_SETUP },
 	{ "shortlog", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },
 	{ "show", cmd_show, RUN_SETUP },
 	{ "show-branch", cmd_show_branch, RUN_SETUP },
diff --git a/serve.c b/serve.c
new file mode 100644
index 000000000..cf23179b9
--- /dev/null
+++ b/serve.c
@@ -0,0 +1,250 @@
+#include "cache.h"
+#include "repository.h"
+#include "config.h"
+#include "pkt-line.h"
+#include "version.h"
+#include "argv-array.h"
+#include "serve.h"
+
+static int agent_advertise(struct repository *r,
+			   struct strbuf *value)
+{
+	if (value)
+		strbuf_addstr(value, git_user_agent_sanitized());
+	return 1;
+}
+
+struct protocol_capability {
+	/*
+	 * The name of the capability.  The server uses this name when
+	 * advertising this capability, and the client uses this name to
+	 * specify this capability.
+	 */
+	const char *name;
+
+	/*
+	 * Function queried to see if a capability should be advertised.
+	 * Optionally a value can be specified by adding it to 'value'.
+	 * If a value is added to 'value', the server will advertise this
+	 * capability as "<name>=<value>" instead of "<name>".
+	 */
+	int (*advertise)(struct repository *r, struct strbuf *value);
+
+	/*
+	 * Function called when a client requests the capability as a command.
+	 * The command request will be provided to the function via 'keys', the
+	 * capabilities requested, and 'args', the command specific parameters.
+	 *
+	 * This field should be NULL for capabilities which are not commands.
+	 */
+	int (*command)(struct repository *r,
+		       struct argv_array *keys,
+		       struct argv_array *args);
+};
+
+static struct protocol_capability capabilities[] = {
+	{ "agent", agent_advertise, NULL },
+};
+
+static void advertise_capabilities(void)
+{
+	struct strbuf capability = STRBUF_INIT;
+	struct strbuf value = STRBUF_INIT;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
+		struct protocol_capability *c = &capabilities[i];
+
+		if (c->advertise(the_repository, &value)) {
+			strbuf_addstr(&capability, c->name);
+
+			if (value.len) {
+				strbuf_addch(&capability, '=');
+				strbuf_addbuf(&capability, &value);
+			}
+
+			strbuf_addch(&capability, '\n');
+			packet_write(1, capability.buf, capability.len);
+		}
+
+		strbuf_reset(&capability);
+		strbuf_reset(&value);
+	}
+
+	packet_flush(1);
+	strbuf_release(&capability);
+	strbuf_release(&value);
+}
+
+static struct protocol_capability *get_capability(const char *key)
+{
+	int i;
+
+	if (!key)
+		return NULL;
+
+	for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
+		struct protocol_capability *c = &capabilities[i];
+		const char *out;
+		if (skip_prefix(key, c->name, &out) && (!*out || *out == '='))
+			return c;
+	}
+
+	return NULL;
+}
+
+static int is_valid_capability(const char *key)
+{
+	const struct protocol_capability *c = get_capability(key);
+
+	return c && c->advertise(the_repository, NULL);
+}
+
+static int is_command(const char *key, struct protocol_capability **command)
+{
+	const char *out;
+
+	if (skip_prefix(key, "command=", &out)) {
+		struct protocol_capability *cmd = get_capability(out);
+
+		if (!cmd || !cmd->advertise(the_repository, NULL) || !cmd->command)
+			die("invalid command '%s'", out);
+		if (*command)
+			die("command already requested");
+
+		*command = cmd;
+		return 1;
+	}
+
+	return 0;
+}
+
+int has_capability(const struct argv_array *keys, const char *capability,
+		   const char **value)
+{
+	int i;
+	for (i = 0; i < keys->argc; i++) {
+		const char *out;
+		if (skip_prefix(keys->argv[i], capability, &out) &&
+		    (!*out || *out == '=')) {
+			if (value) {
+				if (*out == '=')
+					out++;
+				*value = out;
+			}
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+enum request_state {
+	PROCESS_REQUEST_KEYS = 0,
+	PROCESS_REQUEST_ARGS,
+	PROCESS_REQUEST_DONE,
+};
+
+static int process_request(void)
+{
+	enum request_state state = PROCESS_REQUEST_KEYS;
+	struct packet_reader reader;
+	struct argv_array keys = ARGV_ARRAY_INIT;
+	struct argv_array args = ARGV_ARRAY_INIT;
+	struct protocol_capability *command = NULL;
+
+	packet_reader_init(&reader, 0, NULL, 0,
+			   PACKET_READ_CHOMP_NEWLINE |
+			   PACKET_READ_GENTLE_ON_EOF);
+
+	/*
+	 * Check to see if the client closed their end before sending another
+	 * request.  If so we can terminate the connection.
+	 */
+	if (packet_reader_peek(&reader) == PACKET_READ_EOF)
+		return 1;
+	reader.options = PACKET_READ_CHOMP_NEWLINE;
+
+	while (state != PROCESS_REQUEST_DONE) {
+		switch (packet_reader_read(&reader)) {
+		case PACKET_READ_EOF:
+			BUG("Should have already died when seeing EOF");
+		case PACKET_READ_NORMAL:
+			break;
+		case PACKET_READ_FLUSH:
+			state = PROCESS_REQUEST_DONE;
+			continue;
+		case PACKET_READ_DELIM:
+			if (state != PROCESS_REQUEST_KEYS)
+				die("protocol error");
+			state = PROCESS_REQUEST_ARGS;
+			/*
+			 * maybe include a check to make sure that a
+			 * command/capabilities were given.
+			 */
+			continue;
+		}
+
+		switch (state) {
+		case PROCESS_REQUEST_KEYS:
+			/* collect request; a sequence of keys and values */
+			if (is_command(reader.line, &command) ||
+			    is_valid_capability(reader.line))
+				argv_array_push(&keys, reader.line);
+			else
+				die("unknown capability '%s'", reader.line);
+			break;
+		case PROCESS_REQUEST_ARGS:
+			/* collect arguments for the requested command */
+			argv_array_push(&args, reader.line);
+			break;
+		case PROCESS_REQUEST_DONE:
+			continue;
+		}
+	}
+
+	/*
+	 * If no command and no keys were given then the client wanted to
+	 * terminate the connection.
+	 */
+	if (!keys.argc && !args.argc)
+		return 1;
+
+	if (!command)
+		die("no command requested");
+
+	command->command(the_repository, &keys, &args);
+
+	argv_array_clear(&keys);
+	argv_array_clear(&args);
+	return 0;
+}
+
+/* Main serve loop for protocol version 2 */
+void serve(struct serve_options *options)
+{
+	if (options->advertise_capabilities || !options->stateless_rpc) {
+		/* serve by default supports v2 */
+		packet_write_fmt(1, "version 2\n");
+
+		advertise_capabilities();
+		/*
+		 * If only the list of capabilities was requested exit
+		 * immediately after advertising capabilities
+		 */
+		if (options->advertise_capabilities)
+			return;
+	}
+
+	/*
+	 * If stateless-rpc was requested then exit after
+	 * a single request/response exchange
+	 */
+	if (options->stateless_rpc) {
+		process_request();
+	} else {
+		for (;;)
+			if (process_request())
+				break;
+	}
+}
diff --git a/serve.h b/serve.h
new file mode 100644
index 000000000..fe65ba9f4
--- /dev/null
+++ b/serve.h
@@ -0,0 +1,15 @@
+#ifndef SERVE_H
+#define SERVE_H
+
+struct argv_array;
+extern int has_capability(const struct argv_array *keys, const char *capability,
+			  const char **value);
+
+struct serve_options {
+	unsigned advertise_capabilities;
+	unsigned stateless_rpc;
+};
+#define SERVE_OPTIONS_INIT { 0 }
+extern void serve(struct serve_options *options);
+
+#endif /* SERVE_H */
diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh
new file mode 100755
index 000000000..affbad097
--- /dev/null
+++ b/t/t5701-git-serve.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='test git-serve and server commands'
+
+. ./test-lib.sh
+
+test_expect_success 'test capability advertisement' '
+	cat >expect <<-EOF &&
+	version 2
+	agent=git/$(git version | cut -d" " -f3)
+	0000
+	EOF
+
+	git serve --advertise-capabilities >out &&
+	test-pkt-line unpack <out >actual &&
+	test_cmp actual expect
+'
+
+test_expect_success 'stateless-rpc flag does not list capabilities' '
+	# Empty request
+	test-pkt-line pack >in <<-EOF &&
+	0000
+	EOF
+	git serve --stateless-rpc >out <in &&
+	test_must_be_empty out &&
+
+	# EOF
+	git serve --stateless-rpc >out &&
+	test_must_be_empty out
+'
+
+test_expect_success 'request invalid capability' '
+	test-pkt-line pack >in <<-EOF &&
+	foobar
+	0000
+	EOF
+	test_must_fail git serve --stateless-rpc 2>err <in &&
+	test_i18ngrep "unknown capability" err
+'
+
+test_expect_success 'request with no command' '
+	test-pkt-line pack >in <<-EOF &&
+	agent=git/test
+	0000
+	EOF
+	test_must_fail git serve --stateless-rpc 2>err <in &&
+	test_i18ngrep "no command requested" err
+'
+
+test_expect_success 'request invalid command' '
+	test-pkt-line pack >in <<-EOF &&
+	command=foo
+	agent=git/test
+	0000
+	EOF
+	test_must_fail git serve --stateless-rpc 2>err <in &&
+	test_i18ngrep "invalid command" err
+'
+
+test_done
-- 
2.16.2.395.g2e18187dfd-goog
Previous: Brandon WilliamsNext: Junio C Hamano
Message 306 of 362 in “protocol version 2”
  1. 00/26 protocol version 2Brandon Williams, Jan 3, 2018
  2. 01/26 pkt-line: introduce packet_read_with_statusBrandon Williams, Jan 3, 2018
  3. Stefan BellerJan 3, 2018
  4. Brandon WilliamsJan 5, 2018
  5. Jonathan TanJan 9, 2018
  6. Brandon WilliamsJan 9, 2018
  7. 02/26 pkt-line: introduce struct packet_readerBrandon Williams, Jan 3, 2018
  8. Jonathan TanJan 9, 2018
  9. Brandon WilliamsJan 9, 2018
  10. 05/26 upload-pack: factor out processing linesBrandon Williams, Jan 3, 2018
  11. Stefan BellerJan 3, 2018
  12. 07/26 connect: convert get_remote_heads to use struct packet_readerBrandon Williams, Jan 3, 2018
  13. Jonathan TanJan 9, 2018
  14. Brandon WilliamsJan 9, 2018
  15. 08/26 connect: discover protocol version outside of get_remote_headsBrandon Williams, Jan 3, 2018
  16. 03/26 pkt-line: add delim packet supportBrandon Williams, Jan 3, 2018
  17. 13/26 connect: request remote refs using v2Brandon Williams, Jan 3, 2018
  18. Jonathan TanJan 9, 2018
  19. 04/26 upload-pack: convert to a builtinBrandon Williams, Jan 3, 2018
  20. Stefan BellerJan 3, 2018
  21. Brandon WilliamsJan 3, 2018
  22. Jonathan NiederFeb 21, 2018
  23. Junio C HamanoFeb 21, 2018
  24. 16/26 ls-remote: pass ref patterns when requesting a remote's refsBrandon Williams, Jan 3, 2018
  25. 14/26 transport: convert get_refs_list to take a list of ref patternsBrandon Williams, Jan 3, 2018
  26. 18/26 push: pass ref patterns when pushingBrandon Williams, Jan 3, 2018
  27. 12/26 ls-refs: introduce ls-refs server commandBrandon Williams, Jan 3, 2018
  28. Stefan BellerJan 4, 2018
  29. Brandon WilliamsJan 5, 2018
  30. Jonathan TanJan 9, 2018
  31. Brandon WilliamsJan 16, 2018
  32. Jeff HostetlerFeb 1, 2018
  33. Brandon WilliamsFeb 7, 2018
  34. 25/26 remote-curl: create copy of the service nameBrandon Williams, Jan 3, 2018
  35. 26/26 remote-curl: implement connect-half-duplex commandBrandon Williams, Jan 3, 2018
  36. Jonathan TanJan 10, 2018
  37. Jonathan TanJan 10, 2018
  38. Brandon WilliamsJan 11, 2018
  39. 22/26 transport-helper: refactor process_connect_serviceBrandon Williams, Jan 3, 2018
  40. 20/26 fetch-pack: perform a fetch using v2Brandon Williams, Jan 3, 2018
  41. Stefan BellerJan 4, 2018
  42. Brandon WilliamsJan 5, 2018
  43. Jonathan TanJan 10, 2018
  44. 21/26 transport-helper: remove name parameterBrandon Williams, Jan 3, 2018
  45. 23/26 transport-helper: introduce connect-half-duplexBrandon Williams, Jan 3, 2018
  46. 19/26 upload-pack: introduce fetch server commandBrandon Williams, Jan 3, 2018
  47. Stefan BellerJan 4, 2018
  48. 24/26 pkt-line: add packet_buf_write_len functionBrandon Williams, Jan 3, 2018
  49. 15/26 transport: convert transport_get_remote_refs to take a list of ref patternsBrandon Williams, Jan 3, 2018
  50. 17/26 fetch: pass ref patterns when fetchingBrandon Williams, Jan 3, 2018
  51. 06/26 transport: use get_refs_via_connect to get refsBrandon Williams, Jan 3, 2018
  52. Stefan BellerJan 3, 2018
  53. 11/26 serve: introduce git-serveBrandon Williams, Jan 3, 2018
  54. Jonathan TanJan 9, 2018
  55. Brandon WilliamsJan 9, 2018
  56. Jonathan TanJan 9, 2018
  57. Brandon WilliamsJan 9, 2018
  58. Jeff HostetlerFeb 1, 2018
  59. Stefan BellerFeb 1, 2018
  60. Jeff HostetlerFeb 1, 2018
  61. Brandon WilliamsFeb 1, 2018
  62. Randall S. BeckerFeb 1, 2018
  63. 'Brandon Williams'Feb 1, 2018
  64. Randall S. BeckerFeb 1, 2018
  65. Stefan BellerFeb 1, 2018
  66. 09/26 transport: store protocol versionBrandon Williams, Jan 3, 2018
  67. Jonathan TanJan 9, 2018
  68. Brandon WilliamsJan 9, 2018
  69. 10/26 protocol: introduce enum protocol_version value protocol_v2Brandon Williams, Jan 3, 2018
  70. Jonathan TanJan 9, 2018
  71. Brandon WilliamsJan 11, 2018
  72. 00/27 protocol version 2Brandon Williams, Jan 25, 2018
  73. 01/27 pkt-line: introduce packet_read_with_statusBrandon Williams, Jan 25, 2018
  74. 02/27 pkt-line: introduce struct packet_readerBrandon Williams, Jan 25, 2018
  75. 03/27 pkt-line: add delim packet supportBrandon Williams, Jan 25, 2018
  76. 04/27 upload-pack: convert to a builtinBrandon Williams, Jan 25, 2018
  77. 06/27 transport: use get_refs_via_connect to get refsBrandon Williams, Jan 25, 2018
  78. 07/27 connect: convert get_remote_heads to use struct packet_readerBrandon Williams, Jan 25, 2018
  79. 08/27 connect: discover protocol version outside of get_remote_headsBrandon Williams, Jan 25, 2018
  80. Derrick StoleeJan 31, 2018
  81. Brandon WilliamsFeb 1, 2018
  82. 09/27 transport: store protocol versionBrandon Williams, Jan 25, 2018
  83. Derrick StoleeJan 31, 2018
  84. 10/27 protocol: introduce enum protocol_version value protocol_v2Brandon Williams, Jan 25, 2018
  85. Derrick StoleeJan 31, 2018
  86. Brandon WilliamsFeb 2, 2018
  87. Derrick StoleeFeb 5, 2018
  88. 12/27 serve: introduce git-serveBrandon Williams, Jan 25, 2018
  89. Duy NguyenJan 26, 2018
  90. Jonathan NiederFeb 27, 2018
  91. Derrick StoleeJan 31, 2018
  92. 14/27 connect: request remote refs using v2Brandon Williams, Jan 25, 2018
  93. Derrick StoleeJan 31, 2018
  94. Eric SunshineJan 31, 2018
  95. Derrick StoleeJan 31, 2018
  96. 16/27 transport: convert transport_get_remote_refs to take a list of ref patternsBrandon Williams, Jan 25, 2018
  97. 17/27 ls-remote: pass ref patterns when requesting a remote's refsBrandon Williams, Jan 25, 2018
  98. 18/27 fetch: pass ref patterns when fetchingBrandon Williams, Jan 25, 2018
  99. 19/27 push: pass ref patterns when pushingBrandon Williams, Jan 25, 2018
  100. 13/27 ls-refs: introduce ls-refs server commandBrandon Williams, Jan 25, 2018
  101. Stefan BellerJan 26, 2018
  102. Brandon WilliamsFeb 2, 2018
  103. 22/27 transport-helper: remove name parameterBrandon Williams, Jan 25, 2018
  104. 23/27 transport-helper: refactor process_connect_serviceBrandon Williams, Jan 25, 2018
  105. 15/27 transport: convert get_refs_list to take a list of ref patternsBrandon Williams, Jan 25, 2018
  106. 24/27 transport-helper: introduce stateless-connectBrandon Williams, Jan 25, 2018
  107. 26/27 remote-curl: create copy of the service nameBrandon Williams, Jan 25, 2018
  108. 27/27 remote-curl: implement stateless-connect commandBrandon Williams, Jan 25, 2018
  109. 25/27 pkt-line: add packet_buf_write_len functionBrandon Williams, Jan 25, 2018
  110. 20/27 upload-pack: introduce fetch server commandBrandon Williams, Jan 25, 2018
  111. 21/27 fetch-pack: perform a fetch using v2Brandon Williams, Jan 25, 2018
  112. 11/27 test-pkt-line: introduce a packet-line test helperBrandon Williams, Jan 25, 2018
  113. 05/27 upload-pack: factor out processing linesBrandon Williams, Jan 25, 2018
  114. Stefan BellerJan 26, 2018
  115. Brandon WilliamsJan 26, 2018
  116. Derrick StoleeJan 31, 2018
  117. Derrick StoleeJan 31, 2018
  118. Brandon WilliamsFeb 7, 2018
  119. Jeff HostetlerFeb 1, 2018
  120. 00/35 protocol version 2Brandon Williams, Feb 7, 2018
  121. 01/35 pkt-line: introduce packet_read_with_statusBrandon Williams, Feb 7, 2018
  122. Jonathan NiederFeb 13, 2018
  123. 02/35 pkt-line: introduce struct packet_readerBrandon Williams, Feb 7, 2018
  124. Jonathan NiederFeb 13, 2018
  125. Brandon WilliamsFeb 27, 2018
  126. Jonathan NiederFeb 27, 2018
  127. Jonathan NiederFeb 27, 2018
  128. Jonathan NiederFeb 27, 2018
  129. 04/35 upload-pack: convert to a builtinBrandon Williams, Feb 7, 2018
  130. Jonathan TanFeb 21, 2018
  131. Jeff KingFeb 22, 2018
  132. Brandon WilliamsFeb 22, 2018
  133. Jeff KingFeb 22, 2018
  134. Jonathan NiederFeb 22, 2018
  135. Jeff KingFeb 22, 2018
  136. Jeff KingFeb 22, 2018
  137. Jonathan NiederFeb 22, 2018
  138. Jeff KingFeb 22, 2018
  139. Jonathan NiederMar 12, 2018
  140. Jeff KingMar 12, 2018
  141. Jonathan NiederMar 12, 2018
  142. Jeff KingMar 12, 2018
  143. Brandon WilliamsFeb 23, 2018
  144. Jeff KingMar 3, 2018
  145. Jonathan NiederFeb 22, 2018
  146. Jeff KingFeb 22, 2018
  147. Jeff KingFeb 22, 2018
  148. Jonathan NiederFeb 22, 2018
  149. Jeff KingFeb 22, 2018
  150. Jeff KingFeb 22, 2018
  151. 03/35 pkt-line: add delim packet supportBrandon Williams, Feb 7, 2018
  152. Stefan BellerFeb 22, 2018
  153. Brandon WilliamsFeb 22, 2018
  154. 05/35 upload-pack: factor out processing linesBrandon Williams, Feb 7, 2018
  155. Stefan BellerFeb 22, 2018
  156. Brandon WilliamsFeb 22, 2018
  157. 06/35 transport: use get_refs_via_connect to get refsBrandon Williams, Feb 7, 2018
  158. Jonathan NiederFeb 27, 2018
  159. Brandon WilliamsFeb 27, 2018
  160. Jonathan NiederFeb 27, 2018
  161. Brandon WilliamsFeb 27, 2018
  162. 08/35 connect: discover protocol version outside of get_remote_headsBrandon Williams, Feb 7, 2018
  163. Jonathan TanFeb 21, 2018
  164. Brandon WilliamsFeb 22, 2018
  165. Jonathan TanFeb 22, 2018
  166. 09/35 transport: store protocol versionBrandon Williams, Feb 7, 2018
  167. 10/35 protocol: introduce enum protocol_version value protocol_v2Brandon Williams, Feb 7, 2018
  168. Jonathan NiederFeb 27, 2018
  169. Brandon WilliamsFeb 27, 2018
  170. 11/35 test-pkt-line: introduce a packet-line test helperBrandon Williams, Feb 7, 2018
  171. Stefan BellerFeb 22, 2018
  172. Brandon WilliamsFeb 23, 2018
  173. Jeff KingMar 3, 2018
  174. Brandon WilliamsMar 5, 2018
  175. 12/35 serve: introduce git-serveBrandon Williams, Feb 7, 2018
  176. Jonathan TanFeb 21, 2018
  177. Brandon WilliamsFeb 23, 2018
  178. Jonathan TanFeb 27, 2018
  179. Brandon WilliamsFeb 27, 2018
  180. Jeff KingFeb 22, 2018
  181. Brandon WilliamsFeb 23, 2018
  182. Jeff KingMar 3, 2018
  183. Brandon WilliamsMar 5, 2018
  184. Jeff KingMar 5, 2018
  185. Jonathan NiederMar 5, 2018
  186. Jeff KingMar 6, 2018
  187. Jeff KingMar 12, 2018
  188. 13/35 ls-refs: introduce ls-refs server commandBrandon Williams, Feb 7, 2018
  189. Jeff KingFeb 22, 2018
  190. Brandon WilliamsFeb 23, 2018
  191. Brandon WilliamsFeb 24, 2018
  192. Jeff KingFeb 24, 2018
  193. Jeff KingFeb 24, 2018
  194. Junio C HamanoFeb 26, 2018
  195. Ævar Arnfjörð BjarmasonFeb 27, 2018
  196. Jonathan NiederFeb 27, 2018
  197. Brandon WilliamsFeb 27, 2018
  198. 17/35 ls-remote: pass ref patterns when requesting a remote's refsBrandon Williams, Feb 7, 2018
  199. 18/35 fetch: pass ref patterns when fetchingBrandon Williams, Feb 7, 2018
  200. Jonathan NiederFeb 27, 2018
  201. 14/35 connect: request remote refs using v2Brandon Williams, Feb 7, 2018
  202. Jonathan TanFeb 21, 2018
  203. Brandon WilliamsFeb 22, 2018
  204. Jeff KingFeb 22, 2018
  205. Jonathan TanFeb 22, 2018
  206. Jonathan NiederFeb 27, 2018
  207. Junio C HamanoFeb 27, 2018
  208. Jeff KingFeb 27, 2018
  209. Eric SunshineFeb 27, 2018
  210. Jeff KingFeb 27, 2018
  211. Junio C HamanoFeb 27, 2018
  212. Jonathan NiederFeb 27, 2018
  213. Brandon WilliamsFeb 27, 2018
  214. 16/35 transport: convert transport_get_remote_refs to take a list of ref patternsBrandon Williams, Feb 7, 2018
  215. Jonathan TanFeb 21, 2018
  216. Brandon WilliamsFeb 22, 2018
  217. Jonathan TanFeb 22, 2018
  218. Brandon WilliamsFeb 22, 2018
  219. 21/35 fetch-pack: perform a fetch using v2Brandon Williams, Feb 7, 2018
  220. Jonathan TanFeb 24, 2018
  221. Brandon WilliamsFeb 26, 2018
  222. Stefan BellerFeb 27, 2018
  223. Brandon WilliamsFeb 27, 2018
  224. 22/35 upload-pack: support shallow requestsBrandon Williams, Feb 7, 2018
  225. Stefan BellerFeb 7, 2018
  226. Duy NguyenFeb 10, 2018
  227. Brandon WilliamsFeb 13, 2018
  228. Jonathan NiederFeb 27, 2018
  229. Brandon WilliamsFeb 27, 2018
  230. 19/35 push: pass ref patterns when pushingBrandon Williams, Feb 7, 2018
  231. Stefan BellerFeb 27, 2018
  232. 23/35 fetch-pack: support shallow requestsBrandon Williams, Feb 7, 2018
  233. Jonathan TanFeb 23, 2018
  234. Brandon WilliamsFeb 23, 2018
  235. 27/35 transport-helper: refactor process_connect_serviceBrandon Williams, Feb 7, 2018
  236. 28/35 transport-helper: introduce stateless-connectBrandon Williams, Feb 7, 2018
  237. Jonathan TanFeb 22, 2018
  238. Brandon WilliamsFeb 22, 2018
  239. Jonathan TanFeb 22, 2018
  240. Jonathan NiederFeb 27, 2018
  241. Brandon WilliamsFeb 28, 2018
  242. 29/35 pkt-line: add packet_buf_write_len functionBrandon Williams, Feb 7, 2018
  243. Jonathan NiederFeb 27, 2018
  244. Brandon WilliamsFeb 28, 2018
  245. 30/35 remote-curl: create copy of the service nameBrandon Williams, Feb 7, 2018
  246. Jonathan TanFeb 22, 2018
  247. Brandon WilliamsFeb 22, 2018
  248. 32/35 http: allow providing extra headers for http requestsBrandon Williams, Feb 7, 2018
  249. Jonathan TanFeb 22, 2018
  250. Brandon WilliamsFeb 22, 2018
  251. 33/35 http: don't always add Git-Protocol headerBrandon Williams, Feb 7, 2018
  252. 34/35 remote-curl: implement stateless-connect commandBrandon Williams, Feb 7, 2018
  253. Jonathan NiederFeb 28, 2018
  254. Brandon WilliamsFeb 28, 2018
  255. 24/35 connect: refactor git_connect to only get the protocol version onceBrandon Williams, Feb 7, 2018
  256. Jonathan TanFeb 21, 2018
  257. 35/35 remote-curl: don't request v2 when pushingBrandon Williams, Feb 7, 2018
  258. Jonathan TanFeb 22, 2018
  259. Brandon WilliamsFeb 22, 2018
  260. Brandon WilliamsFeb 22, 2018
  261. 31/35 remote-curl: store the protocol version the server responded withBrandon Williams, Feb 7, 2018
  262. Jonathan NiederFeb 27, 2018
  263. 25/35 connect: don't request v2 when pushingBrandon Williams, Feb 7, 2018
  264. 26/35 transport-helper: remove name parameterBrandon Williams, Feb 7, 2018
  265. Jonathan NiederFeb 27, 2018
  266. 15/35 transport: convert get_refs_list to take a list of ref patternsBrandon Williams, Feb 7, 2018
  267. Jonathan TanFeb 21, 2018
  268. Brandon WilliamsFeb 22, 2018
  269. 20/35 upload-pack: introduce fetch server commandBrandon Williams, Feb 7, 2018
  270. Jonathan TanFeb 21, 2018
  271. Brandon WilliamsFeb 22, 2018
  272. 07/35 connect: convert get_remote_heads to use struct packet_readerBrandon Williams, Feb 7, 2018
  273. Stefan BellerFeb 22, 2018
  274. Stefan BellerFeb 22, 2018
  275. Brandon WilliamsFeb 23, 2018
  276. Stefan BellerFeb 23, 2018
  277. Brandon WilliamsFeb 23, 2018
  278. Derrick StoleeFeb 12, 2018
  279. Brandon WilliamsFeb 21, 2018
  280. 00/35 protocol version 2Brandon Williams, Feb 28, 2018
  281. 01/35 pkt-line: introduce packet_read_with_statusBrandon Williams, Feb 28, 2018
  282. Jonathan TanMar 13, 2018
  283. Brandon WilliamsMar 13, 2018
  284. 02/35 pkt-line: allow peeking a packet line without consuming itBrandon Williams, Feb 28, 2018
  285. Junio C HamanoMar 1, 2018
  286. Brandon WilliamsMar 12, 2018
  287. 04/35 upload-pack: convert to a builtinBrandon Williams, Feb 28, 2018
  288. Jonathan TanMar 13, 2018
  289. Brandon WilliamsMar 13, 2018
  290. 03/35 pkt-line: add delim packet supportBrandon Williams, Feb 28, 2018
  291. Junio C HamanoMar 1, 2018
  292. Junio C HamanoMar 1, 2018
  293. Brandon WilliamsMar 1, 2018
  294. Junio C HamanoMar 1, 2018
  295. 05/35 upload-pack: factor out processing linesBrandon Williams, Feb 28, 2018
  296. Junio C HamanoMar 1, 2018
  297. Brandon WilliamsMar 12, 2018
  298. Brandon WilliamsMar 12, 2018
  299. 06/35 transport: use get_refs_via_connect to get refsBrandon Williams, Feb 28, 2018
  300. Junio C HamanoMar 1, 2018
  301. 07/35 connect: convert get_remote_heads to use struct packet_readerBrandon Williams, Feb 28, 2018
  302. 08/35 connect: discover protocol version outside of get_remote_headsBrandon Williams, Feb 28, 2018
  303. Jonathan TanMar 13, 2018
  304. 09/35 transport: store protocol versionBrandon Williams, Feb 28, 2018
  305. 11/35 test-pkt-line: introduce a packet-line test helperBrandon Williams, Feb 28, 2018
  306. 12/35 serve: introduce git-serveBrandon Williams, Feb 28, 2018
  307. Junio C HamanoMar 1, 2018
  308. Brandon WilliamsMar 12, 2018
  309. Junio C HamanoMar 2, 2018
  310. Brandon WilliamsMar 13, 2018
  311. Junio C HamanoMar 2, 2018
  312. Brandon WilliamsMar 13, 2018
  313. 10/35 protocol: introduce enum protocol_version value protocol_v2Brandon Williams, Feb 28, 2018
  314. 14/35 connect: request remote refs using v2Brandon Williams, Feb 28, 2018
  315. 15/35 transport: convert get_refs_list to take a list of ref patternsBrandon Williams, Feb 28, 2018
  316. 13/35 ls-refs: introduce ls-refs server commandBrandon Williams, Feb 28, 2018
  317. Junio C HamanoMar 2, 2018
  318. Brandon WilliamsMar 13, 2018
  319. Jeff KingMar 3, 2018
  320. Brandon WilliamsMar 5, 2018
  321. Jonathan NiederMar 5, 2018
  322. Jeff KingMar 5, 2018
  323. Jeff KingMar 5, 2018
  324. Brandon WilliamsMar 13, 2018
  325. 19/35 push: pass ref patterns when pushingBrandon Williams, Feb 28, 2018
  326. Junio C HamanoMar 2, 2018
  327. Brandon WilliamsMar 12, 2018
  328. 20/35 upload-pack: introduce fetch server commandBrandon Williams, Feb 28, 2018
  329. Jonathan TanMar 13, 2018
  330. Brandon WilliamsMar 13, 2018
  331. 21/35 fetch-pack: perform a fetch using v2Brandon Williams, Feb 28, 2018
  332. 22/35 fetch-pack: support shallow requestsBrandon Williams, Feb 28, 2018
  333. 23/35 connect: refactor git_connect to only get the protocol version onceBrandon Williams, Feb 28, 2018
  334. 24/35 connect: don't request v2 when pushingBrandon Williams, Feb 28, 2018
  335. 25/35 transport-helper: remove name parameterBrandon Williams, Feb 28, 2018
  336. 27/35 transport-helper: introduce stateless-connectBrandon Williams, Feb 28, 2018
  337. Jonathan TanMar 13, 2018
  338. Brandon WilliamsMar 14, 2018
  339. 29/35 remote-curl: create copy of the service nameBrandon Williams, Feb 28, 2018
  340. Jonathan TanMar 13, 2018
  341. 28/35 pkt-line: add packet_buf_write_len functionBrandon Williams, Feb 28, 2018
  342. 31/35 http: allow providing extra headers for http requestsBrandon Williams, Feb 28, 2018
  343. Jonathan TanMar 13, 2018
  344. 32/35 http: don't always add Git-Protocol headerBrandon Williams, Feb 28, 2018
  345. 33/35 http: eliminate "# service" line when using protocol v2Brandon Williams, Feb 28, 2018
  346. 35/35 remote-curl: don't request v2 when pushingBrandon Williams, Feb 28, 2018
  347. Jonathan TanMar 13, 2018
  348. 30/35 remote-curl: store the protocol version the server responded withBrandon Williams, Feb 28, 2018
  349. 34/35 remote-curl: implement stateless-connect commandBrandon Williams, Feb 28, 2018
  350. Johannes SchindelinMar 2, 2018
  351. Brandon WilliamsMar 5, 2018
  352. 26/35 transport-helper: refactor process_connect_serviceBrandon Williams, Feb 28, 2018
  353. 16/35 transport: convert transport_get_remote_refs to take a list of ref patternsBrandon Williams, Feb 28, 2018
  354. Jonathan TanMar 13, 2018
  355. 17/35 ls-remote: pass ref patterns when requesting a remote's refsBrandon Williams, Feb 28, 2018
  356. Junio C HamanoMar 2, 2018
  357. 18/35 fetch: pass ref patterns when fetchingBrandon Williams, Feb 28, 2018
  358. Junio C HamanoMar 2, 2018
  359. Brandon WilliamsMar 12, 2018
  360. Junio C HamanoMar 1, 2018
  361. Brandon WilliamsMar 1, 2018
  362. Junio C HamanoMar 1, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.