Sync with 2.18.2
[git] / t / t7700-repack.sh
1 #!/bin/sh
2
3 test_description='git repack works correctly'
4
5 . ./test-lib.sh
6
7 commit_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
13 test_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
44 test_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
60 test_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
76 test_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
96 test_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
112 test_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
132 test_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
157 test_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
176 test_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
193 test_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
205 test_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
224 test_done
225