diff mbox series

[v4,3/3] receive-pack: use default version 0 for proc-receive

Message ID 20201111113202.24911-4-zhiyou.jx@alibaba-inc.com (mailing list archive)
State New, archived
Headers show
Series [v3,1/2] t5411: refactor make_user_friendly_and_stable_output | expand

Commit Message

Jiang Xin Nov. 11, 2020, 11:32 a.m. UTC
In the verison negotiation phase between "receive-pack" and
"proc-receive", "proc-receive" can send an empty flush-pkt to end the
negotiation and use default version 0. Capabilities (such as
"push-options") are not supported in version 0.

Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
---
 builtin/receive-pack.c                       |  7 ++-
 t/helper/test-proc-receive.c                 | 16 +++--
 t/t5411/test-0026-push-options.sh            | 60 +++++++++++++++++++
 t/t5411/test-0027-push-options--porcelain.sh | 62 ++++++++++++++++++++
 4 files changed, 138 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 2bd736525f..f1f0f7bef6 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1192,7 +1192,12 @@  static int run_proc_receive_hook(struct command *commands,
 		goto cleanup;
 	}
 
-	if (version != 1) {
+	switch (version) {
+	case 0:
+		/* fallthrough */
+	case 1:
+		break;
+	default:
 		strbuf_addf(&errmsg, "proc-receive version '%d' is not supported",
 			    version);
 		code = -1;
diff --git a/t/helper/test-proc-receive.c b/t/helper/test-proc-receive.c
index 6652cedcee..cc08506cf0 100644
--- a/t/helper/test-proc-receive.c
+++ b/t/helper/test-proc-receive.c
@@ -45,8 +45,14 @@  static void proc_receive_verison(struct packet_reader *reader) {
 		if (packet_reader_read(reader) != PACKET_READ_NORMAL)
 			break;
 
+		/* Ignore version negotiation for version 0 */
+		if (version == 0)
+			continue;
+
 		if (reader->pktlen > 8 && starts_with(reader->line, "version=")) {
 			server_version = atoi(reader->line+8);
+			if (server_version != 1)
+				die("bad protocol version: %d", server_version);
 			linelen = strlen(reader->line);
 			if (linelen < reader->pktlen) {
 				const char *feature_list = reader->line + linelen + 1;
@@ -58,15 +64,13 @@  static void proc_receive_verison(struct packet_reader *reader) {
 		}
 	}
 
-	if (server_version != 1)
-		die("bad protocol version: %d", server_version);
-
 	if (die_write_version)
 		die("die with the --die-write-version option");
 
-	packet_write_fmt(1, "version=%d%c%s\n",
-			 version, '\0',
-			 use_push_options && !no_push_options ? "push-options": "");
+	if (version != 0)
+		packet_write_fmt(1, "version=%d%c%s\n",
+				 version, '\0',
+				 use_push_options && !no_push_options ? "push-options": "");
 	packet_flush(1);
 }
 
diff --git a/t/t5411/test-0026-push-options.sh b/t/t5411/test-0026-push-options.sh
index d414be87d0..e88edb16a4 100644
--- a/t/t5411/test-0026-push-options.sh
+++ b/t/t5411/test-0026-push-options.sh
@@ -32,6 +32,66 @@  test_expect_success "enable push options ($PROTOCOL)" '
 	git -C "$upstream" config receive.advertisePushOptions true
 '
 
+test_expect_success "setup version=0 for proc-receive hook ($PROTOCOL)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v \
+		--version 0 \
+		-r "ok refs/for/main/topic"
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push -o ...  :                       next(A)  refs/for/main/topic
+test_expect_success "proc-receive: ignore push-options for version 0 ($PROTOCOL)" '
+	git -C workbench push \
+		--atomic \
+		-o issue=123 \
+		-o reviewer=user1 \
+		origin \
+		HEAD:refs/heads/next \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	remote: # pre-receive hook
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: # proc-receive hook
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
+	remote: # post-receive hook
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	To <URL/of/upstream.git>
+	 * [new branch] HEAD -> next
+	 * [new reference] HEAD -> refs/for/main/topic
+	EOF
+	test_cmp expect actual &&
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
+	<COMMIT-A> refs/heads/next
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "restore proc-receive hook ($PROTOCOL)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v \
+		-r "ok refs/for/main/topic"
+	EOF
+'
+
+# Refs of upstream : main(A)             next(A)
+# Refs of workbench: main(A)  tags/v123
+test_expect_success "cleanup ($PROTOCOL)" '
+	git -C "$upstream" update-ref -d refs/heads/next
+'
+
 # Refs of upstream : main(A)
 # Refs of workbench: main(A)  tags/v123
 # git push -o ...  :                       next(A)  refs/for/main/topic
diff --git a/t/t5411/test-0027-push-options--porcelain.sh b/t/t5411/test-0027-push-options--porcelain.sh
index d5d0dcb172..3a6561b5ea 100644
--- a/t/t5411/test-0027-push-options--porcelain.sh
+++ b/t/t5411/test-0027-push-options--porcelain.sh
@@ -33,6 +33,68 @@  test_expect_success "enable push options ($PROTOCOL/porcelain)" '
 	git -C "$upstream" config receive.advertisePushOptions true
 '
 
+test_expect_success "setup version=0 for proc-receive hook ($PROTOCOL/porcelain)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v \
+		--version 0 \
+		-r "ok refs/for/main/topic"
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push -o ...  :                       next(A)  refs/for/main/topic
+test_expect_success "proc-receive: ignore push-options for version 0 ($PROTOCOL/porcelain)" '
+	git -C workbench push \
+		--porcelain \
+		--atomic \
+		-o issue=123 \
+		-o reviewer=user1 \
+		origin \
+		HEAD:refs/heads/next \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	remote: # pre-receive hook
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: # proc-receive hook
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
+	remote: # post-receive hook
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	To <URL/of/upstream.git>
+	*    HEAD:refs/heads/next    [new branch]
+	*    HEAD:refs/for/main/topic    [new reference]
+	Done
+	EOF
+	test_cmp expect actual &&
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
+	<COMMIT-A> refs/heads/next
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "restore proc-receive hook ($PROTOCOL/porcelain)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v \
+		-r "ok refs/for/main/topic"
+	EOF
+'
+
+# Refs of upstream : main(A)             next(A)
+# Refs of workbench: main(A)  tags/v123
+test_expect_success "cleanup ($PROTOCOL/porcelain)" '
+	git -C "$upstream" update-ref -d refs/heads/next
+'
+
 # Refs of upstream : main(A)
 # Refs of workbench: main(A)  tags/v123
 # git push -o ...  :                       next(A)  refs/for/main/topic