receive-pack: gently write messages to proc-receive

Johannes found a flaky hang in `t5411/test-0013-bad-protocol.sh` in the osx-clang job of the CI/PR builds, and ran into an issue when using the `--stress` option with the following error messages: fatal: unable to write flush packet: Broken pipe send-pack: unexpected disconnect while reading sideband packet fatal: the remote end hung up unexpectedly In this test case, the "proc-receive" hook sends an error message and dies earlier. While "receive-pack" on the other side of the pipe should forward the error message of the "proc-receive" hook to the client side, but it fails to do so. This is because "receive-pack" uses `packet_write_fmt()` and `packet_flush()` to write pkt-line message to "proc-receive" hook, and these functions die immediately when pipe is broken. Using "gently" forms for these functions will get more predicable output. Add more "--die-*" options to test helper to test different stages of the protocol between "receive-pack" and "proc-receive" hook. Reported-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Suggested-by: Jeff King <peff@peff.net> Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jiang Xin committed Nov 11, 2020 at 19:32 UTC f65003b4c4abea49a00cc9f3d87b9f37db6b48f1
4 files changed +392 -48
builtin/receive-pack.c
+63 -24
@@ -977,15 +977,25 @@ static int read_proc_receive_report(struct packet_reader *reader,
977 int new_report = 0;
978 int code = 0;
979 int once = 0;
980 + int response = 0;
981
982 for (;;) {
983 struct object_id old_oid, new_oid;
984 const char *head;
985 const char *refname;
986 char *p;
986 -
987 - if (packet_reader_read(reader) != PACKET_READ_NORMAL)
987 + enum packet_read_status status;
988 +
989 + status = packet_reader_read(reader);
990 + if (status != PACKET_READ_NORMAL) {
991 + /* Check whether proc-receive exited abnormally */
992 + if (status == PACKET_READ_EOF && !response) {
993 + strbuf_addstr(errmsg, "proc-receive exited abnormally");
994 + return -1;
995 + }
996 break;
997 + }
998 + response++;
999
1000 head = reader->line;
1001 p = strchr(head, ' ');
@@ -1145,28 +1155,41 @@ static int run_proc_receive_hook(struct command *commands,
1155 if (use_push_options)
1156 strbuf_addstr(&cap, " push-options");
1157 if (cap.len) {
1148 - packet_write_fmt(proc.in, "version=1%c%s\n", '\0', cap.buf + 1);
1158 + code = packet_write_fmt_gently(proc.in, "version=1%c%s\n", '\0', cap.buf + 1);
1159 strbuf_release(&cap);
1160 } else {
1151 - packet_write_fmt(proc.in, "version=1\n");
1161 + code = packet_write_fmt_gently(proc.in, "version=1\n");
1162 }
1153 - packet_flush(proc.in);
1163 + if (!code)
1164 + code = packet_flush_gently(proc.in);
1165
1155 - for (;;) {
1156 - int linelen;
1166 + if (!code)
1167 + for (;;) {
1168 + int linelen;
1169 + enum packet_read_status status;
1170
1158 - if (packet_reader_read(&reader) != PACKET_READ_NORMAL)
1159 - break;
1171 + status = packet_reader_read(&reader);
1172 + if (status != PACKET_READ_NORMAL) {
1173 + /* Check whether proc-receive exited abnormally */
1174 + if (status == PACKET_READ_EOF)
1175 + code = -1;
1176 + break;
1177 + }
1178
1161 - if (reader.pktlen > 8 && starts_with(reader.line, "version=")) {
1162 - version = atoi(reader.line + 8);
1163 - linelen = strlen(reader.line);
1164 - if (linelen < reader.pktlen) {
1165 - const char *feature_list = reader.line + linelen + 1;
1166 - if (parse_feature_request(feature_list, "push-options"))
1167 - hook_use_push_options = 1;
1179 + if (reader.pktlen > 8 && starts_with(reader.line, "version=")) {
1180 + version = atoi(reader.line + 8);
1181 + linelen = strlen(reader.line);
1182 + if (linelen < reader.pktlen) {
1183 + const char *feature_list = reader.line + linelen + 1;
1184 + if (parse_feature_request(feature_list, "push-options"))
1185 + hook_use_push_options = 1;
1186 + }
1187 }
1188 }
1189 +
1190 + if (code) {
1191 + strbuf_addstr(&errmsg, "fail to negotiate version with proc-receive hook");
1192 + goto cleanup;
1193 }
1194
1195 if (version != 1) {
@@ -1180,20 +1203,36 @@ static int run_proc_receive_hook(struct command *commands,
1203 for (cmd = commands; cmd; cmd = cmd->next) {
1204 if (!cmd->run_proc_receive || cmd->skip_update || cmd->error_string)
1205 continue;
1183 - packet_write_fmt(proc.in, "%s %s %s",
1184 - oid_to_hex(&cmd->old_oid),
1185 - oid_to_hex(&cmd->new_oid),
1186 - cmd->ref_name);
1206 + code = packet_write_fmt_gently(proc.in, "%s %s %s",
1207 + oid_to_hex(&cmd->old_oid),
1208 + oid_to_hex(&cmd->new_oid),
1209 + cmd->ref_name);
1210 + if (code)
1211 + break;
1212 + }
1213 + if (!code)
1214 + code = packet_flush_gently(proc.in);
1215 + if (code) {
1216 + strbuf_addstr(&errmsg, "fail to write commands to proc-receive hook");
1217 + goto cleanup;
1218 }
1188 - packet_flush(proc.in);
1219
1220 /* Send push options */
1221 if (hook_use_push_options) {
1222 struct string_list_item *item;
1223
1194 - for_each_string_list_item(item, push_options)
1195 - packet_write_fmt(proc.in, "%s", item->string);
1196 - packet_flush(proc.in);
1224 + for_each_string_list_item(item, push_options) {
1225 + code = packet_write_fmt_gently(proc.in, "%s", item->string);
1226 + if (code)
1227 + break;
1228 + }
1229 + if (!code)
1230 + code = packet_flush_gently(proc.in);
1231 + if (code) {
1232 + strbuf_addstr(&errmsg,
1233 + "fail to write push-options to proc-receive hook");
1234 + goto cleanup;
1235 + }
1236 }
1237
1238 /* Read result from proc-receive */
t/helper/test-proc-receive.c
+32 -10
@@ -10,8 +10,11 @@ static const char *proc_receive_usage[] = {
10 NULL
11 };
12
13 -static int die_version;
14 -static int die_readline;
13 +static int die_read_version;
14 +static int die_write_version;
15 +static int die_read_commands;
16 +static int die_read_push_options;
17 +static int die_write_report;
18 static int no_push_options;
19 static int use_atomic;
20 static int use_push_options;
@@ -33,6 +36,9 @@ struct command {
36 static void proc_receive_verison(struct packet_reader *reader) {
37 int server_version = 0;
38
39 + if (die_read_version)
40 + die("die with the --die-read-version option");
41 +
42 for (;;) {
43 int linelen;
44
@@ -52,9 +58,12 @@ static void proc_receive_verison(struct packet_reader *reader) {
58 }
59 }
60
55 - if (server_version != 1 || die_version)
61 + if (server_version != 1)
62 die("bad protocol version: %d", server_version);
63
64 + if (die_write_version)
65 + die("die with the --die-write-version option");
66 +
67 packet_write_fmt(1, "version=%d%c%s\n",
68 version, '\0',
69 use_push_options && !no_push_options ? "push-options": "");
@@ -75,11 +84,13 @@ static void proc_receive_read_commands(struct packet_reader *reader,
84 if (packet_reader_read(reader) != PACKET_READ_NORMAL)
85 break;
86
87 + if (die_read_commands)
88 + die("die with the --die-read-commands option");
89 +
90 if (parse_oid_hex(reader->line, &old_oid, &p) ||
91 *p++ != ' ' ||
92 parse_oid_hex(p, &new_oid, &p) ||
81 - *p++ != ' ' ||
82 - die_readline)
93 + *p++ != ' ')
94 die("protocol error: expected 'old new ref', got '%s'",
95 reader->line);
96 refname = p;
@@ -99,6 +110,9 @@ static void proc_receive_read_push_options(struct packet_reader *reader,
110 if (no_push_options || !use_push_options)
111 return;
112
113 + if (die_read_push_options)
114 + die("die with the --die-read-push-options option");
115 +
116 while (1) {
117 if (packet_reader_read(reader) != PACKET_READ_NORMAL)
118 break;
@@ -117,10 +131,16 @@ int cmd__proc_receive(int argc, const char **argv)
131 struct option options[] = {
132 OPT_BOOL(0, "no-push-options", &no_push_options,
133 "disable push options"),
120 - OPT_BOOL(0, "die-version", &die_version,
121 - "die during version negotiation"),
122 - OPT_BOOL(0, "die-readline", &die_readline,
123 - "die when readline"),
134 + OPT_BOOL(0, "die-read-version", &die_read_version,
135 + "die when reading version"),
136 + OPT_BOOL(0, "die-write-version", &die_write_version,
137 + "die when writing version"),
138 + OPT_BOOL(0, "die-read-commands", &die_read_commands,
139 + "die when reading commands"),
140 + OPT_BOOL(0, "die-read-push-options", &die_read_push_options,
141 + "die when reading push-options"),
142 + OPT_BOOL(0, "die-write-report", &die_write_report,
143 + "die when writing report"),
144 OPT_STRING_LIST('r', "return", &returns, "old/new/ref/status/msg",
145 "return of results"),
146 OPT__VERBOSE(&verbose, "be verbose"),
@@ -136,7 +156,7 @@ int cmd__proc_receive(int argc, const char **argv)
156 usage_msg_opt("Too many arguments.", proc_receive_usage, options);
157 packet_reader_init(&reader, 0, NULL, 0,
158 PACKET_READ_CHOMP_NEWLINE |
139 - PACKET_READ_DIE_ON_ERR_PACKET);
159 + PACKET_READ_GENTLE_ON_EOF);
160
161 sigchain_push(SIGPIPE, SIG_IGN);
162 proc_receive_verison(&reader);
@@ -166,6 +186,8 @@ int cmd__proc_receive(int argc, const char **argv)
186 fprintf(stderr, "proc-receive> %s\n", item->string);
187 }
188
189 + if (die_write_report)
190 + die("die with the --die-write-report option");
191 if (returns.nr)
192 for_each_string_list_item(item, &returns)
193 packet_write_fmt(1, "%s\n", item->string);
t/t5411/test-0013-bad-protocol.sh
+125 -13
@@ -16,7 +16,8 @@ test_expect_success "proc-receive: bad protocol (unknown version, $PROTOCOL)" '
16
17 # Check status report for git-push
18 sed -n \
19 - -e "/^To / { p; n; p; }" \
19 + -e "/^To / { p; }" \
20 + -e "/^ ! / { p; }" \
21 <actual >actual-report &&
22 cat >expect <<-EOF &&
23 To <URL/of/upstream.git>
@@ -41,32 +42,98 @@ test_expect_success "proc-receive: bad protocol (unknown version, $PROTOCOL)" '
42 test_cmp expect actual
43 '
44
44 -test_expect_success "setup proc-receive hook (hook --die-version, $PROTOCOL)" '
45 +test_expect_success "setup proc-receive hook (hook --die-read-version, $PROTOCOL)" '
46 write_script "$upstream/hooks/proc-receive" <<-EOF
47 printf >&2 "# proc-receive hook\n"
47 - test-tool proc-receive -v --die-version
48 + test-tool proc-receive -v --die-read-version
49 EOF
50 '
51
52 # Refs of upstream : main(A)
53 # Refs of workbench: main(A) tags/v123
54 # git push : refs/for/main/topic(A)
54 -test_expect_success "proc-receive: bad protocol (hook --die-version, $PROTOCOL)" '
55 +test_expect_success "proc-receive: bad protocol (hook --die-read-version, $PROTOCOL)" '
56 test_must_fail git -C workbench push origin \
57 HEAD:refs/for/main/topic \
58 >out 2>&1 &&
59 + filter_out_user_friendly_and_stable_output \
60 + -e "/^To / { p; }" \
61 + -e "/^ ! / { p; }" \
62 + <out >actual &&
63 + cat >expect <<-EOF &&
64 + To <URL/of/upstream.git>
65 + ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
66 + EOF
67 + test_cmp expect actual &&
68 + grep "remote: fatal: die with the --die-read-version option" out &&
69 + grep "remote: error: fail to negotiate version with proc-receive hook" out &&
70 +
71 + git -C "$upstream" show-ref >out &&
72 make_user_friendly_and_stable_output <out >actual &&
73 + cat >expect <<-EOF &&
74 + <COMMIT-A> refs/heads/main
75 + EOF
76 + test_cmp expect actual
77 +'
78 +
79 +test_expect_success "setup proc-receive hook (hook --die-write-version, $PROTOCOL)" '
80 + write_script "$upstream/hooks/proc-receive" <<-EOF
81 + printf >&2 "# proc-receive hook\n"
82 + test-tool proc-receive -v --die-write-version
83 + EOF
84 +'
85
86 +# Refs of upstream : main(A)
87 +# Refs of workbench: main(A) tags/v123
88 +# git push : refs/for/main/topic(A)
89 +test_expect_success "proc-receive: bad protocol (hook --die-write-version, $PROTOCOL)" '
90 + test_must_fail git -C workbench push origin \
91 + HEAD:refs/for/main/topic \
92 + >out 2>&1 &&
93 + filter_out_user_friendly_and_stable_output \
94 + -e "/^To / { p; }" \
95 + -e "/^ ! / { p; }" \
96 + <out >actual &&
97 + cat >expect <<-EOF &&
98 + To <URL/of/upstream.git>
99 + ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
100 + EOF
101 + test_cmp expect actual &&
102 + grep "remote: fatal: die with the --die-write-version option" out &&
103 + grep "remote: error: fail to negotiate version with proc-receive hook" out &&
104 +
105 + git -C "$upstream" show-ref >out &&
106 + make_user_friendly_and_stable_output <out >actual &&
107 + cat >expect <<-EOF &&
108 + <COMMIT-A> refs/heads/main
109 + EOF
110 + test_cmp expect actual
111 +'
112 +
113 +test_expect_success "setup proc-receive hook (hook --die-read-commands, $PROTOCOL)" '
114 + write_script "$upstream/hooks/proc-receive" <<-EOF
115 + printf >&2 "# proc-receive hook\n"
116 + test-tool proc-receive -v --die-read-commands
117 + EOF
118 +'
119 +
120 +# Refs of upstream : main(A)
121 +# Refs of workbench: main(A) tags/v123
122 +# git push : refs/for/main/topic(A)
123 +test_expect_success "proc-receive: bad protocol (hook --die-read-commands, $PROTOCOL)" '
124 + test_must_fail git -C workbench push origin \
125 + HEAD:refs/for/main/topic \
126 + >out 2>&1 &&
127 + filter_out_user_friendly_and_stable_output \
128 + -e "/^To / { p; }" \
129 + -e "/^ ! / { p; }" \
130 + <out >actual &&
131 cat >expect <<-EOF &&
61 - remote: # pre-receive hook
62 - remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
63 - remote: # proc-receive hook
64 - remote: fatal: bad protocol version: 1
65 - remote: error: proc-receive version "0" is not supported
132 To <URL/of/upstream.git>
133 ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
134 EOF
135 test_cmp expect actual &&
136 + grep "remote: fatal: die with the --die-read-commands option" out &&
137
138 git -C "$upstream" show-ref >out &&
139 make_user_friendly_and_stable_output <out >actual &&
@@ -76,23 +143,65 @@ test_expect_success "proc-receive: bad protocol (hook --die-version, $PROTOCOL)"
143 test_cmp expect actual
144 '
145
79 -test_expect_success "setup proc-receive hook (hook --die-readline, $PROTOCOL)" '
146 +test_expect_success "setup proc-receive hook (hook --die-read-push-options, $PROTOCOL)" '
147 write_script "$upstream/hooks/proc-receive" <<-EOF
148 printf >&2 "# proc-receive hook\n"
82 - test-tool proc-receive -v --die-readline
149 + test-tool proc-receive -v --die-read-push-options
150 EOF
151 '
152
153 # Refs of upstream : main(A)
154 # Refs of workbench: main(A) tags/v123
155 # git push : refs/for/main/topic(A)
89 -test_expect_success "proc-receive: bad protocol (hook --die-readline, $PROTOCOL)" '
156 +test_expect_success "proc-receive: bad protocol (hook --die-read-push-options, $PROTOCOL)" '
157 + git -C "$upstream" config receive.advertisePushOptions true &&
158 test_must_fail git -C workbench push origin \
159 + -o reviewers=user1,user2 \
160 HEAD:refs/for/main/topic \
161 >out 2>&1 &&
162 + filter_out_user_friendly_and_stable_output \
163 + -e "/^To / { p; }" \
164 + -e "/^ ! / { p; }" \
165 + <out >actual &&
166 + cat >expect <<-EOF &&
167 + To <URL/of/upstream.git>
168 + ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
169 + EOF
170 + test_cmp expect actual &&
171 + grep "remote: fatal: die with the --die-read-push-options option" out &&
172 +
173 + git -C "$upstream" show-ref >out &&
174 make_user_friendly_and_stable_output <out >actual &&
175 + cat >expect <<-EOF &&
176 + <COMMIT-A> refs/heads/main
177 + EOF
178 + test_cmp expect actual
179 +'
180 +
181 +test_expect_success "setup proc-receive hook (hook --die-write-report, $PROTOCOL)" '
182 + write_script "$upstream/hooks/proc-receive" <<-EOF
183 + printf >&2 "# proc-receive hook\n"
184 + test-tool proc-receive -v --die-write-report
185 + EOF
186 +'
187
95 - grep "remote: fatal: protocol error: expected \"old new ref\", got \"<ZERO-OID> <COMMIT-A> refs/for/main/topic\"" actual &&
188 +# Refs of upstream : main(A)
189 +# Refs of workbench: main(A) tags/v123
190 +# git push : refs/for/main/topic(A)
191 +test_expect_success "proc-receive: bad protocol (hook --die-write-report, $PROTOCOL)" '
192 + test_must_fail git -C workbench push origin \
193 + HEAD:refs/for/main/topic \
194 + >out 2>&1 &&
195 + filter_out_user_friendly_and_stable_output \
196 + -e "/^To / { p; }" \
197 + -e "/^ ! / { p; }" \
198 + <out >actual &&
199 + cat >expect <<-EOF &&
200 + To <URL/of/upstream.git>
201 + ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
202 + EOF
203 + test_cmp expect actual &&
204 + grep "remote: fatal: die with the --die-write-report option" out &&
205
206 git -C "$upstream" show-ref >out &&
207 make_user_friendly_and_stable_output <out >actual &&
@@ -130,6 +239,7 @@ test_expect_success "proc-receive: bad protocol (no report, $PROTOCOL)" '
239 ! [remote rejected] HEAD -> refs/for/main/topic (proc-receive failed to report status)
240 EOF
241 test_cmp expect actual &&
242 +
243 git -C "$upstream" show-ref >out &&
244 make_user_friendly_and_stable_output <out >actual &&
245 cat >expect <<-EOF &&
@@ -173,6 +283,7 @@ test_expect_success "proc-receive: bad protocol (no ref, $PROTOCOL)" '
283 ! [remote rejected] HEAD -> refs/for/main/topic (proc-receive failed to report status)
284 EOF
285 test_cmp expect actual &&
286 +
287 git -C "$upstream" show-ref >out &&
288 make_user_friendly_and_stable_output <out >actual &&
289 cat >expect <<-EOF &&
@@ -208,6 +319,7 @@ test_expect_success "proc-receive: bad protocol (unknown status, $PROTOCOL)" '
319 ! [remote rejected] HEAD -> refs/for/main/topic (proc-receive failed to report status)
320 EOF
321 test_cmp expect actual &&
322 +
323 git -C "$upstream" show-ref >out &&
324 make_user_friendly_and_stable_output <out >actual &&
325 cat >expect <<-EOF &&
t/t5411/test-0014-bad-protocol--porcelain.sh
+172 -1
@@ -42,6 +42,175 @@ test_expect_success "proc-receive: bad protocol (unknown version, $PROTOCOL/porc
42 test_cmp expect actual
43 '
44
45 +test_expect_success "setup proc-receive hook (hook --die-read-version, $PROTOCOL/porcelain)" '
46 + write_script "$upstream/hooks/proc-receive" <<-EOF
47 + printf >&2 "# proc-receive hook\n"
48 + test-tool proc-receive -v --die-read-version
49 + EOF
50 +'
51 +
52 +# Refs of upstream : main(A)
53 +# Refs of workbench: main(A) tags/v123
54 +# git push : refs/for/main/topic(A)
55 +test_expect_success "proc-receive: bad protocol (hook --die-read-version, $PROTOCOL/porcelain)" '
56 + test_must_fail git -C workbench push --porcelain origin \
57 + HEAD:refs/for/main/topic \
58 + >out 2>&1 &&
59 + filter_out_user_friendly_and_stable_output \
60 + -e "/^To / { p; n; p; n; p; }" \
61 + <out >actual &&
62 + cat >expect <<-EOF &&
63 + To <URL/of/upstream.git>
64 + ! HEAD:refs/for/main/topic [remote rejected] (fail to run proc-receive hook)
65 + Done
66 + EOF
67 + test_cmp expect actual &&
68 + grep "remote: fatal: die with the --die-read-version option" out &&
69 + grep "remote: error: fail to negotiate version with proc-receive hook" out &&
70 +
71 + git -C "$upstream" show-ref >out &&
72 + make_user_friendly_and_stable_output <out >actual &&
73 + cat >expect <<-EOF &&
74 + <COMMIT-A> refs/heads/main
75 + EOF
76 + test_cmp expect actual
77 +'
78 +
79 +test_expect_success "setup proc-receive hook (hook --die-write-version, $PROTOCOL/porcelain)" '
80 + write_script "$upstream/hooks/proc-receive" <<-EOF
81 + printf >&2 "# proc-receive hook\n"
82 + test-tool proc-receive -v --die-write-version
83 + EOF
84 +'
85 +
86 +# Refs of upstream : main(A)
87 +# Refs of workbench: main(A) tags/v123
88 +# git push : refs/for/main/topic(A)
89 +test_expect_success "proc-receive: bad protocol (hook --die-write-version, $PROTOCOL/porcelain)" '
90 + test_must_fail git -C workbench push --porcelain origin \
91 + HEAD:refs/for/main/topic \
92 + >out 2>&1 &&
93 + filter_out_user_friendly_and_stable_output \
94 + -e "/^To / { p; n; p; n; p; }" \
95 + <out >actual &&
96 + cat >expect <<-EOF &&
97 + To <URL/of/upstream.git>
98 + ! HEAD:refs/for/main/topic [remote rejected] (fail to run proc-receive hook)
99 + Done
100 + EOF
101 + test_cmp expect actual &&
102 + grep "remote: fatal: die with the --die-write-version option" out &&
103 + grep "remote: error: fail to negotiate version with proc-receive hook" out &&
104 +
105 + git -C "$upstream" show-ref >out &&
106 + make_user_friendly_and_stable_output <out >actual &&
107 + cat >expect <<-EOF &&
108 + <COMMIT-A> refs/heads/main
109 + EOF
110 + test_cmp expect actual
111 +'
112 +
113 +test_expect_success "setup proc-receive hook (hook --die-read-commands, $PROTOCOL/porcelain)" '
114 + write_script "$upstream/hooks/proc-receive" <<-EOF
115 + printf >&2 "# proc-receive hook\n"
116 + test-tool proc-receive -v --die-read-commands
117 + EOF
118 +'
119 +
120 +# Refs of upstream : main(A)
121 +# Refs of workbench: main(A) tags/v123
122 +# git push : refs/for/main/topic(A)
123 +test_expect_success "proc-receive: bad protocol (hook --die-read-commands, $PROTOCOL/porcelain)" '
124 + test_must_fail git -C workbench push --porcelain origin \
125 + HEAD:refs/for/main/topic \
126 + >out 2>&1 &&
127 + filter_out_user_friendly_and_stable_output \
128 + -e "/^To / { p; n; p; n; p; }" \
129 + <out >actual &&
130 + cat >expect <<-EOF &&
131 + To <URL/of/upstream.git>
132 + ! HEAD:refs/for/main/topic [remote rejected] (fail to run proc-receive hook)
133 + Done
134 + EOF
135 + test_cmp expect actual &&
136 + grep "remote: fatal: die with the --die-read-commands option" out &&
137 +
138 + git -C "$upstream" show-ref >out &&
139 + make_user_friendly_and_stable_output <out >actual &&
140 + cat >expect <<-EOF &&
141 + <COMMIT-A> refs/heads/main
142 + EOF
143 + test_cmp expect actual
144 +'
145 +
146 +test_expect_success "setup proc-receive hook (hook --die-read-push-options, $PROTOCOL/porcelain)" '
147 + write_script "$upstream/hooks/proc-receive" <<-EOF
148 + printf >&2 "# proc-receive hook\n"
149 + test-tool proc-receive -v --die-read-push-options
150 + EOF
151 +'
152 +
153 +# Refs of upstream : main(A)
154 +# Refs of workbench: main(A) tags/v123
155 +# git push : refs/for/main/topic(A)
156 +test_expect_success "proc-receive: bad protocol (hook --die-read-push-options, $PROTOCOL/porcelain)" '
157 + git -C "$upstream" config receive.advertisePushOptions true &&
158 + test_must_fail git -C workbench push --porcelain origin \
159 + -o reviewers=user1,user2 \
160 + HEAD:refs/for/main/topic \
161 + >out 2>&1 &&
162 + filter_out_user_friendly_and_stable_output \
163 + -e "/^To / { p; n; p; n; p; }" \
164 + <out >actual &&
165 + cat >expect <<-EOF &&
166 + To <URL/of/upstream.git>
167 + ! HEAD:refs/for/main/topic [remote rejected] (fail to run proc-receive hook)
168 + Done
169 + EOF
170 + test_cmp expect actual &&
171 + grep "remote: fatal: die with the --die-read-push-options option" out &&
172 +
173 + git -C "$upstream" show-ref >out &&
174 + make_user_friendly_and_stable_output <out >actual &&
175 + cat >expect <<-EOF &&
176 + <COMMIT-A> refs/heads/main
177 + EOF
178 + test_cmp expect actual
179 +'
180 +
181 +test_expect_success "setup proc-receive hook (hook --die-write-report, $PROTOCOL/porcelain)" '
182 + write_script "$upstream/hooks/proc-receive" <<-EOF
183 + printf >&2 "# proc-receive hook\n"
184 + test-tool proc-receive -v --die-write-report
185 + EOF
186 +'
187 +
188 +# Refs of upstream : main(A)
189 +# Refs of workbench: main(A) tags/v123
190 +# git push : refs/for/main/topic(A)
191 +test_expect_success "proc-receive: bad protocol (hook --die-write-report, $PROTOCOL/porcelain)" '
192 + test_must_fail git -C workbench push --porcelain origin \
193 + HEAD:refs/for/main/topic \
194 + >out 2>&1 &&
195 + filter_out_user_friendly_and_stable_output \
196 + -e "/^To / { p; n; p; n; p; }" \
197 + <out >actual &&
198 + cat >expect <<-EOF &&
199 + To <URL/of/upstream.git>
200 + ! HEAD:refs/for/main/topic [remote rejected] (fail to run proc-receive hook)
201 + Done
202 + EOF
203 + test_cmp expect actual &&
204 + grep "remote: fatal: die with the --die-write-report option" out &&
205 +
206 + git -C "$upstream" show-ref >out &&
207 + make_user_friendly_and_stable_output <out >actual &&
208 + cat >expect <<-EOF &&
209 + <COMMIT-A> refs/heads/main
210 + EOF
211 + test_cmp expect actual
212 +'
213 +
214 test_expect_success "setup proc-receive hook (no report, $PROTOCOL/porcelain)" '
215 write_script "$upstream/hooks/proc-receive" <<-EOF
216 printf >&2 "# proc-receive hook\n"
@@ -71,6 +240,7 @@ test_expect_success "proc-receive: bad protocol (no report, $PROTOCOL/porcelain)
240 Done
241 EOF
242 test_cmp expect actual &&
243 +
244 git -C "$upstream" show-ref >out &&
245 make_user_friendly_and_stable_output <out >actual &&
246 cat >expect <<-EOF &&
@@ -84,7 +254,6 @@ test_expect_success "proc-receive: bad protocol (no report, $PROTOCOL/porcelain)
254 # Refs of workbench: main(A) tags/v123
255 test_expect_success "cleanup ($PROTOCOL/porcelain)" '
256 git -C "$upstream" update-ref -d refs/heads/next
87 -
257 '
258
259 test_expect_success "setup proc-receive hook (no ref, $PROTOCOL/porcelain)" '
@@ -115,6 +284,7 @@ test_expect_success "proc-receive: bad protocol (no ref, $PROTOCOL/porcelain)" '
284 Done
285 EOF
286 test_cmp expect actual &&
287 +
288 git -C "$upstream" show-ref >out &&
289 make_user_friendly_and_stable_output <out >actual &&
290 cat >expect <<-EOF &&
@@ -151,6 +321,7 @@ test_expect_success "proc-receive: bad protocol (unknown status, $PROTOCOL/porce
321 Done
322 EOF
323 test_cmp expect actual &&
324 +
325 git -C "$upstream" show-ref >out &&
326 make_user_friendly_and_stable_output <out >actual &&
327 cat >expect <<-EOF &&