All of lore.kernel.org
 help / color / mirror / Atom feed
From: Josh Steadmon <steadmon@google.com>
To: git@vger.kernel.org
Cc: Josh Steadmon <steadmon@google.com>
Subject: [PATCH v2 3/4] archive: implement protocol v2 archive command
Date: Wed, 26 Sep 2018 18:24:54 -0700	[thread overview]
Message-ID: <20180927012455.234876-4-steadmon@google.com> (raw)
In-Reply-To: <20180927012455.234876-1-steadmon@google.com>

This adds a new archive command for protocol v2. The command expects
arguments in the form "argument X" which are passed unmodified to
git-upload-archive--writer.

This command works over the file://, Git, and SSH transports. HTTP
support will be added in a separate patch.

NEEDSWORK: this is not backwards-compatible with older clients that set
GIT_PROTOCOL=version=2 or configure protocol.version=2.

Signed-off-by: Josh Steadmon <steadmon@google.com>
---
 Documentation/technical/protocol-v2.txt | 21 +++++++++++-
 builtin/archive.c                       | 45 +++++++++++++++++--------
 builtin/upload-archive.c                | 27 +++++++++++++--
 serve.c                                 |  7 ++++
 t/t5000-tar-tree.sh                     |  7 ++++
 t/t5701-git-serve.sh                    |  1 +
 6 files changed, 90 insertions(+), 18 deletions(-)

diff --git a/Documentation/technical/protocol-v2.txt b/Documentation/technical/protocol-v2.txt
index 09e4e0273f..6126fc5738 100644
--- a/Documentation/technical/protocol-v2.txt
+++ b/Documentation/technical/protocol-v2.txt
@@ -77,7 +77,8 @@ A v2 server would reply:
    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).
+`$GIT_URL/git-upload-pack`. (This works the same for git-receive-pack or
+git-upload-archive).
 
  Capability Advertisement
 --------------------------
@@ -168,6 +169,24 @@ printable ASCII characters except space (i.e., the byte range 32 < x <
 and debugging purposes, and MUST NOT be used to programmatically assume
 the presence or absence of particular features.
 
+ archive
+~~~~~~~~~
+
+`archive` is the command to request an archive (such as a tarball) from a server
+over v2.
+
+archive takes the following optional arguments:
+
+    argument <arg>
+       This specifies that <arg> should be passed as an argument to the
+       underlying archive writer.  This option can be repeated to pass
+       additional arguments to the archive writer.
+
+See linkgit:git-archive[1] for allowed values of `<arg>`.
+
+The output of archive is a packet-line stream of the resulting archive, with
+error messages transferred over the sideband channel.
+
  ls-refs
 ~~~~~~~~~
 
diff --git a/builtin/archive.c b/builtin/archive.c
index 4eb547c5b7..f91d222677 100644
--- a/builtin/archive.c
+++ b/builtin/archive.c
@@ -5,9 +5,11 @@
 #include "cache.h"
 #include "builtin.h"
 #include "archive.h"
+#include "connect.h"
 #include "transport.h"
 #include "parse-options.h"
 #include "pkt-line.h"
+#include "protocol.h"
 #include "sideband.h"
 
 static void create_output_file(const char *output_file)
@@ -23,6 +25,13 @@ static void create_output_file(const char *output_file)
 	}
 }
 
+static void do_v2_command_and_cap(int out)
+{
+	packet_write_fmt(out, "command=archive\n");
+	/* Capability list would go here, if we wanted to request any. */
+	packet_delim(out);
+}
+
 static int run_remote_archiver(int argc, const char **argv,
 			       const char *remote, const char *exec,
 			       const char *name_hint)
