Raw
1 #!/bin/sh
2
3 test_description='test config file include directives'
4 . ./test-lib.sh
5
6 # Force setup_explicit_git_dir() to run until the end. This is needed
7 # by some tests to make sure real_path() is called on $GIT_DIR. The
8 # caller needs to make sure git commands are run from a subdirectory
9 # though or real_path() will not be called.
10 force_setup_explicit_git_dir() {
11 GIT_DIR="$(pwd)/.git"
12 GIT_WORK_TREE="$(pwd)"
13 export GIT_DIR GIT_WORK_TREE
14 }
15
16 test_expect_success 'include file by absolute path' '
17 echo "[test]one = 1" >one &&
18 echo "[include]path = \"$(pwd)/one\"" >.gitconfig &&
19 echo 1 >expect &&
20 git config test.one >actual &&
21 test_cmp expect actual
22 '
23
24 test_expect_success 'include file by relative path' '
25 echo "[test]one = 1" >one &&
26 echo "[include]path = one" >.gitconfig &&
27 echo 1 >expect &&
28 git config test.one >actual &&
29 test_cmp expect actual
30 '
31
32 test_expect_success 'chained relative paths' '
33 mkdir subdir &&
34 echo "[test]three = 3" >subdir/three &&
35 echo "[include]path = three" >subdir/two &&
36 echo "[include]path = subdir/two" >.gitconfig &&
37 echo 3 >expect &&
38 git config test.three >actual &&
39 test_cmp expect actual
40 '
41
42 test_expect_success 'include paths get tilde-expansion' '
43 echo "[test]one = 1" >one &&
44 echo "[include]path = ~/one" >.gitconfig &&
45 echo 1 >expect &&
46 git config test.one >actual &&
47 test_cmp expect actual
48 '
49
50 test_expect_success 'include options can still be examined' '
51 echo "[test]one = 1" >one &&
52 echo "[include]path = one" >.gitconfig &&
53 echo one >expect &&
54 git config include.path >actual &&
55 test_cmp expect actual
56 '
57
58 test_expect_success 'listing includes option and expansion' '
59 echo "[test]one = 1" >one &&
60 echo "[include]path = one" >.gitconfig &&
61 cat >expect <<-\EOF &&
62 include.path=one
63 test.one=1
64 EOF
65 git config --list >actual.full &&
66 grep -v -e ^core -e ^extensions actual.full >actual &&
67 test_cmp expect actual
68 '
69
70 test_expect_success 'single file lookup does not expand includes by default' '
71 echo "[test]one = 1" >one &&
72 echo "[include]path = one" >.gitconfig &&
73 test_must_fail git config -f .gitconfig test.one &&
74 test_must_fail git config --global test.one &&
75 echo 1 >expect &&
76 git config --includes -f .gitconfig test.one >actual &&
77 test_cmp expect actual
78 '
79
80 test_expect_success 'single file list does not expand includes by default' '
81 echo "[test]one = 1" >one &&
82 echo "[include]path = one" >.gitconfig &&
83 echo "include.path=one" >expect &&
84 git config -f .gitconfig --list >actual &&
85 test_cmp expect actual
86 '
87
88 test_expect_success 'writing config file does not expand includes' '
89 echo "[test]one = 1" >one &&
90 echo "[include]path = one" >.gitconfig &&
91 git config test.two 2 &&
92 echo 2 >expect &&
93 git config --no-includes test.two >actual &&
94 test_cmp expect actual &&
95 test_must_fail git config --no-includes test.one
96 '
97
98 test_expect_success 'config modification does not affect includes' '
99 echo "[test]one = 1" >one &&
100 echo "[include]path = one" >.gitconfig &&
101 git config test.one 2 &&
102 echo 1 >expect &&
103 git config -f one test.one >actual &&
104 test_cmp expect actual &&
105 cat >expect <<-\EOF &&
106 1
107 2
108 EOF
109 git config --get-all test.one >actual &&
110 test_cmp expect actual
111 '
112
113 test_expect_success 'missing include files are ignored' '
114 cat >.gitconfig <<-\EOF &&
115 [include]path = non-existent
116 [test]value = yes
117 EOF
118 echo yes >expect &&
119 git config test.value >actual &&
120 test_cmp expect actual
121 '
122
123 test_expect_success 'absolute includes from command line work' '
124 echo "[test]one = 1" >one &&
125 echo 1 >expect &&
126 git -c include.path="$(pwd)/one" config test.one >actual &&
127 test_cmp expect actual
128 '
129
130 test_expect_success 'relative includes from command line fail' '
131 echo "[test]one = 1" >one &&
132 test_must_fail git -c include.path=one config test.one
133 '
134
135 test_expect_success 'absolute includes from blobs work' '
136 echo "[test]one = 1" >one &&
137 echo "[include]path=$(pwd)/one" >blob &&
138 blob=$(git hash-object -w blob) &&
139 echo 1 >expect &&
140 git config --blob=$blob test.one >actual &&
141 test_cmp expect actual
142 '
143
144 test_expect_success 'relative includes from blobs fail' '
145 echo "[test]one = 1" >one &&
146 echo "[include]path=one" >blob &&
147 blob=$(git hash-object -w blob) &&
148 test_must_fail git config --blob=$blob test.one
149 '
150
151 test_expect_success 'absolute includes from stdin work' '
152 echo "[test]one = 1" >one &&
153 echo 1 >expect &&
154 echo "[include]path=\"$(pwd)/one\"" |
155 git config --file - test.one >actual &&
156 test_cmp expect actual
157 '
158
159 test_expect_success 'relative includes from stdin line fail' '
160 echo "[test]one = 1" >one &&
161 echo "[include]path=one" |
162 test_must_fail git config --file - test.one
163 '
164
165 test_expect_success 'conditional include, both unanchored' '
166 git init foo &&
167 (
168 cd foo &&
169 echo "[includeIf \"gitdir:foo/\"]path=bar" >>.git/config &&
170 echo "[test]one=1" >.git/bar &&
171 echo 1 >expect &&
172 git config test.one >actual &&
173 test_cmp expect actual
174 )
175 '
176
177 test_expect_success 'conditional include, $HOME expansion' '
178 (
179 cd foo &&
180 echo "[includeIf \"gitdir:~/foo/\"]path=bar2" >>.git/config &&
181 echo "[test]two=2" >.git/bar2 &&
182 echo 2 >expect &&
183 git config test.two >actual &&
184 test_cmp expect actual
185 )
186 '
187
188 test_expect_success 'conditional include, full pattern' '
189 (
190 cd foo &&
191 echo "[includeIf \"gitdir:**/foo/**\"]path=bar3" >>.git/config &&
192 echo "[test]three=3" >.git/bar3 &&
193 echo 3 >expect &&
194 git config test.three >actual &&
195 test_cmp expect actual
196 )
197 '
198
199 test_expect_success 'conditional include, relative path' '
200 echo "[includeIf \"gitdir:./foo/.git\"]path=bar4" >>.gitconfig &&
201 echo "[test]four=4" >bar4 &&
202 (
203 cd foo &&
204 echo 4 >expect &&
205 git config test.four >actual &&
206 test_cmp expect actual
207 )
208 '
209
210 test_expect_success 'conditional include, both unanchored, icase' '
211 (
212 cd foo &&
213 echo "[includeIf \"gitdir/i:FOO/\"]path=bar5" >>.git/config &&
214 echo "[test]five=5" >.git/bar5 &&
215 echo 5 >expect &&
216 git config test.five >actual &&
217 test_cmp expect actual
218 )
219 '
220
221 test_expect_success 'conditional include, early config reading' '
222 (
223 cd foo &&
224 echo "[includeIf \"gitdir:foo/\"]path=bar6" >>.git/config &&
225 echo "[test]six=6" >.git/bar6 &&
226 echo 6 >expect &&
227 test-tool config read_early_config test.six >actual &&
228 test_cmp expect actual
229 )
230 '
231
232 test_expect_success 'conditional include with /**/' '
233 REPO=foo/bar/repo &&
234 git init $REPO &&
235 cat >>$REPO/.git/config <<-\EOF &&
236 [includeIf "gitdir:**/foo/**/bar/**"]
237 path=bar7
238 EOF
239 echo "[test]seven=7" >$REPO/.git/bar7 &&
240 echo 7 >expect &&
241 git -C $REPO config test.seven >actual &&
242 test_cmp expect actual
243 '
244
245 test_expect_success SYMLINKS 'conditional include, set up symlinked $HOME' '
246 mkdir real-home &&
247 ln -s real-home home &&
248 (
249 HOME="$TRASH_DIRECTORY/home" &&
250 export HOME &&
251 cd "$HOME" &&
252
253 git init foo &&
254 cd foo &&
255 mkdir sub
256 )
257 '
258
259 test_expect_success SYMLINKS 'conditional include, $HOME expansion with symlinks' '
260 (
261 HOME="$TRASH_DIRECTORY/home" &&
262 export HOME &&
263 cd "$HOME"/foo &&
264
265 echo "[includeIf \"gitdir:~/foo/\"]path=bar2" >>.git/config &&
266 echo "[test]two=2" >.git/bar2 &&
267 echo 2 >expect &&
268 force_setup_explicit_git_dir &&
269 git -C sub config test.two >actual &&
270 test_cmp expect actual
271 )
272 '
273
274 test_expect_success SYMLINKS 'conditional include, relative path with symlinks' '
275 echo "[includeIf \"gitdir:./foo/.git\"]path=bar4" >home/.gitconfig &&
276 echo "[test]four=4" >home/bar4 &&
277 (
278 HOME="$TRASH_DIRECTORY/home" &&
279 export HOME &&
280 cd "$HOME"/foo &&
281
282 echo 4 >expect &&
283 force_setup_explicit_git_dir &&
284 git -C sub config test.four >actual &&
285 test_cmp expect actual
286 )
287 '
288
289 test_expect_success SYMLINKS,!MINGW 'conditional include, gitdir matching symlink' '
290 ln -s foo bar &&
291 (
292 cd bar &&
293 echo "[includeIf \"gitdir:bar/\"]path=bar7" >>.git/config &&
294 echo "[test]seven=7" >.git/bar7 &&
295 echo 7 >expect &&
296 git config test.seven >actual &&
297 test_cmp expect actual
298 )
299 '
300
301 test_expect_success SYMLINKS,!MINGW 'conditional include, gitdir matching symlink, icase' '
302 (
303 cd bar &&
304 echo "[includeIf \"gitdir/i:BAR/\"]path=bar8" >>.git/config &&
305 echo "[test]eight=8" >.git/bar8 &&
306 echo 8 >expect &&
307 git config test.eight >actual &&
308 test_cmp expect actual
309 )
310 '
311
312 test_expect_success 'conditional include, onbranch' '
313 echo "[includeIf \"onbranch:foo-branch\"]path=bar9" >>.git/config &&
314 echo "[test]nine=9" >.git/bar9 &&
315 git checkout -b main &&
316 test_must_fail git config test.nine &&
317 git checkout -b foo-branch &&
318 echo 9 >expect &&
319 git config test.nine >actual &&
320 test_cmp expect actual
321 '
322
323 test_expect_success 'conditional include, onbranch, wildcard' '
324 echo "[includeIf \"onbranch:?oo-*/**\"]path=bar10" >>.git/config &&
325 echo "[test]ten=10" >.git/bar10 &&
326 git checkout -b not-foo-branch/a &&
327 test_must_fail git config test.ten &&
328
329 echo 10 >expect &&
330 git checkout -b foo-branch/a/b/c &&
331 git config test.ten >actual &&
332 test_cmp expect actual &&
333
334 git checkout -b moo-bar/a &&
335 git config test.ten >actual &&
336 test_cmp expect actual
337 '
338
339 test_expect_success 'conditional include, onbranch, implicit /** for /' '
340 echo "[includeIf \"onbranch:foo-dir/\"]path=bar11" >>.git/config &&
341 echo "[test]eleven=11" >.git/bar11 &&
342 git checkout -b not-foo-dir/a &&
343 test_must_fail git config test.eleven &&
344
345 echo 11 >expect &&
346 git checkout -b foo-dir/a/b/c &&
347 git config test.eleven >actual &&
348 test_cmp expect actual
349 '
350
351 test_expect_success 'include cycles are detected' '
352 git init --bare cycle &&
353 git -C cycle --git-dir=. config include.path cycle &&
354 git config -f cycle/cycle include.path config &&
355 test_must_fail git -C cycle --git-dir=. config --get-all test.value 2>stderr &&
356 test_grep "exceeded maximum include depth" stderr
357 '
358
359 test_expect_success 'onbranch with unborn branch' '
360 test_when_finished "rm -rf repo" &&
361 git init repo &&
362 (
363 cd repo &&
364 git config set includeIf.onbranch:"*".path config.inc &&
365 git config set -f .git/config.inc foo.bar baz &&
366 git config get foo.bar
367 )
368 '
369
370 test_expect_success 'onbranch with detached HEAD' '
371 test_when_finished "rm -rf repo" &&
372 git init repo &&
373 (
374 cd repo &&
375 git config set "includeIf.onbranch:*.path" config.inc &&
376 git config set -f .git/config.inc foo.bar baz &&
377 test_commit initial &&
378 git switch --detach HEAD &&
379 test_must_fail git config get foo.bar
380 )
381 '
382
383 test_expect_success 'onbranch without repository' '
384 test_when_finished "rm -f .gitconfig config.inc" &&
385 git config set -f .gitconfig "includeIf.onbranch:**.path" config.inc &&
386 git config set -f config.inc foo.bar baz &&
387 git config get foo.bar &&
388 test_must_fail nongit git config get foo.bar
389 '
390
391 test_expect_success 'onbranch without repository but explicit nonexistent Git directory' '
392 test_when_finished "rm -f .gitconfig config.inc" &&
393 git config set -f .gitconfig "includeIf.onbranch:**.path" config.inc &&
394 git config set -f config.inc foo.bar baz &&
395 git config get foo.bar &&
396 test_must_fail nongit git --git-dir=nonexistent config get foo.bar
397 '
398
399 # worktree: conditional include tests
400
401 test_expect_success 'conditional include, worktree bare repo' '
402 git init --bare wt-bare &&
403 (
404 cd wt-bare &&
405 echo "[includeIf \"worktree:/\"]path=bar-bare" >>config &&
406 echo "[test]wtbare=1" >bar-bare &&
407 test_must_fail git config test.wtbare
408 )
409 '
410
411 test_expect_success 'conditional include, worktree multiple worktrees' '
412 git init wt-multi &&
413 (
414 cd wt-multi &&
415 test_commit initial &&
416 git worktree add -b linked-branch ../wt-linked HEAD &&
417 git worktree add -b prefix-branch ../wt-prefix/linked HEAD
418 ) &&
419 wt_main="$(cd wt-multi && pwd)" &&
420 wt_linked="$(cd wt-linked && pwd)" &&
421 wt_prefix_parent="$(cd wt-prefix && pwd)" &&
422 cat >>wt-multi/.git/config <<-EOF &&
423 [includeIf "worktree:$wt_main"]
424 path = main-config
425 [includeIf "worktree:$wt_linked"]
426 path = linked-config
427 [includeIf "worktree:$wt_prefix_parent/"]
428 path = prefix-config
429 EOF
430 echo "[test]mainvar=main" >wt-multi/.git/main-config &&
431 echo "[test]linkedvar=linked" >wt-multi/.git/linked-config &&
432 echo "[test]prefixvar=prefix" >wt-multi/.git/prefix-config &&
433 echo main >expect &&
434 git -C wt-multi config test.mainvar >actual &&
435 test_cmp expect actual &&
436 test_must_fail git -C wt-multi config test.linkedvar &&
437 test_must_fail git -C wt-multi config test.prefixvar &&
438 echo linked >expect &&
439 git -C wt-linked config test.linkedvar >actual &&
440 test_cmp expect actual &&
441 test_must_fail git -C wt-linked config test.mainvar &&
442 test_must_fail git -C wt-linked config test.prefixvar &&
443 echo prefix >expect &&
444 git -C wt-prefix/linked config test.prefixvar >actual &&
445 test_cmp expect actual &&
446 test_must_fail git -C wt-prefix/linked config test.mainvar &&
447 test_must_fail git -C wt-prefix/linked config test.linkedvar
448 '
449
450 test_expect_success SYMLINKS 'conditional include, worktree resolves symlinks' '
451 mkdir real-wt &&
452 ln -s real-wt link-wt &&
453 git init link-wt/repo &&
454 (
455 cd link-wt/repo &&
456 # repo->worktree resolves symlinks, so use real path in pattern
457 echo "[includeIf \"worktree:**/real-wt/repo\"]path=bar-link" >>.git/config &&
458 echo "[test]wtlink=2" >.git/bar-link &&
459 echo 2 >expect &&
460 git config test.wtlink >actual &&
461 test_cmp expect actual
462 )
463 '
464
465 test_expect_success !CASE_INSENSITIVE_FS 'conditional include, worktree, case sensitive' '
466 git init wt-case &&
467 (
468 cd wt-case &&
469 test_commit initial &&
470 wt_path="$(pwd)" &&
471 wt_upper=$(echo "$wt_path" | tr a-z A-Z) &&
472 echo "[includeIf \"worktree:$wt_upper\"]path=case-inc" >>.git/config &&
473 echo "[test]wtcase=1" >.git/case-inc &&
474 test_must_fail git config test.wtcase
475 )
476 '
477
478 test_expect_success 'conditional include, worktree, icase' '
479 git init wt-icase &&
480 (
481 cd wt-icase &&
482 test_commit initial &&
483 wt_path="$(pwd)" &&
484 wt_upper=$(echo "$wt_path" | tr a-z A-Z) &&
485 echo "[includeIf \"worktree/i:$wt_upper\"]path=icase-inc" >>.git/config &&
486 echo "[test]wticase=1" >.git/icase-inc &&
487 echo 1 >expect &&
488 git config test.wticase >actual &&
489 test_cmp expect actual
490 )
491 '
492
493 # The "worktree" condition cannot match during early config reading
494 # because the repository object is not yet fully initialized and
495 # repo_get_work_tree() returns NULL.
496 test_expect_success 'conditional include, worktree does not match in early config' '
497 git init wt-early &&
498 (
499 cd wt-early &&
500 test_commit initial &&
501 wt_path="$(pwd)" &&
502 echo "[includeIf \"worktree:$wt_path\"]path=early-inc" >>.git/config &&
503 echo "[test]wtearly=1" >.git/early-inc &&
504 test-tool config read_early_config test.wtearly >actual &&
505 test_must_be_empty actual
506 )
507 '
508
509 # Use a loose pattern so the "present in non-worktree cases" check works
510 # for Unix-style absolute paths and Windows paths like D:/a/git/...
511 test_expect_success 'conditional include, worktree without repository' '
512 test_when_finished "rm -f .gitconfig config.inc" &&
513 git config set -f .gitconfig "includeIf.worktree:**.path" config.inc &&
514 git config set -f config.inc foo.bar baz &&
515 git config get foo.bar &&
516 test_must_fail nongit git config get foo.bar
517 '
518
519 test_expect_success 'conditional include, worktree without repository but explicit nonexistent Git directory' '
520 test_when_finished "rm -f .gitconfig config.inc" &&
521 git config set -f .gitconfig "includeIf.worktree:**.path" config.inc &&
522 git config set -f config.inc foo.bar baz &&
523 git config get foo.bar &&
524 test_must_fail nongit git --git-dir=nonexistent config get foo.bar
525 '
526
527 test_done