|  | 
|  | 1 | +#!/bin/sh | 
|  | 2 | + | 
|  | 3 | +test_description='verify that push respects `pack.usePathWalk`' | 
|  | 4 | + | 
|  | 5 | +TEST_PASSES_SANITIZE_LEAK=true | 
|  | 6 | +. ./test-lib.sh | 
|  | 7 | +. "$TEST_DIRECTORY"/lib-pack.sh | 
|  | 8 | + | 
|  | 9 | +test_expect_success 'setup bare repository and clone' ' | 
|  | 10 | +	git init --bare -b main bare.git && | 
|  | 11 | +	git --git-dir=bare.git config receive.unpackLimit 0 && | 
|  | 12 | +	git --git-dir bare.git commit-tree -m initial $EMPTY_TREE >head_oid && | 
|  | 13 | +	git --git-dir bare.git update-ref refs/heads/main $(cat head_oid) && | 
|  | 14 | +	git clone --bare bare.git clone.git | 
|  | 15 | +' | 
|  | 16 | +test_expect_success 'avoid reusing deltified objects' ' | 
|  | 17 | +	# construct two commits, one containing a file with the hex digits | 
|  | 18 | +	# repeated 16 times, the next reducing that to 8 times. The crucial | 
|  | 19 | +	# part is that the blob of the second commit is deltified _really_ | 
|  | 20 | +	# badly and it is therefore easy to detect if a `git push` reused that | 
|  | 21 | +	# delta. | 
|  | 22 | +	x="0123456789abcdef" && | 
|  | 23 | +	printf "$x$x$x$x$x$x$x$x" >x128 && | 
|  | 24 | +	printf "$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x" >x256 && | 
|  | 25 | +
 | 
|  | 26 | +	pack=clone.git/objects/pack/pack-tmp.pack && | 
|  | 27 | +	pack_header 2 >$pack && | 
|  | 28 | +
 | 
|  | 29 | +	# add x256 as a non-deltified object, using an uncompressed zlib stream | 
|  | 30 | +	# for simplicity | 
|  | 31 | +	# 060 = OBJ_BLOB << 4, 0200 = size larger than 15, | 
|  | 32 | +	# 0 = lower 4 bits of size, 020 = bits 5-9 of size (size = 256) | 
|  | 33 | +	printf "\260\020" >>$pack && | 
|  | 34 | +	# Uncompressed zlib stream always starts with 0170 1 1, followed | 
|  | 35 | +	# by two bytes encoding the size, little endian, then two bytes with | 
|  | 36 | +	# the bitwise-complement of that size, then the payload, and then the | 
|  | 37 | +	# Adler32 checksum. For some reason, the checksum is in big-endian | 
|  | 38 | +	# format. | 
|  | 39 | +	printf "\170\001\001\0\001\377\376" >>$pack && | 
|  | 40 | +	cat x256 >>$pack && | 
|  | 41 | +	# Manually-computed Adler32 checksum: 0xd7ae4621 | 
|  | 42 | +	printf "\327\256\106\041" >>$pack && | 
|  | 43 | +
 | 
|  | 44 | +	# add x128 as a very badly deltified object | 
|  | 45 | +	# 0120 = OBJ_OFS_DELTA << 4, 0200 = total size larger than 15, | 
|  | 46 | +	# 4 = lower 4 bits of size, 030 = bits 5-9 of size | 
|  | 47 | +	# (size = 128 * 3 + 2 + 2) | 
|  | 48 | +	printf "\344\030" >>$pack && | 
|  | 49 | +	# 0415 = size (i.e. the relative negative offset) of the previous | 
|  | 50 | +	# object (x256, used as base object) | 
|  | 51 | +	# encoded as 0200 | ((0415 >> 7) - 1), 0415 & 0177 | 
|  | 52 | +	printf "\201\015" >>$pack && | 
|  | 53 | +	# Uncompressed zlib stream, as before, size = 2 + 2 + 128 * 3 (i.e. | 
|  | 54 | +	# 0604) | 
|  | 55 | +	printf "\170\001\001\204\001\173\376" >>$pack && | 
|  | 56 | +	# base object size = 0400 (encoded as 0200 | (0400 & 0177), | 
|  | 57 | +	# 0400 >> 7) | 
|  | 58 | +	printf "\200\002" >>$pack && | 
|  | 59 | +	# object size = 0200 (encoded as 0200 | (0200 & 0177), 0200 >> 7 | 
|  | 60 | +	printf "\200\001" >>$pack && | 
|  | 61 | +	# massively badly-deltified object: copy every single byte individually | 
|  | 62 | +	# 0200 = copy, 1 = use 1 byte to encode the offset (counter), | 
|  | 63 | +	# 020 = use 1 byte to encode the size (1) | 
|  | 64 | +	printf "$(printf "\\\\221\\\\%03o\\\\001" $(test_seq 0 127))" >>$pack && | 
|  | 65 | +	# Manually-computed Adler32 checksum: 0x99c369c4 | 
|  | 66 | +	printf "\231\303\151\304" >>$pack && | 
|  | 67 | +
 | 
