Skip to content

Commit 67cf2fa

Browse files
committed
Merge branch 'jt/tighten-fetch-proto-v2-response'
"git fetch" was a bit loose in parsing resposes from the other side when talking over the protocol v2. * jt/tighten-fetch-proto-v2-response: fetch-pack: be more precise in parsing v2 response
2 parents abb4824 + 5400b2a commit 67cf2fa

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

fetch-pack.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,18 @@ static int process_acks(struct fetch_negotiator *negotiator,
12481248
reader->status != PACKET_READ_DELIM)
12491249
die(_("error processing acks: %d"), reader->status);
12501250

1251+
/*
1252+
* If an "acknowledgments" section is sent, a packfile is sent if and
1253+
* only if "ready" was sent in this section. The other sections
1254+
* ("shallow-info" and "wanted-refs") are sent only if a packfile is
1255+
* sent. Therefore, a DELIM is expected if "ready" is sent, and a FLUSH
1256+
* otherwise.
1257+
*/
1258+
if (received_ready && reader->status != PACKET_READ_DELIM)
1259+
die(_("expected packfile to be sent after 'ready'"));
1260+
if (!received_ready && reader->status != PACKET_READ_FLUSH)
1261+
die(_("expected no other sections to be sent after no 'ready'"));
1262+
12511263
/* return 0 if no common, 1 if there are common, or 2 if ready */
12521264
return received_ready ? 2 : (received_ack ? 1 : 0);
12531265
}

t/t5702-protocol-v2.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,56 @@ test_expect_success 'push with http:// and a config of v2 does not request v2' '
537537
! grep "git< version 2" log
538538
'
539539

540+
test_expect_success 'when server sends "ready", expect DELIM' '
541+
rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child &&
542+
543+
git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
544+
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one &&
545+
546+
git clone "$HTTPD_URL/smart/http_parent" http_child &&
547+
548+
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two &&
549+
550+
# After "ready" in the acknowledgments section, pretend that a FLUSH
551+
# (0000) was sent instead of a DELIM (0001).
552+
printf "/ready/,$ s/0001/0000/" \
553+
>"$HTTPD_ROOT_PATH/one-time-sed" &&
554+
555+
test_must_fail git -C http_child -c protocol.version=2 \
556+
fetch "$HTTPD_URL/one_time_sed/http_parent" 2> err &&
557+
test_i18ngrep "expected packfile to be sent after .ready." err
558+
'
559+
560+
test_expect_success 'when server does not send "ready", expect FLUSH' '
561+
rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child log &&
562+
563+
git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
564+
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one &&
565+
566+
git clone "$HTTPD_URL/smart/http_parent" http_child &&
567+
568+
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two &&
569+
570+
# Create many commits to extend the negotiation phase across multiple
571+
# requests, so that the server does not send "ready" in the first
572+
# request.
573+
for i in $(test_seq 1 32)
574+
do
575+
test_commit -C http_child c$i
576+
done &&
577+
578+
# After the acknowledgments section, pretend that a DELIM
579+
# (0001) was sent instead of a FLUSH (0000).
580+
printf "/acknowledgments/,$ s/0000/0001/" \
581+
>"$HTTPD_ROOT_PATH/one-time-sed" &&
582+
583+
test_must_fail env GIT_TRACE_PACKET="$(pwd)/log" git -C http_child \
584+
-c protocol.version=2 \
585+
fetch "$HTTPD_URL/one_time_sed/http_parent" 2> err &&
586+
grep "fetch< acknowledgments" log &&
587+
! grep "fetch< ready" log &&
588+
test_i18ngrep "expected no other sections to be sent after no .ready." err
589+
'
540590

541591
stop_httpd
542592

0 commit comments

Comments
 (0)