Git development
 help / color / mirror / Atom feed
From: Patrick Steinhardt <ps@pks.im>
To: Kristofer Karlsson via GitGitGadget <gitgitgadget@gmail.com>
Cc: git@vger.kernel.org,
	Johannes Schindelin <johannes.schindelin@gmx.de>,
	Kristofer Karlsson <krka@spotify.com>
Subject: Re: [PATCH 2/2] t5608: assert that the packs involved really are that large
Date: Fri, 6 Nov 2026 15:54:32 +0100	[thread overview]
Message-ID: <au3qKLWlM45rByWg@pks.im> (raw)
In-Reply-To: <6c6abee65cb3987978b982e69f227e408c0bf408.1793969476.git.gitgitgadget@gmail.com>

On Fri, Nov 06, 2026 at 12:51:16PM +0000, Kristofer Karlsson via GitGitGadget wrote:
> From: Kristofer Karlsson <krka@spotify.com>
> 
> t5608 was added in ca31f0b5c2 (Add an (optional, since expensive) test
> for >2gb clones, 2009-03-06) to construct a repository larger than 2GB
> and clone it.  It already anticipated that the setup might stop doing
> what it is meant to do: "Should that break in the future, e.g. when
> pack v4 becomes default, there is a commented-out call to
> test-genrandom which can be substituted".
> 
> It did break, silently, with d9545c7f46 (fast-import: implement unpack
> limit, 2016-04-25).  The setup writes only 24 objects, which is below
> the default fastimport.unpackLimit of 100, so fast-import does not
> keep its pack but turns it into loose objects.  Since the blobs
> compress very well, the repository has less than 10MB of loose
> objects, and the bare clone merely copies those.  Only the file://
> clone still deals with a pack larger than 2GB, because the sending
> side generates a new pack from the loose objects.
> 
> The ">4GB object" tests added in 4b220cafbe (t5608: add regression
> test for >4GB object clone, 2026-05-08) have a similar problem.  They
> are meant to cover a fix in both index-pack and unpack-objects, but
> "git clone" always keeps the received pack, so setting
> fetch.unpackLimit in the unpack-objects variant has no effect, and
> both tests use index-pack.

So this test in particular never exercised what it was designed to?

> Nothing noticed any of this, because the tests only check that the
> commands succeed.  Add assertions on what each test relies on, so
> that it fails when its setup no longer does what it is meant to:
> 
>  - the pack created by the setup, and the packs of both clones, are
>    larger than 2GB;
> 
>  - the synthesized pack with the >4GB object, and the pack written by
>    the index-pack clone, are larger than 4GB;
> 
>  - the unpack-objects variant really runs unpack-objects, as seen in
>    its trace2 output.

Makes sense.

> Some of these assertions fail with the tests as they are, so fix them:
> 
>  - Set fastimport.unpackLimit=0 in the setup.  fast-import then
>    keeps its pack regardless of how few objects it contains, so the
>    repository, and the bare clone that copies it, have a pack larger
>    than 2GB again.
> 
>  - In the unpack-objects variant, use "git fetch" into an empty
>    repository instead of "git clone".  Unlike clone, fetch honors
>    fetch.unpackLimit, so with five objects and a limit of 100 the
>    received pack really is passed to unpack-objects.

And the preceding patch fixes a third assertion that we'd otherwise have
seen fail here, I assume?

> As a bonus, keeping the fast-import pack also makes the test cheaper,
> because unpack-objects no longer hashes and compresses all of the 2GB
> of data a second time.  Locally, the time spent in the setup is
> roughly reduced from 80 to 40 seconds.  The test runs in all CI jobs
> via GIT_TEST_CLONE_2GB, and is among the slowest tests there.

Nice.

