mirror of
https://github.com/git/git
synced 2024-08-25 10:45:59 +00:00
![Johan Herland](/assets/img/avatar_default.png)
quickfetch() calls rev-list to check whether the objects we are about to fetch are already present in the repo (if so, we can skip the object fetch). However, when there are many (~1000) refs to be fetched, the rev-list command line grows larger than the maximum command line size on some systems (32K in Windows). This causes rev-list to fail, making quickfetch() return non-zero, which unnecessarily triggers the transport machinery. This somehow causes fetch to fail with an exit code. By using the --stdin option to rev-list (and feeding the object list to its standard input), we prevent the overflow of the rev-list command line, which causes quickfetch(), and subsequently the overall fetch, to succeed. However, using rev-list --stdin is not entirely straightforward: rev-list terminates immediately when encountering an unknown object, which can trigger SIGPIPE if we are still writing object's to its standard input. We therefore temporarily ignore SIGPIPE so that the fetch process is not terminated. The patch also contains a testcase to verify the fix (note that before the patch, the testcase would only fail on msysGit). Signed-off-by: Johan Herland <johan@herland.net> Improved-by: Johannes Sixt <j6t@kdbg.org> Improved-by: Alex Riesen <raa.lkml@gmail.com> Tested-by: Peter Krefting <peter@softwolves.pp.se> Signed-off-by: Junio C Hamano <gitster@pobox.com>
143 lines
2.5 KiB
Bash
Executable file
143 lines
2.5 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
test_description='test quickfetch from local'
|
|
|
|
. ./test-lib.sh
|
|
|
|
test_expect_success setup '
|
|
|
|
test_tick &&
|
|
echo ichi >file &&
|
|
git add file &&
|
|
git commit -m initial &&
|
|
|
|
cnt=$( (
|
|
git count-objects | sed -e "s/ *objects,.*//"
|
|
) ) &&
|
|
test $cnt -eq 3
|
|
'
|
|
|
|
test_expect_success 'clone without alternate' '
|
|
|
|
(
|
|
mkdir cloned &&
|
|
cd cloned &&
|
|
git init-db &&
|
|
git remote add -f origin ..
|
|
) &&
|
|
cnt=$( (
|
|
cd cloned &&
|
|
git count-objects | sed -e "s/ *objects,.*//"
|
|
) ) &&
|
|
test $cnt -eq 3
|
|
'
|
|
|
|
test_expect_success 'further commits in the original' '
|
|
|
|
test_tick &&
|
|
echo ni >file &&
|
|
git commit -a -m second &&
|
|
|
|
cnt=$( (
|
|
git count-objects | sed -e "s/ *objects,.*//"
|
|
) ) &&
|
|
test $cnt -eq 6
|
|
'
|
|
|
|
test_expect_success 'copy commit and tree but not blob by hand' '
|
|
|
|
git rev-list --objects HEAD |
|
|
git pack-objects --stdout |
|
|
(
|
|
cd cloned &&
|
|
git unpack-objects
|
|
) &&
|
|
|
|
cnt=$( (
|
|
cd cloned &&
|
|
git count-objects | sed -e "s/ *objects,.*//"
|
|
) ) &&
|
|
test $cnt -eq 6
|
|
|
|
blob=$(git rev-parse HEAD:file | sed -e "s|..|&/|") &&
|
|
test -f "cloned/.git/objects/$blob" &&
|
|
rm -f "cloned/.git/objects/$blob" &&
|
|
|
|
cnt=$( (
|
|
cd cloned &&
|
|
git count-objects | sed -e "s/ *objects,.*//"
|
|
) ) &&
|
|
test $cnt -eq 5
|
|
|
|
'
|
|
|
|
test_expect_success 'quickfetch should not leave a corrupted repository' '
|
|
|
|
(
|
|
cd cloned &&
|
|
git fetch
|
|
) &&
|
|
|
|
cnt=$( (
|
|
cd cloned &&
|
|
git count-objects | sed -e "s/ *objects,.*//"
|
|
) ) &&
|
|
test $cnt -eq 6
|
|
|
|
'
|
|
|
|
test_expect_success 'quickfetch should not copy from alternate' '
|
|
|
|
(
|
|
mkdir quickclone &&
|
|
cd quickclone &&
|
|
git init-db &&
|
|
(cd ../.git/objects && pwd) >.git/objects/info/alternates &&
|
|
git remote add origin .. &&
|
|
git fetch -k -k
|
|
) &&
|
|
obj_cnt=$( (
|
|
cd quickclone &&
|
|
git count-objects | sed -e "s/ *objects,.*//"
|
|
) ) &&
|
|
pck_cnt=$( (
|
|
cd quickclone &&
|
|
git count-objects -v | sed -n -e "/packs:/{
|
|
s/packs://
|
|
p
|
|
q
|
|
}"
|
|
) ) &&
|
|
origin_master=$( (
|
|
cd quickclone &&
|
|
git rev-parse origin/master
|
|
) ) &&
|
|
echo "loose objects: $obj_cnt, packfiles: $pck_cnt" &&
|
|
test $obj_cnt -eq 0 &&
|
|
test $pck_cnt -eq 0 &&
|
|
test z$origin_master = z$(git rev-parse master)
|
|
|
|
'
|
|
|
|
test_expect_success 'quickfetch should handle ~1000 refs (on Windows)' '
|
|
|
|
git gc &&
|
|
head=$(git rev-parse HEAD) &&
|
|
branchprefix="$head refs/heads/branch" &&
|
|
for i in 0 1 2 3 4 5 6 7 8 9; do
|
|
for j in 0 1 2 3 4 5 6 7 8 9; do
|
|
for k in 0 1 2 3 4 5 6 7 8 9; do
|
|
echo "$branchprefix$i$j$k" >> .git/packed-refs
|
|
done
|
|
done
|
|
done &&
|
|
(
|
|
cd cloned &&
|
|
git fetch &&
|
|
git fetch
|
|
)
|
|
|
|
'
|
|
|
|
test_done
|