summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
authorLibravatar Jonathan Tan <jonathantanmy@google.com>2018-07-02 15:08:43 -0700
committerLibravatar Junio C Hamano <gitster@pobox.com>2018-07-03 14:57:44 -0700
commitcf1e7c07705eb21c30d0ee414810e7bc8fdf7d82 (patch)
treedb2515073445cc5b9fdb89f6472f91ed8505a59c /t
parentfetch-pack: implement ref-in-want (diff)
downloadtgif-cf1e7c07705eb21c30d0ee414810e7bc8fdf7d82.tar.xz
fetch-pack: write shallow, then check connectivity
When fetching, connectivity is checked after the shallow file is updated. There are 2 issues with this: (1) the connectivity check is only performed up to ancestors of existing refs (which is not thorough enough if we were deepening an existing ref in the first place), and (2) there is no rollback of the shallow file if the connectivity check fails. To solve (1), update the connectivity check to check the ancestry chain completely in the case of a deepening fetch by refraining from passing "--not --all" when invoking rev-list in connected.c. To solve (2), have fetch_pack() perform its own connectivity check before updating the shallow file. To support existing use cases in which "git fetch-pack" is used to download objects without much regard as to the connectivity of the resulting objects with respect to the existing repository, the connectivity check is only done if necessary (that is, the fetch is not a clone, and the fetch involves shallow/deepen functionality). "git fetch" still performs its own connectivity check, preserving correctness but sometimes performing redundant work. This redundancy is mitigated by the fact that fetch_pack() reports if it has performed a connectivity check itself, and if the transport supports connect or stateless-connect, it will bubble up that report so that "git fetch" knows not to perform the connectivity check in such a case. This was noticed when a user tried to deepen an existing repository by fetching with --no-shallow from a server that did not send all necessary objects - the connectivity check as run by "git fetch" succeeded, but a subsequent "git fsck" failed. Signed-off-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 't')
-rwxr-xr-xt/t5537-fetch-shallow.sh43
1 files changed, 43 insertions, 0 deletions
diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh
index df8d2f095a..a7afb66049 100755
--- a/t/t5537-fetch-shallow.sh
+++ b/t/t5537-fetch-shallow.sh
@@ -186,4 +186,47 @@ EOF
test_cmp expect actual
'
+. "$TEST_DIRECTORY"/lib-httpd.sh
+start_httpd
+
+REPO="$HTTPD_DOCUMENT_ROOT_PATH/repo"
+
+test_expect_success 'shallow fetches check connectivity before writing shallow file' '
+ rm -rf "$REPO" client &&
+
+ git init "$REPO" &&
+ test_commit -C "$REPO" one &&
+ test_commit -C "$REPO" two &&
+ test_commit -C "$REPO" three &&
+
+ git init client &&
+
+ # Use protocol v2 to ensure that shallow information is sent exactly
+ # once by the server, since we are planning to manipulate it.
+ git -C "$REPO" config protocol.version 2 &&
+ git -C client config protocol.version 2 &&
+
+ git -C client fetch --depth=2 "$HTTPD_URL/one_time_sed/repo" master:a_branch &&
+
+ # Craft a situation in which the server sends back an unshallow request
+ # with an empty packfile. This is done by refetching with a shorter
+ # depth (to ensure that the packfile is empty), and overwriting the
+ # shallow line in the response with the unshallow line we want.
+ printf "s/0034shallow %s/0036unshallow %s/" \
+ "$(git -C "$REPO" rev-parse HEAD)" \
+ "$(git -C "$REPO" rev-parse HEAD^)" \
+ >"$HTTPD_ROOT_PATH/one-time-sed" &&
+ test_must_fail git -C client fetch --depth=1 "$HTTPD_URL/one_time_sed/repo" \
+ master:a_branch &&
+
+ # Ensure that the one-time-sed script was used.
+ ! test -e "$HTTPD_ROOT_PATH/one-time-sed" &&
+
+ # Ensure that the resulting repo is consistent, despite our failure to
+ # fetch.
+ git -C client fsck
+'
+
+stop_httpd
+
test_done