Skip to content

Commit

Permalink
Merge branch 'nd/http-fetch-shallow-fix'
Browse files Browse the repository at this point in the history
Attempting to deepen a shallow repository by fetching over smart
HTTP transport failed in the protocol exchange, when no-done
extension was used.  The fetching side waited for the list of
shallow boundary commits after the sending end stopped talking to
it.

* nd/http-fetch-shallow-fix:
  t5537: move http tests out to t5539
  fetch-pack: fix deepen shallow over smart http with no-done cap
  protocol-capabilities.txt: document no-done
  protocol-capabilities.txt: refer multi_ack_detailed back to pack-protocol.txt
  pack-protocol.txt: clarify 'obj-id' in the last ACK after 'done'
  test: rename http fetch and push test files
  • Loading branch information
gitster committed Feb 27, 2014
2 parents 0f9e62e + 0232852 commit 2de3478
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 29 deletions.
3 changes: 2 additions & 1 deletion Documentation/technical/pack-protocol.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
18 changes: 18 additions & 0 deletions Documentation/technical/protocol-capabilities.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
---------

Expand Down
3 changes: 2 additions & 1 deletion fetch-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
27 changes: 0 additions & 27 deletions t/t5537-fetch-shallow.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 <<EOF >expect &&
7
6
5
4
3
EOF
test_cmp expect actual
)
'

stop_httpd
test_done
82 changes: 82 additions & 0 deletions t/t5539-fetch-http-shallow.sh
Original file line number Diff line number Diff line change
@@ -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 <<EOF >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
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 2de3478

Please sign in to comment.