summaryrefslogtreecommitdiffstats
path: root/t/t1423-ref-backend.sh
blob: fd47d77e8e2904cb314831508759c8fc9141c081 (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
269
270
271
272
273
274
275
276
277
278
279
280
#!/bin/sh

test_description='Test reference backend URIs'

. ./test-lib.sh

# Run a git command with the provided reference storage. Reset the backend
# post running the command.
# Usage: run_with_uri <repo> <backend> <uri> <cmd>
#   <repo> is the relative path to the repo to run the command in.
#   <backend> is the original ref storage of the repo.
#   <uri> is the new URI to be set for the ref storage.
#   <cmd> is the git subcommand to be run in the repository.
#   <via> if 'config', set the backend via the 'extensions.refStorage' config.
#         if 'env', set the backend via the 'GIT_REFERENCE_BACKEND' env.
run_with_uri () {
	repo=$1 &&
	backend=$2 &&
	uri=$3 &&
	cmd=$4 &&
	via=$5 &&

	git -C "$repo" config set core.repositoryformatversion 1 &&
	if test "$via" = "env"
	then
		test_env GIT_REFERENCE_BACKEND="$uri" git -C "$repo" $cmd
	elif test "$via" = "config"
	then
		git -C "$repo" config set extensions.refStorage "$uri" &&
		git -C "$repo" $cmd &&
		git -C "$repo" config set extensions.refStorage "$backend"
	fi
}

# Test a repository with a given reference storage by running and comparing
# 'git refs list' before and after setting the new reference backend. If
# err_msg is set, expect the command to fail and grep for the provided err_msg.
# Usage: run_with_uri <repo> <backend> <uri> <cmd>
#   <repo> is the relative path to the repo to run the command in.
#   <backend> is the original ref storage of the repo.
#   <uri> is the new URI to be set for the ref storage.
#   <via> if 'config', set the backend via the 'extensions.refStorage' config.
#         if 'env', set the backend via the 'GIT_REFERENCE_BACKEND' env.
#   <err_msg> (optional) if set, check if 'git-refs(1)' failed with the provided msg.
test_refs_backend () {
	repo=$1 &&
	backend=$2 &&
	uri=$3 &&
	via=$4 &&
	err_msg=$5 &&


	if test -n "$err_msg";
	then
		if test "$via" = "env"
		then
			test_env GIT_REFERENCE_BACKEND="$uri" test_must_fail git -C "$repo" refs list 2>err
		elif test "$via" = "config"
		then
			git -C "$repo" config set extensions.refStorage "$uri" &&
			test_must_fail git -C "$repo" refs list 2>err &&
			test_grep "$err_msg" err
		fi
	else
		git -C "$repo" refs list >expect &&
		run_with_uri "$repo" "$backend" "$uri" "refs list" "$via">actual &&
		test_cmp expect actual
	fi
}

# Verify that the expected files are present in the gitdir and the refsdir.
# Usage: verify_files_exist <gitdir> <refdir>
#   <gitdir> is the path for the gitdir.
#   <refdir> is the path for the refdir.
verify_files_exist () {
	gitdir=$1 &&
	refdir=$2 &&

	# verify that the stubs were added to the $GITDIR.
	echo "repository uses alternate refs storage" >expect &&
	test_cmp expect $gitdir/refs/heads &&
	echo "ref: refs/heads/.invalid" >expect &&
	test_cmp expect $gitdir/HEAD

	# verify that backend specific files exist.
	case "$GIT_DEFAULT_REF_FORMAT" in
	files)
		test_path_is_dir $refdir/refs/heads &&
		test_path_is_file $refdir/HEAD;;
	reftable)
		test_path_is_dir $refdir/reftable &&
		test_path_is_file $refdir/reftable/tables.list;;
	*)
		BUG "unhandled ref format $GIT_DEFAULT_REF_FORMAT";;
	esac
}

methods="config env"
for method in $methods
do

test_expect_success "$method: URI is invalid" '
	test_when_finished "rm -rf repo" &&
	git init repo &&
	test_refs_backend repo files "reftable@/home/reftable" "$method" \
		"invalid value for ${SQ}extensions.refstorage${SQ}"
'

test_expect_success "$method: URI ends with colon" '
	test_when_finished "rm -rf repo" &&
	git init repo &&
	test_refs_backend repo files "reftable:" "$method" \
		"invalid value for ${SQ}extensions.refstorage${SQ}"
'

test_expect_success "$method: unknown reference backend" '
	test_when_finished "rm -rf repo" &&
	git init repo &&
	test_refs_backend repo files "db://.git" "$method" \
		"invalid value for ${SQ}extensions.refstorage${SQ}"
'

ref_formats="files reftable"
for from_format in $ref_formats
do