|  | 68 | +	pack_trailer $pack && | 
|  | 69 | +	git index-pack -v $pack && | 
|  | 70 | +
 | 
|  | 71 | +	oid256=$(git hash-object x256) && | 
|  | 72 | +	printf "100755 blob $oid256\thex\n" >tree && | 
|  | 73 | +	tree_oid="$(git --git-dir=clone.git mktree <tree)" && | 
|  | 74 | +	commit_oid=$(git --git-dir=clone.git commit-tree \ | 
|  | 75 | +		-p $(git --git-dir=clone.git rev-parse main) \ | 
|  | 76 | +		-m 256 $tree_oid) && | 
|  | 77 | +
 | 
|  | 78 | +	oid128=$(git hash-object x128) && | 
|  | 79 | +	printf "100755 blob $oid128\thex\n" >tree && | 
|  | 80 | +	tree_oid="$(git --git-dir=clone.git mktree <tree)" && | 
|  | 81 | +	commit_oid=$(git --git-dir=clone.git commit-tree \ | 
|  | 82 | +		-p $commit_oid \ | 
|  | 83 | +		-m 128 $tree_oid) && | 
|  | 84 | +
 | 
|  | 85 | +	# Verify that the on-disk size of the delta object is suboptimal in the | 
|  | 86 | +	# clone (see below why 18 bytes or smaller is the optimal size): | 
|  | 87 | +	git index-pack --verify-stat clone.git/objects/pack/pack-*.pack >verify && | 
|  | 88 | +	size="$(sed -n "s/^$oid128 blob *\([^ ]*\).*/\1/p" <verify)" && | 
|  | 89 | +	test $size -gt 18 && | 
|  | 90 | +
 | 
|  | 91 | +	git --git-dir=clone.git update-ref refs/heads/main $commit_oid && | 
|  | 92 | +	git --git-dir=clone.git -c pack.usePathWalk=true push origin main && | 
|  | 93 | +	git index-pack --verify-stat bare.git/objects/pack/pack-*.pack >verify && | 
|  | 94 | +	size="$(sed -n "s/^$oid128 blob *\([^ ]*\).*/\1/p" <verify)" && | 
|  | 95 | +	# The on-disk size of the delta object should be smaller than, or equal | 
|  | 96 | +	# to, 18 bytes, as that would be the size if storing the payload | 
|  | 97 | +	# uncompressed: | 
|  | 98 | +	#   3 bytes: 0170 01 01 | 
|  | 99 | +	# + 2 bytes: zlib stream size | 
|  | 100 | +	# + 2 bytes: but-wise complement of the zlib stream size | 
|  | 101 | +	# + 7 bytes: payload | 
|  | 102 | +	#   (= 2 bytes for the size of tbe base object | 
|  | 103 | +	#    + 2 bytes for the size of the delta command | 
|  | 104 | +	#    + 3 bytes for the copy command) | 
|  | 105 | +	# + 2 + 2 bytes: Adler32 checksum | 
|  | 106 | +	test $size -le 18 | 
|  | 107 | +' | 
|  | 108 | + | 
|  | 109 | +test_done | 
0 commit comments