summaryrefslogtreecommitdiff
path: root/t/t2030-unresolve-info.sh
blob: 2d8c70b03a50e9ca082f7343d78dbcf6ad456159 (plain)
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#!/bin/sh
 
test_description='undoing resolution'
 
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
. ./test-lib.sh
 
check_resolve_undo () {
	msg=$1
	shift
	while case $# in
	0)	break ;;
	1|2|3)	die "Bug in check-resolve-undo test" ;;
	esac
	do
		path=$1
		shift
		for stage in 1 2 3
		do
			sha1=$1
			shift
			case "$sha1" in
			'') continue ;;
			esac
			sha1=$(git rev-parse --verify "$sha1")
			printf "100644 %s %s\t%s\n" $sha1 $stage $path
		done
	done >"$msg.expect" &&
	git ls-files --resolve-undo >"$msg.actual" &&
	test_cmp "$msg.expect" "$msg.actual"
}
 
prime_resolve_undo () {
	git reset --hard &&
	git checkout second^0 &&
	test_tick &&
	test_must_fail git merge third^0 &&
	echo merge does not leave anything &&
	check_resolve_undo empty &&
	echo different >fi/le &&
	git add fi/le &&
	echo resolving records &&
	check_resolve_undo recorded fi/le initial:fi/le second:fi/le third:fi/le
}
 
test_expect_success setup '
	mkdir fi &&
	printf "a\0a" >binary &&
	git add binary &&
	test_commit initial fi/le first &&
	git branch side &&
	git branch another &&
	printf "a\0b" >binary &&
	git add binary &&
	test_commit second fi/le second &&
	git checkout side &&
	test_commit third fi/le third &&
	git branch add-add &&
	git checkout another &&
	test_commit fourth fi/le fourth &&
	git checkout add-add &&
	test_commit fifth add-differently &&
	git checkout main
'
 
test_expect_success 'add records switch clears' '
	prime_resolve_undo &&
	test_tick &&
	git commit -m merged &&
	echo committing keeps &&
	check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
	git checkout second^0 &&
	echo switching clears &&
	check_resolve_undo cleared
'
 
test_expect_success 'rm records reset clears' '
	prime_resolve_undo &&
	test_tick &&
	git commit -m merged &&
	echo committing keeps &&
	check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
 
	echo merge clears upfront &&
	test_must_fail git merge fourth^0 &&
	check_resolve_undo nuked &&
 
	git rm -f fi/le &&
	echo resolving records &&
	check_resolve_undo recorded fi/le initial:fi/le HEAD:fi/le fourth:fi/le &&
 
	git reset --hard &&
	echo resetting discards &&
	check_resolve_undo discarded
'
 
test_expect_success 'plumbing clears' '
	prime_resolve_undo &&
	test_tick &&
	git commit -m merged &&
	echo committing keeps &&
	check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
 
	echo plumbing clear &&
	git update-index --clear-resolve-undo &&
	check_resolve_undo cleared
'
 
test_expect_success 'add records checkout -m undoes' '
	prime_resolve_undo &&
	git diff HEAD &&
	git checkout --conflict=merge fi/le &&
	echo checkout used the record and removed it &&
	check_resolve_undo removed &&
	echo the index and the work tree is unmerged again &&
	git diff >actual &&
	grep "^++<<<<<<<" actual
'
 
test_expect_success 'unmerge with plumbing' '
	prime_resolve_undo &&
	git update-index --unresolve fi/le &&
	git ls-files -u >actual &&
	test_line_count = 3 actual
'
 
test_expect_success 'rerere and rerere forget' '
	mkdir .git/rr-cache &&
	prime_resolve_undo &&
	echo record the resolution &&
	git rerere &&
	rerere_id=$(cd .git/rr-cache && echo */postimage) &&
	rerere_id=${rerere_id%/postimage} &&
	test -f .git/rr-cache/$rerere_id/postimage &&
	git checkout -m fi/le &&
	echo resurrect the conflict &&
	grep "^=======" fi/le &&
	echo reresolve the conflict &&
	git rerere &&
	test "z$(cat fi/le)" = zdifferent &&
	echo register the resolution again &&
	git add fi/le &&
	check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
	test -z "$(git ls-files -u)" &&
	git rerere forget fi/le &&
	! test -f .git/rr-cache/$rerere_id/postimage &&
	tr "\0" "\n" <.git/MERGE_RR >actual &&
	echo "$rerere_id	fi/le" >expect &&
	test_cmp expect actual
