1#!/bin/sh
2
3test_description='git repack works correctly'
4
5. ./test-lib.sh
6
7commit_and_pack() {
8 test_commit "$@" >/dev/null &&
9 SHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&
10 echo pack-${SHA1}.pack
11}
12
13test_expect_success 'objects in packs marked .keep are not repacked' '
14 echo content1 > file1 &&
15 echo content2 > file2 &&
16 git add . &&
17 test_tick &&
18 git commit -m initial_commit &&
19 # Create two packs
20 # The first pack will contain all of the objects except one
21 git rev-list --objects --all | grep -v file2 |
22 git pack-objects pack > /dev/null &&
23 # The second pack will contain the excluded object
24 packsha1=$(git rev-list --objects --all | grep file2 |
25 git pack-objects pack) &&
26 >pack-$packsha1.keep &&
27 objsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |
28 sed -e "s/^\([0-9a-f]\{40\}\).*/\1/") &&
29 mv pack-* .git/objects/pack/ &&
30 git repack -A -d -l &&
31 git prune-packed &&
32 for p in .git/objects/pack/*.idx; do
33 idx=$(basename $p)
34 test "pack-$packsha1.idx" = "$idx" && continue
35 if git verify-pack -v $p | egrep "^$objsha1"; then
36 found_duplicate_object=1
37 echo "DUPLICATE OBJECT FOUND"
38 break
39 fi
40 done &&
41 test -z "$found_duplicate_object"
42'
43
44test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '
45 # build on $objsha1, $packsha1, and .keep state from previous
46 git repack -Adbl &&
47 test_when_finished "found_duplicate_object=" &&
48 for p in .git/objects/pack/*.idx; do
49 idx=$(basename $p)
50 test "pack-$packsha1.idx" = "$idx" && continue
51 if git verify-pack -v $p | egrep "^$objsha1"; then
52 found_duplicate_object=1
53 echo "DUPLICATE OBJECT FOUND"
54 break
55 fi
56 done &&
57 test "$found_duplicate_object" = 1
58'
59
60test_expect_success 'writing bitmaps via config can duplicate .keep objects' '
61 # build on $objsha1, $packsha1, and .keep state from previous
62 git -c repack.writebitmaps=true repack -Adl &&
63 test_when_finished "found_duplicate_object=" &&
64 for p in .git/objects/pack/*.idx; do
65 idx=$(basename $p)
66 test "pack-$packsha1.idx" = "$idx" && continue
67 if git verify-pack -v $p | egrep "^$objsha1"; then
68 found_duplicate_object=1
69 echo "DUPLICATE OBJECT FOUND"
70 break
71 fi
72 done &&
73 test "$found_duplicate_object" = 1
74'
75
76test_expect_success 'loose objects in alternate ODB are not repacked' '
77 mkdir alt_objects &&
78 echo $(pwd)/alt_objects > .git/objects/info/alternates &&
79 echo content3 > file3 &&
80 objsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&
81 git add file3 &&
82 test_tick &&
83 git commit -m commit_file3 &&
84 git repack -a -d -l &&
85 git prune-packed &&
86 for p in .git/objects/pack/*.idx; do
87 if git verify-pack -v $p | egrep "^$objsha1"; then
88 found_duplicate_object=1
89 echo "DUPLICATE OBJECT FOUND"
90 break
91 fi
92 done &&
93 test -z "$found_duplicate_object"
94'
95
96test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '
97 mkdir alt_objects/pack &&
98 mv .git/objects/pack/* alt_objects/pack &&
99 git repack -a &&
100 myidx=$(ls -1 .git/objects/pack/*.idx) &&
101 test -f "$myidx" &&
102 for p in alt_objects/pack/*.idx; do
103 git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
104 done | while read sha1 rest; do
105 if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
106 echo "Missing object in local pack: $sha1"
107 return 1
108 fi
109 done
110'
111
112test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '
113 rm -f .git/objects/pack/* &&
114 echo new_content >> file1 &&
115 git add file1 &&
116 test_tick &&
117 git commit -m more_content &&
118 git repack &&
119 git repack -a -d &&
120 myidx=$(ls -1 .git/objects/pack/*.idx) &&
121 test -f "$myidx" &&
122 for p in alt_objects/pack/*.idx; do
123 git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
124 done | while read sha1 rest; do
125 if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
126 echo "Missing object in local pack: $sha1"
127 return 1
128 fi
129 done
130'
131
132test_expect_success 'packed obs in alternate ODB kept pack are repacked' '
133 # swap the .keep so the commit object is in the pack with .keep
134 for p in alt_objects/pack/*.pack
135 do
136 base_name=$(basename $p .pack) &&
137 if test -f alt_objects/pack/$base_name.keep
138 then
139 rm alt_objects/pack/$base_name.keep
140 else
141 touch alt_objects/pack/$base_name.keep
142 fi
143 done &&
144 git repack -a -d &&
145 myidx=$(ls -1 .git/objects/pack/*.idx) &&
146 test -f "$myidx" &&
147 for p in alt_objects/pack/*.idx; do
148 git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
149 done | while read sha1 rest; do
150 if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
151 echo "Missing object in local pack: $sha1"
152 return 1
153 fi
154 done
155'
156
157test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '
158 rm -f alt_objects/pack/*.keep &&
159 mv .git/objects/pack/* alt_objects/pack/ &&
160 csha1=$(git rev-parse HEAD^{commit}) &&
161 git reset --hard HEAD^ &&
162 test_tick &&
163 git reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&
164 # The pack-objects call on the next line is equivalent to
165 # git repack -A -d without the call to prune-packed
166 git pack-objects --honor-pack-keep --non-empty --all --reflog \
167 --unpack-unreachable </dev/null pack &&
168 rm -f .git/objects/pack/* &&
169 mv pack-* .git/objects/pack/ &&
170 test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
171 egrep "^$csha1 " | sort | uniq | wc -l) &&
172 echo > .git/objects/info/alternates &&
173 test_must_fail git show $csha1
174'
175
176test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '
177 echo $(pwd)/alt_objects > .git/objects/info/alternates &&
178 echo "$csha1" | git pack-objects --non-empty --all --reflog pack &&
179 rm -f .git/objects/pack/* &&
180 mv pack-* .git/objects/pack/ &&
181 # The pack-objects call on the next line is equivalent to
182 # git repack -A -d without the call to prune-packed
183 git pack-objects --honor-pack-keep --non-empty --all --reflog \
184 --unpack-unreachable </dev/null pack &&
185 rm -f .git/objects/pack/* &&
186 mv pack-* .git/objects/pack/ &&
187 test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
188 egrep "^$csha1 " | sort | uniq | wc -l) &&
189 echo > .git/objects/info/alternates &&
190 test_must_fail git show $csha1
191'
192
193test_expect_success 'objects made unreachable by grafts only are kept' '
194 test_tick &&
195 git commit --allow-empty -m "commit 4" &&
196 H0=$(git rev-parse HEAD) &&
197 H1=$(git rev-parse HEAD^) &&
198 H2=$(git rev-parse HEAD^^) &&
199 echo "$H0 $H2" > .git/info/grafts &&
200 git reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&
201 git repack -a -d &&
202 git cat-file -t $H1
203'
204
205test_expect_success 'repack --keep-pack' '
206 test_create_repo keep-pack &&
207 (
208 cd keep-pack &&
209 P1=$(commit_and_pack 1) &&
210 P2=$(commit_and_pack 2) &&
211 P3=$(commit_and_pack 3) &&
212 P4=$(commit_and_pack 4) &&
213 ls .git/objects/pack/*.pack >old-counts &&
214 test_line_count = 4 old-counts &&
215 git repack -a -d --keep-pack $P1 --keep-pack $P4 &&
216 ls .git/objects/pack/*.pack >new-counts &&
217 grep -q $P1 new-counts &&
218 grep -q $P4 new-counts &&
219 test_line_count = 3 new-counts &&
220 git fsck
221 )
222'
223
224test_expect_success 'bitmaps are created by default in bare repos' '
225 git clone --bare .git bare.git &&
226 git -C bare.git repack -ad &&
227 bitmap=$(ls bare.git/objects/pack/*.bitmap) &&
228 test_path_is_file "$bitmap"
229'
230
231test_expect_success 'incremental repack does not complain' '
232 git -C bare.git repack -q 2>repack.err &&
233 test_must_be_empty repack.err
234'
235
236test_expect_success 'bitmaps can be disabled on bare repos' '
237 git -c repack.writeBitmaps=false -C bare.git repack -ad &&
238 bitmap=$(ls bare.git/objects/pack/*.bitmap 2>/dev/null || :) &&
239 test -z "$bitmap"
240'
241
242test_expect_success 'no bitmaps created if .keep files present' '
243 pack=$(ls bare.git/objects/pack/*.pack) &&
244 test_path_is_file "$pack" &&
245 keep=${pack%.pack}.keep &&
246 test_when_finished "rm -f \"\$keep\"" &&
247 >"$keep" &&
248 git -C bare.git repack -ad 2>stderr &&
249 test_must_be_empty stderr &&
250 find bare.git/objects/pack/ -type f -name "*.bitmap" >actual &&
251 test_must_be_empty actual
252'
253
254test_expect_success 'auto-bitmaps do not complain if unavailable' '
255 test_config -C bare.git pack.packSizeLimit 1M &&
256 blob=$(test-tool genrandom big $((1024*1024)) |
257 git -C bare.git hash-object -w --stdin) &&
258 git -C bare.git update-ref refs/tags/big $blob &&
259 git -C bare.git repack -ad 2>stderr &&
260 test_must_be_empty stderr &&
261 find bare.git/objects/pack -type f -name "*.bitmap" >actual &&
262 test_must_be_empty actual
263'
264
265test_done