Skip to content

Commit eabe6a7

Browse files
committed
Merge branch 'pt/promisor-lazy-fetch-no-recurse' into jch
The mechanism to avoid recursive lazy-fetch from promisor remotes was not propagated properly to child "git fetch" processes, which has been corrected. Comments? * pt/promisor-lazy-fetch-no-recurse: promisor-remote: prevent lazy-fetch recursion in child fetch
2 parents 3e42c15 + f584f9d commit eabe6a7

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

promisor-remote.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ static int fetch_objects(struct repository *repo,
4242
child.in = -1;
4343
if (repo != the_repository)
4444
prepare_other_repo_env(&child.env, repo->gitdir);
45+
/*
46+
* Prevent the child's index-pack from recursing back into
47+
* fetch_objects() when resolving REF_DELTA bases it does not
48+
* have. With noop negotiation the server should never need
49+
* to send such deltas, so a depth-2 fetch would not help.
50+
*/
51+
strvec_pushf(&child.env, "%s=1", NO_LAZY_FETCH_ENVIRONMENT);
4552
strvec_pushl(&child.args, "-c", "fetch.negotiationAlgorithm=noop",
4653
"fetch", remote_name, "--no-tags",
4754
"--no-write-fetch-head", "--recurse-submodules=no",

t/t5616-partial-clone.sh

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,66 @@ test_expect_success PERL_TEST_HELPERS 'tolerate server sending REF_DELTA against
908908
! test -e "$HTTPD_ROOT_PATH/one-time-script"
909909
'
910910

911+
test_expect_success PERL_TEST_HELPERS 'lazy-fetch of REF_DELTA with missing base does not recurse' '
912+
SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" &&
913+
rm -rf "$SERVER" repo &&
914+
test_create_repo "$SERVER" &&
915+
test_config -C "$SERVER" uploadpack.allowfilter 1 &&
916+
test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 &&
917+
918+
# Create a commit with 2 blobs to be used as delta base and content.
919+
for i in $(test_seq 10)
920+
do
921+
echo "this is a line" >>"$SERVER/foo.txt" &&
922+
echo "this is another line" >>"$SERVER/bar.txt" || return 1
923+
done &&
924+
git -C "$SERVER" add foo.txt bar.txt &&
925+
git -C "$SERVER" commit -m initial &&
926+
BLOB_FOO=$(git -C "$SERVER" rev-parse HEAD:foo.txt) &&
927+
BLOB_BAR=$(git -C "$SERVER" rev-parse HEAD:bar.txt) &&
928+
929+
# Partial clone with blob:none. The client has commits and
930+
# trees but no blobs.
931+
test_config -C "$SERVER" protocol.version 2 &&
932+
git -c protocol.version=2 clone --no-checkout \
933+
--filter=blob:none $HTTPD_URL/one_time_script/server repo &&
934+
935+
# Sanity check: client does not have either blob locally.
936+
git -C repo rev-list --objects --ignore-missing \
937+
-- $BLOB_FOO >objlist &&
938+
test_line_count = 0 objlist &&
939+
940+
# Craft a thin pack where BLOB_FOO is a REF_DELTA against
941+
# BLOB_BAR. Since the client has neither blob (blob:none
942+
# filter), the delta base will be missing. This simulates a
943+
# misbehaving server that sends REF_DELTA against an object
944+
# the client does not have.
945+
test-tool -C "$SERVER" pack-deltas --num-objects=1 >thin.pack <<-EOF &&
946+
REF_DELTA $BLOB_FOO $BLOB_BAR
947+
EOF
948+
949+
replace_packfile thin.pack &&
950+
951+
# Trigger a lazy fetch for BLOB_FOO. The child fetch spawned
952+
# by fetch_objects() receives our crafted thin pack. Its
953+
# index-pack encounters the missing delta base (BLOB_BAR) and
954+
# tries to lazy-fetch it via promisor_remote_get_direct().
955+
#
956+
# With the fix: fetch_objects() propagates GIT_NO_LAZY_FETCH=1
957+
# to the child, so the depth-2 fetch is blocked and we see the
958+
# "lazy fetching disabled" warning. The object cannot be
959+
# resolved, so cat-file fails.
960+
#
961+
# Without the fix: the depth-2 fetch would proceed, potentially
962+
# recursing unboundedly with a persistently misbehaving server.
963+
test_must_fail git -C repo -c protocol.version=2 \
964+
cat-file -p $BLOB_FOO 2>err &&
965+
test_grep "lazy fetching disabled" err &&
966+
967+
# Ensure that the one-time-script was used.
968+
! test -e "$HTTPD_ROOT_PATH/one-time-script"
969+
'
970+
911971
# DO NOT add non-httpd-specific tests here, because the last part of this
912972
# test script is only executed when httpd is available and enabled.
913973

0 commit comments

Comments
 (0)