diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt index c73b62f5e1ced76d783dcd5e7aef64016ca1fb4c..39c64105a61a3743da0c8c3b04ee31106090cfa7 100644 --- a/Documentation/technical/pack-protocol.txt +++ b/Documentation/technical/pack-protocol.txt @@ -338,7 +338,8 @@ during a prior round. This helps to ensure that at least one common ancestor is found before we give up entirely. Once the 'done' line is read from the client, the server will either -send a final 'ACK obj-id' or it will send a 'NAK'. The server only sends +send a final 'ACK obj-id' or it will send a 'NAK'. 'obj-id' is the object +name of the last commit determined to be common. The server only sends ACK after 'done' if there is at least one common base and multi_ack or multi_ack_detailed is enabled. The server always sends NAK after 'done' if there is no common base found. diff --git a/Documentation/technical/protocol-capabilities.txt b/Documentation/technical/protocol-capabilities.txt index e3e792476e7a6b7554582469b2c5ac172b2f17dd..e17434384724662aabb60d7fceed40a433207608 100644 --- a/Documentation/technical/protocol-capabilities.txt +++ b/Documentation/technical/protocol-capabilities.txt @@ -69,6 +69,24 @@ ends. Without multi_ack the client would have sent that c-b-a chain anyway, interleaved with S-R-Q. +multi_ack_detailed +------------------ +This is an extension of multi_ack that permits client to better +understand the server's in-memory state. See pack-protocol.txt, +section "Packfile Negotiation" for more information. + +no-done +------- +This capability should only be used with the smart HTTP protocol. If +multi_ack_detailed and no-done are both present, then the sender is +free to immediately send a pack following its first "ACK obj-id ready" +message. + +Without no-done in the smart HTTP protocol, the server session would +end and the client has to make another trip to send "done" before +the server can send the pack. no-done removes the last round and +thus slightly reduces latency. + thin-pack --------- diff --git a/fetch-pack.c b/fetch-pack.c index 90fdd49821a1d6d3e104124444e37ac4b9b03fa2..f061f1fe85ea20549f860c4bf37980941f480833 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -439,7 +439,8 @@ static int find_common(struct fetch_pack_args *args, } strbuf_release(&req_buf); - consume_shallow_list(args, fd[0]); + if (!got_ready || !no_done) + consume_shallow_list(args, fd[0]); while (flushes || multi_ack) { int ack = get_ack(fd[0], result_sha1); if (ack) { diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh index adf215a1937cf2ab2049e3e942497860e49d67cb..3ae9092f5c2511e075c1bf6c215ea773f738f1f9 100755 --- a/t/t5537-fetch-shallow.sh +++ b/t/t5537-fetch-shallow.sh @@ -173,31 +173,4 @@ EOF ) ' -if test -n "$NO_CURL" -o -z "$GIT_TEST_HTTPD"; then - say 'skipping remaining tests, git built without http support' - test_done -fi - -. "$TEST_DIRECTORY"/lib-httpd.sh -start_httpd - -test_expect_success 'clone http repository' ' - git clone --bare --no-local shallow "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && - git clone $HTTPD_URL/smart/repo.git clone && - ( - cd clone && - git fsck && - git log --format=%s origin/master >actual && - cat <expect && -7 -6 -5 -4 -3 -EOF - test_cmp expect actual - ) -' - -stop_httpd test_done diff --git a/t/t5539-fetch-http-shallow.sh b/t/t5539-fetch-http-shallow.sh new file mode 100755 index 0000000000000000000000000000000000000000..94553e103968433aa55fd882a3006b375999759e --- /dev/null +++ b/t/t5539-fetch-http-shallow.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +test_description='fetch/clone from a shallow clone over http' + +. ./test-lib.sh + +if test -n "$NO_CURL"; then + skip_all='skipping test, git built without http support' + test_done +fi + +. "$TEST_DIRECTORY"/lib-httpd.sh +start_httpd + +commit() { + echo "$1" >tracked && + git add tracked && + git commit -m "$1" +} + +test_expect_success 'setup shallow clone' ' + commit 1 && + commit 2 && + commit 3 && + commit 4 && + commit 5 && + commit 6 && + commit 7 && + git clone --no-local --depth=5 .git shallow && + git config --global transfer.fsckObjects true +' + +test_expect_success 'clone http repository' ' + git clone --bare --no-local shallow "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git clone $HTTPD_URL/smart/repo.git clone && + ( + cd clone && + git fsck && + git log --format=%s origin/master >actual && + cat <expect && +7 +6 +5 +4 +3 +EOF + test_cmp expect actual + ) +' + +# This test is tricky. We need large enough "have"s that fetch-pack +# will put pkt-flush in between. Then we need a "have" the server +# does not have, it'll send "ACK %s ready" +test_expect_success 'no shallow lines after receiving ACK ready' ' + ( + cd shallow && + for i in $(test_seq 15) + do + git checkout --orphan unrelated$i && + test_commit unrelated$i && + git push -q "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \ + refs/heads/unrelated$i:refs/heads/unrelated$i && + git push -q ../clone/.git \ + refs/heads/unrelated$i:refs/heads/unrelated$i || + exit 1 + done && + git checkout master && + test_commit new && + git push "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" master + ) && + ( + cd clone && + git checkout --orphan newnew && + test_commit new-too && + GIT_TRACE_PACKET="$TRASH_DIRECTORY/trace" git fetch --depth=2 && + grep "fetch-pack< ACK .* ready" ../trace && + ! grep "fetch-pack> done" ../trace + ) +' + +stop_httpd +test_done diff --git a/t/t5540-http-push.sh b/t/t5540-http-push-webdav.sh similarity index 100% rename from t/t5540-http-push.sh rename to t/t5540-http-push-webdav.sh diff --git a/t/t5541-http-push.sh b/t/t5541-http-push-smart.sh similarity index 100% rename from t/t5541-http-push.sh rename to t/t5541-http-push-smart.sh diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch-dumb.sh similarity index 100% rename from t/t5550-http-fetch.sh rename to t/t5550-http-fetch-dumb.sh diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch-smart.sh similarity index 100% rename from t/t5551-http-fetch.sh rename to t/t5551-http-fetch-smart.sh