for to_format in $ref_formats
do
	if test "$from_format" = "$to_format"
	then
		continue
	fi


	for dir in "$(pwd)/repo/.git" "."
	do

		test_expect_success "$method: read from $to_format backend, $dir dir" '
			test_when_finished "rm -rf repo" &&
			git init --ref-format=$from_format repo &&
			(
				cd repo &&
				test_commit 1 &&
				test_commit 2 &&
				test_commit 3 &&

				git refs migrate --dry-run --ref-format=$to_format >out &&
				BACKEND_PATH="$dir/$(sed "s/.* ${SQ}.git\/\(.*\)${SQ}/\1/" out)" &&
				test_refs_backend . $from_format "$to_format://$BACKEND_PATH" "$method"
			)
		'

		test_expect_success "$method: write to $to_format backend, $dir dir" '
			test_when_finished "rm -rf repo" &&
			git init --ref-format=$from_format repo &&
			(
				cd repo &&
				test_commit 1 &&
				test_commit 2 &&
				test_commit 3 &&

				git refs migrate --dry-run --ref-format=$to_format >out &&
				BACKEND_PATH="$dir/$(sed "s/.* ${SQ}.git\/\(.*\)${SQ}/\1/" out)" &&

				test_refs_backend . $from_format "$to_format://$BACKEND_PATH" "$method" &&

				git refs list >expect &&
				run_with_uri . "$from_format" "$to_format://$BACKEND_PATH" \
					"tag -d 1" "$method" &&
				git refs list >actual &&
				test_cmp expect actual &&

				git refs list | grep -v "refs/tags/1" >expect &&
				run_with_uri . "$from_format" "$to_format://$BACKEND_PATH" \
					"refs list" "$method" >actual &&
				test_cmp expect actual
			)
		'

		test_expect_success "$method: with worktree and $to_format backend, $dir dir" '
			test_when_finished "rm -rf repo wt" &&
			git init --ref-format=$from_format repo &&
			(
				cd repo &&
				test_commit 1 &&
				test_commit 2 &&
				test_commit 3 &&

				git refs migrate --dry-run --ref-format=$to_format >out &&
				BACKEND_PATH="$dir/$(sed "s/.* ${SQ}.git\/\(.*\)${SQ}/\1/" out)" &&

				run_with_uri . "$from_format" "$to_format://$BACKEND_PATH" \
					"worktree add ../wt 2" "$method" &&

				run_with_uri . "$from_format" "$to_format://$BACKEND_PATH" \
					"for-each-ref --include-root-refs" "$method" >actual &&
				run_with_uri ../wt "$from_format" "$to_format://$BACKEND_PATH" \
					"for-each-ref --include-root-refs" "$method" >expect &&
				! test_cmp expect actual &&

				run_with_uri . "$from_format" "$to_format://$BACKEND_PATH" \
					"rev-parse 2" "$method" >actual &&
				run_with_uri ../wt "$from_format" "$to_format://$BACKEND_PATH" \
					"rev-parse HEAD" "$method" >expect &&
				test_cmp expect actual
			)
		'
	done # closes dir

	test_expect_success "migrating repository to $to_format with alternate refs directory" '
		test_when_finished "rm -rf repo refdir" &&
		mkdir refdir &&
		GIT_REFERENCE_BACKEND="${from_format}://$(pwd)/refdir" git init repo &&
		(
			cd repo &&

			test_commit 1 &&
			test_commit 2 &&
			test_commit 3 &&

			git refs migrate --ref-format=$to_format &&
			git refs list >out &&
			test_grep "refs/tags/1"	out &&
			test_grep "refs/tags/2"	out &&
			test_grep "refs/tags/3"	out
		)
	'

done # closes to_format
done # closes from_format

done # closes method

test_expect_success 'initializing repository with alt ref directory' '
	test_when_finished "rm -rf repo refdir" &&
	mkdir refdir &&
	BACKEND="$(test_detect_ref_format)://$(pwd)/refdir" &&
	GIT_REFERENCE_BACKEND=$BACKEND git init repo &&
	verify_files_exist repo/.git refdir &&
	(
		cd repo &&

		git config get extensions.refstorage >actual &&
		echo $BACKEND >expect &&
		test_cmp expect actual &&

		test_commit 1 &&
		test_commit 2 &&
		test_commit 3 &&
		git refs list >out &&
		test_grep "refs/tags/1"	out &&
		test_grep "refs/tags/2"	out &&
		test_grep "refs/tags/3"	out
	)
'

test_expect_success 'cloning repository with alt ref directory' '
	test_when_finished "rm -rf source repo refdir" &&
	mkdir refdir &&

	git init source &&
	test_commit -C source 1 &&
	test_commit -C source 2 &&
	test_commit -C source 3 &&

	BACKEND="$(test_detect_ref_format)://$(pwd)/refdir" &&
	GIT_REFERENCE_BACKEND=$BACKEND git clone source repo &&

	git -C repo config get extensions.refstorage >actual &&
	echo $BACKEND >expect &&
	test_cmp expect actual &&

	verify_files_exist repo/.git refdir &&

	git -C source for-each-ref refs/tags/ >expect &&
	git -C repo for-each-ref refs/tags/ >actual &&
	test_cmp expect actual
'

test_done