> diff --git a/t/t5608-clone-2gb.sh b/t/t5608-clone-2gb.sh
> index 5d56debf1c..9d7152486e 100755
> --- a/t/t5608-clone-2gb.sh
> +++ b/t/t5608-clone-2gb.sh
> @@ -9,12 +9,28 @@ then
>  	test_done
>  fi
>  
> +size_2gb=2147483648
> +size_4gb=4294967296
> +
> +# The tests below are only meaningful if the packs involved really are
> +# that large, so check it explicitly instead of trusting the setup.
> +test_has_pack_larger_than () {
> +	max=$(test-tool path-utils file-size "$1"/*.pack | sort -n | tail -n 1) &&
> +	max=${max:-0} &&
> +	if test "$max" -le "$2"
> +	then
> +		echo >&2 "largest pack in '$1' is $max bytes, expected more than $2" &&
> +		return 1
> +	fi
> +}
> +
>  test_expect_success 'setup' '
>  	git init 2gb-repo &&
>  	(
>  		cd 2gb-repo &&
>  		git config pack.compression 0 &&
>  		git config pack.depth 0 &&
> +		git config fastimport.unpackLimit 0 &&
>  		blobsize=$((100*1024*1024)) &&
>  		blobcount=$((2*1024*1024*1024/$blobsize+1)) &&
>  		i=1 &&
> @@ -39,14 +55,20 @@ test_expect_success 'setup' '
>  	)
>  '
>  
> +test_expect_success 'setup produces a pack larger than 2GB' '
> +	test_has_pack_larger_than 2gb-repo/.git/objects/pack $size_2gb
> +'

Nit, not worth a reroll: I would have folded this into the test itself.

> @@ -59,24 +81,29 @@ test_expect_success SIZE_T_IS_64BIT,EXPENSIVE 'set up repo with >4GB object' '
>  		4gb-repo/objects/pack/test.pack) &&
>  	git -C 4gb-repo index-pack objects/pack/test.pack &&
>  	git -C 4gb-repo update-ref refs/heads/main $head_oid &&
> -	git -C 4gb-repo symbolic-ref HEAD refs/heads/main
> +	git -C 4gb-repo symbolic-ref HEAD refs/heads/main &&
> +	test_has_pack_larger_than 4gb-repo/objects/pack $size_4gb
>  '
>  
> -test_expect_success SIZE_T_IS_64BIT,EXPENSIVE 'clone >4GB object via unpack-objects' '
> -	test_when_finished rm -rf 4gb-clone-unpack &&
> +test_expect_success SIZE_T_IS_64BIT,EXPENSIVE 'fetch >4GB object via unpack-objects' '
> +	test_when_finished rm -rf 4gb-fetch-unpack &&
>  	# The synthesized pack has five objects, so a large unpack limit keeps
> -	# fetch-pack on the unpack-objects path.
> -	git -c fetch.unpackLimit=100 clone --bare \
> -		"file://$(pwd)/4gb-repo" 4gb-clone-unpack &&
> +	# fetch-pack on the unpack-objects path.  This needs "fetch", as
> +	# "clone" always keeps the received pack.

This is a bit of a surprise to me, I thought that it would apply to both
git-clone(1) and git-fetch(1). Did you by any chance check whether this
is intentional or whteher it's another bug?

> +	git init --bare 4gb-fetch-unpack &&
> +	GIT_TRACE2_EVENT="$(pwd)/trace-unpack" \
> +		git -C 4gb-fetch-unpack -c fetch.unpackLimit=100 fetch \
> +		"file://$(pwd)/4gb-repo" main:refs/heads/main &&
> +	test_subcommand_flex git unpack-objects <trace-unpack &&
>  
> -	# Verify the large blob survived the clone by comparing its OID
> -	# between source and clone.  We cannot use "cat-file -s" because
> +	# Verify the large blob survived the fetch by comparing its OID
> +	# between source and destination.  We cannot use "cat-file -s" because
>  	# object_info.sizep is still unsigned long, which truncates >4GB
>  	# sizes on Windows.  OID equality proves content integrity since
> -	# the clone already verified checksums via index-pack/unpack-objects.
> +	# the fetch already verified checksums via unpack-objects.
>  	source_blob=$(git -C 4gb-repo rev-parse main^:file) &&
> -	clone_blob=$(git -C 4gb-clone-unpack rev-parse main^:file) &&
> -	test "$source_blob" = "$clone_blob"
> +	fetched_blob=$(git -C 4gb-fetch-unpack rev-parse main^:file) &&
> +	test "$source_blob" = "$fetched_blob"
>  '

Other than that this looks good to me, thanks.

Patrick

  reply	other threads:[~2026-11-06 14:54 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-06 12:51 [PATCH 0/2] t5608: assert that the packs involved really are that large Kristofer Karlsson via GitGitGadget
2026-11-06 12:51 ` [PATCH 1/2] unpack-objects: pass the size of a streamed blob as size_t Kristofer Karlsson via GitGitGadget
2026-11-06 12:51 ` [PATCH 2/2] t5608: assert that the packs involved really are that large Kristofer Karlsson via GitGitGadget
2026-11-06 14:54   ` Patrick Steinhardt [this message]
2026-11-06 15:12     ` Kristofer Karlsson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=au3qKLWlM45rByWg@pks.im \
    --to=ps@pks.im \
    --cc=git@vger.kernel.org \
    --cc=gitgitgadget@gmail.com \
    --cc=johannes.schindelin@gmx.de \
    --cc=krka@spotify.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox