about summary refs log tree commit diff
path: root/third_party/git/t/t7701-repack-unpack-unreachable.sh
blob: 48261ba0805cd21e64bdf471f2835a7075782a6c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/bin/sh

test_description='git repack works correctly'

. ./test-lib.sh

fsha1=
csha1=
tsha1=

test_expect_success '-A with -d option leaves unreachable objects unpacked' '
	echo content > file1 &&
	git add . &&
	test_tick &&
	git commit -m initial_commit &&
	# create a transient branch with unique content
	git checkout -b transient_branch &&
	echo more content >> file1 &&
	# record the objects created in the database for file, commit, tree
	fsha1=$(git hash-object file1) &&
	test_tick &&
	git commit -a -m more_content &&
	csha1=$(git rev-parse HEAD^{commit}) &&
	tsha1=$(git rev-parse HEAD^{tree}) &&
	git checkout master &&
	echo even more content >> file1 &&
	test_tick &&
	git commit -a -m even_more_content &&
	# delete the transient branch
	git branch -D transient_branch &&
	# pack the repo
	git repack -A -d -l &&
	# verify objects are packed in repository
	test 3 = $(git verify-pack -v -- .git/objects/pack/*.idx |
		   egrep "^($fsha1|$csha1|$tsha1) " |
		   sort | uniq | wc -l) &&
	git show $fsha1 &&
	git show $csha1 &&
	git show $tsha1 &&
	# now expire the reflog, while keeping reachable ones but expiring
	# unreachables immediately
	test_tick &&
	sometimeago=$(( $test_tick - 10000 )) &&
	git reflog expire --expire=$sometimeago --expire-unreachable=$test_tick --all &&
	# and repack
	git repack -A -d -l &&
	# verify objects are retained unpacked
	test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
		   egrep "^($fsha1|$csha1|$tsha1) " |
		   sort | uniq | wc -l) &&
	git show $fsha1 &&
	git show $csha1 &&
	git show $tsha1
'

compare_mtimes ()
{
	read tref &&
	while read t; do
		test "$tref" = "$t" || return 1
	done
}

test_expect_success '-A without -d option leaves unreachable objects packed' '
	fsha1path=$(echo "$fsha1" | sed -e "s|\(..\)|\1/|") &&
	fsha1path=".git/objects/$fsha1path" &&
	csha1path=$(echo "$csha1" | sed -e "s|\(..\)|\1/|") &&
	csha1path=".git/objects/$csha1path" &&
	tsha1path=$(echo "$tsha1" | sed -e "s|\(..\)|\1/|") &&
	tsha1path=".git/objects/$tsha1path" &&
	git branch transient_branch $csha1 &&
	git repack -a -d -l &&
	test ! -f "$fsha1path" &&
	test ! -f "$csha1path" &&
	test ! -f "$tsha1path" &&
	test 1 = $(ls -1 .git/objects/pack/pack-*.pack | wc -l) &&
	packfile=$(ls .git/objects/pack/pack-*.pack) &&
	git branch -D transient_branch &&
	test_tick &&
	git repack -A -l &&
	test ! -f "$fsha1path" &&
	test ! -f "$csha1path" &&
	test ! -f "$tsha1path" &&
	git show $fsha1 &&
	git show $csha1 &&
	git show $tsha1
'

test_expect_success 'unpacked objects receive timestamp of pack file' '
	tmppack=".git/objects/pack/tmp_pack" &&
	ln "$packfile" "$tmppack" &&
	git repack -A -l -d &&
	test-tool chmtime --get "$tmppack" "$fsha1path" "$csha1path" "$tsha1path" \
		> mtimes &&
	compare_mtimes < mtimes
'

test_expect_success 'do not bother loosening old objects' '
	obj1=$(echo one | git hash-object -w --stdin) &&
	obj2=$(echo two | git hash-object -w --stdin) &&
	pack1=$(echo $obj1 | git pack-objects .git/objects/pack/pack) &&
	pack2=$(echo $obj2 | git pack-objects .git/objects/pack/pack) &&
	git prune-packed &&
	git cat-file -p $obj1 &&
	git cat-file -p $obj2 &&
	test-tool chmtime =-86400 .git/objects/pack/pack-$pack2.pack &&
	git repack -A -d --unpack-unreachable=1.hour.ago &&
	git cat-file -p $obj1 &&
	test_must_fail git cat-file -p $obj2
'

test_expect_success 'keep packed objects found only in index' '
	echo my-unique-content >file &&
	git add file &&
	git commit -m "make it reachable" &&
	git gc &&
	git reset HEAD^ &&
	git reflog expire --expire=now --all &&
	git add file &&
	test-tool chmtime =-86400 .git/objects/pack/* &&
	git gc --prune=1.hour.ago &&
	git cat-file blob :file
'

test_expect_success 'repack -k keeps unreachable packed objects' '
	# create packed-but-unreachable object
	sha1=$(echo unreachable-packed | git hash-object -w --stdin) &&
	pack=$(echo $sha1 | git pack-objects .git/objects/pack/pack) &&
	git prune-packed &&

	# -k should keep it
	git repack -adk &&
	git cat-file -p $sha1 &&

	# and double check that without -k it would have been removed
	git repack -ad &&
	test_must_fail git cat-file -p $sha1
'

test_expect_success 'repack -k packs unreachable loose objects' '
	# create loose unreachable object
	sha1=$(echo would-be-deleted-loose | git hash-object -w --stdin) &&
	objpath=.git/objects/$(echo $sha1 | sed "s,..,&/,") &&
	test_path_is_file $objpath &&

	# and confirm that the loose object goes away, but we can
	# still access it (ergo, it is packed)
	git repack -adk &&
	test_path_is_missing $objpath &&
	git cat-file -p $sha1
'

test_done