Commit 98f64f14c3dc52ec6afc00acc53dc9f42399d363

Stefan Sperling 2021-01-05T17:17:58

work around spurious ACK responses from git servers in got-fetch-pack The Git server can apparently send duplicate ACK responses even though we do not enable the multi_ack capability. According to the Git protocol docs the server should only send ACKs after receiving 'done' from the client if multi_ack has been enabled. However, a duplicate ACK response can be triggered by running 'got fetch -a' in our fetch_update_tag test. This resulted in the following error: got-fetch-pack: unknown side-band received from server got: bad packet received

diff --git a/libexec/got-fetch-pack/got-fetch-pack.c b/libexec/got-fetch-pack/got-fetch-pack.c
index 9d32767..dd739fa 100644
--- a/libexec/got-fetch-pack/got-fetch-pack.c
+++ b/libexec/got-fetch-pack/got-fetch-pack.c
@@ -991,6 +991,25 @@ fetch_pack(int fd, int packfd, uint8_t *pack_sha1,
 				}
 				err = fetch_error(buf, r);
 				goto done;
+			} else if (buf[0] == 'A') {
+				err = readn(&r, fd, buf, datalen);
+				if (err)
+					goto done;
+				if (r != datalen) {
+					err = got_error_msg(GOT_ERR_BAD_PACKET,
+					    "packet too short");
+					goto done;
+				}
+				/*
+				 * Git server responds with ACK after 'done'
+				 * even though multi_ack is disabled?!?
+				 */
+				buf[r] = '\0';
+				if (strncmp(buf, "CK ", 3) == 0)
+					continue; /* ignore */
+				err = got_error_msg(GOT_ERR_BAD_PACKET,
+				    "unexpected message from server");
+				goto done;
 			} else {
 				err = got_error_msg(GOT_ERR_BAD_PACKET,
 				    "unknown side-band received from server");
diff --git a/regress/cmdline/fetch.sh b/regress/cmdline/fetch.sh
index 06f040f..0af6ce5 100755
--- a/regress/cmdline/fetch.sh
+++ b/regress/cmdline/fetch.sh
@@ -560,7 +560,7 @@ test_fetch_update_tag() {
 		return 1
 	fi
 
-	got fetch -q -r $testroot/repo-clone
+	got fetch -a -q -r $testroot/repo-clone
 	ret="$?"
 	if [ "$ret" != "0" ]; then
 		echo "got fetch command failed unexpectedly" >&2