@@ -32,6 +41,7 @@ static int run_remote_archiver(int argc, const char **argv,
 	struct remote *_remote;
 	struct packet_reader reader;
 	enum packet_read_status status;
+	enum protocol_version version;
 
 	_remote = remote_get(remote);
 	if (!_remote->url[0])
@@ -41,6 +51,11 @@ static int run_remote_archiver(int argc, const char **argv,
 
 	packet_reader_init(&reader, fd[0], NULL, 0, PACKET_READ_CHOMP_NEWLINE);
 
+	version = discover_version(&reader);
+
+	if (version == protocol_v2 && server_supports_v2("archive", 0))
+		do_v2_command_and_cap(fd[1]);
+
 	/*
 	 * Inject a fake --format field at the beginning of the
 	 * arguments, with the format inferred from our output
@@ -56,22 +71,24 @@ static int run_remote_archiver(int argc, const char **argv,
 		packet_write_fmt(fd[1], "argument %s\n", argv[i]);
 	packet_flush(fd[1]);
 
-	status = packet_reader_read(&reader);
-
-	if (status != PACKET_READ_NORMAL || reader.pktlen <= 0)
-		die(_("git archive: expected ACK/NAK, got a flush packet"));
-	if (strcmp(reader.line, "ACK")) {
-		if (starts_with(reader.line, "NACK "))
-			die(_("git archive: NACK %s"), reader.line + 5);
-		if (starts_with(reader.line, "ERR "))
-			die(_("remote error: %s"), reader.line + 4);
-		die(_("git archive: protocol error"));
+	if (version == protocol_v0) {
+		status = packet_reader_read(&reader);
+
+		if (status != PACKET_READ_NORMAL || reader.pktlen <= 0)
+			die(_("git archive: expected ACK/NAK, got a flush packet"));
+		if (strcmp(reader.line, "ACK")) {
+			if (starts_with(reader.line, "NACK "))
+				die(_("git archive: NACK %s"), reader.line + 5);
+			if (starts_with(reader.line, "ERR "))
+				die(_("remote error: %s"), reader.line + 4);
+			die(_("git archive: protocol error"));
+		}
+
+		status = packet_reader_read(&reader);
+		if (status == PACKET_READ_NORMAL && reader.pktlen > 0)
+			die(_("git archive: expected a flush"));
 	}
 
-	status = packet_reader_read(&reader);
-	if (status == PACKET_READ_NORMAL && reader.pktlen > 0)
-		die(_("git archive: expected a flush"));
-
 	/* Now, start reading from fd[0] and spit it out to stdout */
 	rv = recv_sideband("archive", fd[0], 1);
 	rv |= transport_disconnect(transport);
diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c
index 25d9116356..b8a8fb256f 100644
--- a/builtin/upload-archive.c
+++ b/builtin/upload-archive.c
@@ -5,6 +5,8 @@
 #include "builtin.h"
 #include "archive.h"
 #include "pkt-line.h"
+#include "protocol.h"
+#include "serve.h"
 #include "sideband.h"
 #include "run-command.h"
 #include "argv-array.h"
@@ -76,10 +78,24 @@ static ssize_t process_input(int child_fd, int band)
 int cmd_upload_archive(int argc, const char **argv, const char *prefix)
 {
 	struct child_process writer = { argv };
+	enum protocol_version version = determine_protocol_version_server();
 
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage(upload_archive_usage);
 
+	if (version == protocol_v2) {
+		struct serve_options options = SERVE_OPTIONS_INIT;
+
+		/* Send "version 2" message and capabilities. */
+		options.advertise_capabilities = 1;
+		serve(&options);
+
+		/* Process command request and validate client capabilities. */
+		options.advertise_capabilities = 0;
+		options.stateless_rpc = 1;
+		serve(&options);
+	}
+
 	/*
 	 * Set up sideband subprocess.
 	 *
@@ -92,12 +108,17 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
 	writer.git_cmd = 1;
 	if (start_command(&writer)) {
 		int err = errno;
-		packet_write_fmt(1, "NACK unable to spawn subprocess\n");
+		if (version == protocol_v0 || version == protocol_v1)
+			packet_write_fmt(1, "NACK unable to spawn subprocess\n");
+		else if (version == protocol_v2)
+			error_clnt("unable to spawn subprocess\n");
 		die("upload-archive: %s", strerror(err));
 	}
 
-	packet_write_fmt(1, "ACK\n");
-	packet_flush(1);
+	if (version == protocol_v0 || version == protocol_v1) {
+		packet_write_fmt(1, "ACK\n");
+		packet_flush(1);
+	}
 
 	while (1) {
 		struct pollfd pfd[2];
diff --git a/serve.c b/serve.c
index bda085f09c..cef575086f 100644
--- a/serve.c
+++ b/serve.c
@@ -52,8 +52,15 @@ struct protocol_capability {
 		       struct packet_reader *request);
 };
 
+static int noop(struct repository *r, struct argv_array *keys,
+		struct packet_reader *request)
+{
+	return 0;
+}
+
 static struct protocol_capability capabilities[] = {
 	{ "agent", agent_advertise, NULL },
+	{ "archive", always_advertise, noop },
 	{ "ls-refs", always_advertise, ls_refs },
 	{ "fetch", upload_pack_advertise, upload_pack_v2 },
 	{ "server-option", always_advertise, NULL },
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index c408e3a23d..4a76354021 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -138,6 +138,13 @@ test_expect_success \
 
 test_expect_success 'extract archive' 'check_tar b'
 
+test_expect_success 'protocol v2 for remote' '
+	GIT_PROTOCOL="version=2" GIT_TRACE_PACKET="$(pwd)/log" git archive \
+		--remote=. HEAD >v2_remote.tar &&
+	grep "version 2" log
+'
+test_expect_success 'extract v2 archive' 'check_tar v2_remote'
+
 test_expect_success 'git archive --prefix=prefix/' '
 	git archive --prefix=prefix/ HEAD >with_prefix.tar
 '
diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh
index 75ec79e6cb..f47a14660b 100755
--- a/t/t5701-git-serve.sh
+++ b/t/t5701-git-serve.sh
@@ -8,6 +8,7 @@ test_expect_success 'test capability advertisement' '
 	cat >expect <<-EOF &&
 	version 2
 	agent=git/$(git version | cut -d" " -f3)
+	archive
 	ls-refs
 	fetch=shallow
 	server-option
-- 
2.19.0.605.g01d371f741-goog


  parent reply	other threads:[~2018-09-27  1:25 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-12  5:35 Add proto v2 archive command with HTTP support Josh Steadmon
2018-09-12  5:35 ` [PATCH 1/3] archive: use packet_reader for communications Josh Steadmon
2018-09-12 22:01   ` Stefan Beller
2018-09-13 14:58   ` Junio C Hamano
2018-09-13 15:34     ` Junio C Hamano
2018-09-12  5:35 ` [PATCH 2/3] archive: implement protocol v2 archive command Josh Steadmon
2018-09-12 22:28   ` Stefan Beller
2018-09-13 18:45     ` Ævar Arnfjörð Bjarmason
2018-09-14  6:05       ` Jonathan Nieder
2018-09-14 14:31         ` Ævar Arnfjörð Bjarmason
2018-09-14 16:14         ` Junio C Hamano
2018-09-14 16:19           ` Jonathan Nieder
2018-09-13 16:31   ` Junio C Hamano
2018-09-14  5:39   ` Jonathan Nieder
2018-09-12  5:35 ` [PATCH 3/3] archive: allow archive over HTTP(S) with proto v2 Josh Steadmon
2018-09-12 22:38   ` Stefan Beller
2018-09-13 16:47   ` Junio C Hamano
2018-09-27 20:28     ` Josh Steadmon
2018-09-14  5:57   ` Jonathan Nieder
2018-09-14  5:36 ` Add proto v2 archive command with HTTP support Jonathan Nieder
2018-09-27  1:24 ` [PATCH v2 0/4] " Josh Steadmon
2018-09-27  1:24   ` [PATCH v2 1/4] archive: follow test standards around assertions Josh Steadmon
2018-09-27 18:38     ` Stefan Beller
2018-09-27  1:24   ` [PATCH v2 2/4] archive: use packet_reader for communications Josh Steadmon
2018-09-27 18:42     ` Stefan Beller
2018-09-27  1:24   ` Josh Steadmon [this message]
2018-09-27  1:24   ` [PATCH v2 4/4] archive: allow archive over HTTP(S) with proto v2 Josh Steadmon
2018-09-27 18:20   ` [PATCH v2 0/4] Add proto v2 archive command with HTTP support Stefan Beller
2018-09-27 18:30     ` Jonathan Nieder
2018-09-27 22:20       ` Junio C Hamano
2018-09-27 22:33         ` Josh Steadmon
2018-09-28  1:25           ` Junio C Hamano
2018-09-27 18:30     ` Josh Steadmon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180927012455.234876-4-steadmon@google.com \
    --to=steadmon@google.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.