about summary refs log tree commit diff
path: root/third_party/git/t/t6501-freshen-objects.sh
blob: 033871ee5f35c1a143aec6d2b30c5116bf3f94f5 (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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/bin/sh
#
# This test covers the handling of objects which might have old
# mtimes in the filesystem (because they were used previously)
# and are just now becoming referenced again.
#
# We're going to do two things that are a little bit "fake" to
# help make our simulation easier:
#
#   1. We'll turn off reflogs. You can still run into
#      problems with reflogs on, but your objects
#      don't get pruned until both the reflog expiration
#      has passed on their references, _and_ they are out
#      of prune's expiration period. Dropping reflogs
#      means we only have to deal with one variable in our tests,
#      but the results generalize.
#
#   2. We'll use a temporary index file to create our
#      works-in-progress. Most workflows would mention
#      referenced objects in the index, which prune takes
#      into account. However, many operations don't. For
#      example, a partial commit with "git commit foo"
#      will use a temporary index. Or they may not need
#      an index at all (e.g., creating a new commit
#      to refer to an existing tree).

test_description='check pruning of dependent objects'
. ./test-lib.sh

# We care about reachability, so we do not want to use
# the normal test_commit, which creates extra tags.
add () {
	echo "$1" >"$1" &&
	git add "$1"
}
commit () {
	test_tick &&
	add "$1" &&
	git commit -m "$1"
}

maybe_repack () {
	if test -n "$repack"; then
		git repack -ad
	fi
}

for repack in '' true; do
	title=${repack:+repack}
	title=${title:-loose}

	test_expect_success "make repo completely empty ($title)" '
		rm -rf .git &&
		git init
	'

	test_expect_success "disable reflogs ($title)" '
		git config core.logallrefupdates false &&
		git reflog expire --expire=all --all
	'

	test_expect_success "setup basic history ($title)" '
		commit base
	'

	test_expect_success "create and abandon some objects ($title)" '
		git checkout -b experiment &&
		commit abandon &&
		maybe_repack &&
		git checkout master &&
		git branch -D experiment
	'

	test_expect_success "simulate time passing ($title)" '
		test-tool chmtime --get -86400 $(find .git/objects -type f)
	'

	test_expect_success "start writing new commit with old blob ($title)" '
		tree=$(
			GIT_INDEX_FILE=index.tmp &&
			export GIT_INDEX_FILE &&
			git read-tree HEAD &&
			add unrelated &&
			add abandon &&
			git write-tree
		)
	'

	test_expect_success "simultaneous gc ($title)" '
		git gc --prune=12.hours.ago
	'

	test_expect_success "finish writing out commit ($title)" '
		commit=$(echo foo | git commit-tree -p HEAD $tree) &&
		git update-ref HEAD $commit
	'

	# "abandon" blob should have been rescued by reference from new tree
	test_expect_success "repository passes fsck ($title)" '
		git fsck
	'

	test_expect_success "abandon objects again ($title)" '
		git reset --hard HEAD^ &&
		test-tool chmtime --get -86400 $(find .git/objects -type f)
	'

	test_expect_success "start writing new commit with same tree ($title)" '
		tree=$(
			GIT_INDEX_FILE=index.tmp &&
			export GIT_INDEX_FILE &&
			git read-tree HEAD &&
			add abandon &&
			add unrelated &&
			git write-tree
		)
	'

	test_expect_success "simultaneous gc ($title)" '
		git gc --prune=12.hours.ago
	'

	# tree should have been refreshed by write-tree
	test_expect_success "finish writing out commit ($title)" '
		commit=$(echo foo | git commit-tree -p HEAD $tree) &&
		git update-ref HEAD $commit
	'
done

test_expect_success 'do not complain about existing broken links (commit)' '
	cat >broken-commit <<-\EOF &&
	tree 0000000000000000000000000000000000000001
	parent 0000000000000000000000000000000000000002
	author whatever <whatever@example.com> 1234 -0000
	committer whatever <whatever@example.com> 1234 -0000

	some message
	EOF
	commit=$(git hash-object -t commit -w broken-commit) &&
	git gc 2>stderr &&
	verbose git cat-file -e $commit &&
	test_must_be_empty stderr
'

test_expect_success 'do not complain about existing broken links (tree)' '
	cat >broken-tree <<-\EOF &&
	100644 blob 0000000000000000000000000000000000000003	foo
	EOF
	tree=$(git mktree --missing <broken-tree) &&
	git gc 2>stderr &&
	git cat-file -e $tree &&
	test_must_be_empty stderr
'

test_expect_success 'do not complain about existing broken links (tag)' '
	cat >broken-tag <<-\EOF &&
	object 0000000000000000000000000000000000000004
	type commit
	tag broken
	tagger whatever <whatever@example.com> 1234 -0000

	this is a broken tag
	EOF
	tag=$(git hash-object -t tag -w broken-tag) &&
	git gc 2>stderr &&
	git cat-file -e $tag &&
	test_must_be_empty stderr
'

test_done