'
 
test_expect_success 'rerere and rerere forget (subdirectory)' '
	rm -fr .git/rr-cache &&
	mkdir .git/rr-cache &&
	prime_resolve_undo &&
	echo record the resolution &&
	(cd fi && git rerere) &&
	rerere_id=$(cd .git/rr-cache && echo */postimage) &&
	rerere_id=${rerere_id%/postimage} &&
	test -f .git/rr-cache/$rerere_id/postimage &&
	(cd fi && git checkout -m le) &&
	echo resurrect the conflict &&
	grep "^=======" fi/le &&
	echo reresolve the conflict &&
	(cd fi && git rerere) &&
	test "z$(cat fi/le)" = zdifferent &&
	echo register the resolution again &&
	(cd fi && git add le) &&
	check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
	test -z "$(git ls-files -u)" &&
	(cd fi && git rerere forget le) &&
	! test -f .git/rr-cache/$rerere_id/postimage &&
	tr "\0" "\n" <.git/MERGE_RR >actual &&
	echo "$rerere_id	fi/le" >expect &&
	test_cmp expect actual
'
 
test_expect_success 'rerere forget (binary)' '
	git checkout -f side &&
	test_commit --printf binary binary "a\0c" &&
	test_must_fail git merge second &&
	git rerere forget binary
'
 
test_expect_success 'rerere forget (add-add conflict)' '
	git checkout -f main &&
	echo main >add-differently &&
	git add add-differently &&
	git commit -m "add differently" &&
	test_must_fail git merge fifth &&
	git rerere forget add-differently 2>actual &&
	test_i18ngrep "no remembered" actual
'
 
test_expect_success 'resolve-undo keeps blobs from gc' '
	git checkout -f main &&
 
	# First make sure we do not have any cruft left in the object store
	git repack -a -d &&
	git prune --expire=now &&
	git prune-packed &&
	git gc --prune=now &&
	git fsck --unreachable >cruft &&
	test_must_be_empty cruft &&
 
	# Now add three otherwise unreferenced blob objects to the index
	git reset --hard &&
	B1=$(echo "resolve undo test data 1" | git hash-object -w --stdin) &&
	B2=$(echo "resolve undo test data 2" | git hash-object -w --stdin) &&
	B3=$(echo "resolve undo test data 3" | git hash-object -w --stdin) &&
	git update-index --add --index-info <<-EOF &&
	100644 $B1 1	frotz
	100644 $B2 2	frotz
	100644 $B3 3	frotz
	EOF
 
	# These three blob objects are reachable (only) from the index
	git fsck --unreachable >cruft &&
	test_must_be_empty cruft &&
	# and they should be protected from GC
	git gc --prune=now &&
	git cat-file -e $B1 &&
	git cat-file -e $B2 &&
	git cat-file -e $B3 &&
 
	# Now resolve the conflicted path
	B0=$(echo "resolve undo test data 0" | git hash-object -w --stdin) &&
	git update-index --add --cacheinfo 100644,$B0,frotz &&
 
	# These three blob objects are now reachable only from the resolve-undo
	git fsck --unreachable >cruft &&
	test_must_be_empty cruft &&
 
	# and they should survive GC
	git gc --prune=now &&
	git cat-file -e $B0 &&
	git cat-file -e $B1 &&
	git cat-file -e $B2 &&
	git cat-file -e $B3 &&
 
	# Now we switch away, which nukes resolve-undo, and
	# blobs B0..B3 would become dangling.  fsck should
	# notice that they are now unreachable.
	git checkout -f side &&
	git fsck --unreachable >cruft &&
	sort cruft >actual &&
	sort <<-EOF >expect &&
	unreachable blob $B0
	unreachable blob $B1
	unreachable blob $B2
	unreachable blob $B3
	EOF
	test_cmp expect actual &&
 
	# And they should go away when gc runs.
	git gc --prune=now &&
	git fsck --unreachable >cruft &&
	test_must_be_empty cruft &&
 
	test_must_fail git cat-file -e $B0 &&
	test_must_fail git cat-file -e $B1 &&
	test_must_fail git cat-file -e $B2 &&
	test_must_fail git cat-file -e $B3
'
 
test_done