1#!/bin/sh
2
3test_description='Tests of cwd/prefix/worktree/gitdir setup in all cases'
4
5. ./test-lib.sh
6
7#
8# A few rules for repo setup:
9#
10# 1. GIT_DIR is relative to user's cwd. --git-dir is equivalent to
11# GIT_DIR.
12#
13# 2. .git file is relative to parent directory. .git file is basically
14# symlink in disguise. The directory where .git file points to will
15# become new git_dir.
16#
17# 3. core.worktree is relative to git_dir.
18#
19# 4. GIT_WORK_TREE is relative to user's cwd. --work-tree is
20# equivalent to GIT_WORK_TREE.
21#
22# 5. GIT_WORK_TREE/core.worktree is only effective if GIT_DIR is set
23# Uneffective worktree settings should be warned.
24#
25# 6. Effective GIT_WORK_TREE overrides core.worktree and core.bare
26#
27# 7. Effective core.worktree conflicts with core.bare
28#
29# 8. If GIT_DIR is set but neither worktree nor bare setting is given,
30# original cwd becomes worktree.
31#
32# 9. If .git discovery is done inside a repo, the repo becomes a bare
33# repo. .git discovery is performed if GIT_DIR is not set.
34#
35# 10. If no worktree is available, cwd remains unchanged, prefix is
36# NULL.
37#
38# 11. When user's cwd is outside worktree, cwd remains unchanged,
39# prefix is NULL.
40#
41
42test_repo() {
43 (
44 cd "$1" &&
45 if test -n "$2"; then GIT_DIR="$2" && export GIT_DIR; fi &&
46 if test -n "$3"; then GIT_WORK_TREE="$3" && export GIT_WORK_TREE; fi &&
47 rm -f trace &&
48 GIT_TRACE="`pwd`/trace" git symbolic-ref HEAD >/dev/null &&
49 grep '^setup: ' trace >result &&
50 test_cmp expected result
51 )
52}
53
54# Bit 0 = GIT_WORK_TREE
55# Bit 1 = GIT_DIR
56# Bit 2 = core.worktree
57# Bit 3 = .git is a file
58# Bit 4 = bare repo
59# Case# = encoding of the above 5 bits
60
61#
62# Case #0
63#
64############################################################
65#
66# Input:
67#
68# - GIT_WORK_TREE is not set
69# - GIT_DIR is not set
70# - core.worktree is not set
71# - .git is a directory
72# - core.bare is not set, cwd is outside .git
73#
74# Output:
75#
76# - worktree is .git's parent directory
77# - cwd is at worktree root dir
78# - prefix is calculated
79# - git_dir is set to ".git"
80# - cwd can't be outside worktree
81
82test_expect_success '#0: setup' '
83 unset GIT_DIR GIT_WORK_TREE &&
84 mkdir 0 0/sub &&
85 cd 0 && git init && cd ..
86'
87
88test_expect_success '#0: at root' '
89 cat >0/expected <<EOF &&
90setup: git_dir: .git
91setup: worktree: $TRASH_DIRECTORY/0
92setup: cwd: $TRASH_DIRECTORY/0
93setup: prefix: (null)
94EOF
95 test_repo 0
96'
97
98test_expect_success '#0: in subdir' '
99 cat >0/sub/expected <<EOF &&
100setup: git_dir: .git
101setup: worktree: $TRASH_DIRECTORY/0
102setup: cwd: $TRASH_DIRECTORY/0
103setup: prefix: sub/
104EOF
105 test_repo 0/sub
106'
107
108#
109# case #1
110#
111############################################################
112#
113# Input:
114#
115# - GIT_WORK_TREE is set
116# - GIT_DIR is not set
117# - core.worktree is not set
118# - .git is a directory
119# - core.bare is not set, cwd is outside .git
120#
121# Output:
122#
123# GIT_WORK_TREE is ignored -> #0
124
125test_expect_success '#1: setup' '
126 unset GIT_DIR GIT_WORK_TREE &&
127 mkdir 1 1/sub 1.wt 1.wt/sub 1/wt 1/wt/sub &&
128 cd 1 &&
129 git init &&
130 GIT_WORK_TREE=non-existent &&
131 export GIT_WORK_TREE &&
132 cd ..
133'
134
135test_expect_failure '#1: at root' '
136 cat >1/expected <<EOF &&
137setup: git_dir: .git
138setup: worktree: $TRASH_DIRECTORY/1
139setup: cwd: $TRASH_DIRECTORY/1
140setup: prefix: (null)
141EOF
142 test_repo 1
143'
144
145test_expect_failure '#1: in subdir' '
146 cat >1/sub/expected <<EOF &&
147setup: git_dir: .git
148setup: worktree: $TRASH_DIRECTORY/1
149setup: cwd: $TRASH_DIRECTORY/1
150setup: prefix: sub/
151EOF
152 test_repo 1/sub
153'
154
155#
156# case #2
157#
158############################################################
159#
160# Input:
161#
162# - GIT_WORK_TREE is not set
163# - GIT_DIR is set
164# - core.worktree is not set
165# - .git is a directory
166# - core.bare is not set, cwd is outside .git
167#
168# Output:
169#
170# - worktree is at original cwd
171# - cwd is unchanged
172# - prefix is NULL
173# - git_dir is set to $GIT_DIR
174# - cwd can't be outside worktree
175
176test_expect_success '#2: setup' '
177 unset GIT_DIR GIT_WORK_TREE &&
178 mkdir 2 2/sub &&
179 cd 2 && git init && cd ..
180'
181
182test_expect_success '#2: at root' '
183 cat >2/expected <<EOF &&
184setup: git_dir: $TRASH_DIRECTORY/2/.git
185setup: worktree: $TRASH_DIRECTORY/2
186setup: cwd: $TRASH_DIRECTORY/2
187setup: prefix: (null)
188EOF
189 test_repo 2 "$TRASH_DIRECTORY/2/.git"
190'
191
192test_expect_success '#2: in subdir' '
193 cat >2/sub/expected <<EOF &&
194setup: git_dir: $TRASH_DIRECTORY/2/.git
195setup: worktree: $TRASH_DIRECTORY/2/sub
196setup: cwd: $TRASH_DIRECTORY/2/sub
197setup: prefix: (null)
198EOF
199 test_repo 2/sub "$TRASH_DIRECTORY/2/.git"
200'
201
202test_expect_success '#2: relative GIT_DIR at root' '
203 cat >2/expected <<EOF &&
204setup: git_dir: .git
205setup: worktree: $TRASH_DIRECTORY/2
206setup: cwd: $TRASH_DIRECTORY/2
207setup: prefix: (null)
208EOF
209 test_repo 2 .git
210'
211
212test_expect_success '#2: relative GIT_DIR in subdir' '
213 cat >2/sub/expected <<EOF &&
214setup: git_dir: ../.git
215setup: worktree: $TRASH_DIRECTORY/2/sub
216setup: cwd: $TRASH_DIRECTORY/2/sub
217setup: prefix: (null)
218EOF
219 test_repo 2/sub ../.git
220'
221
222#
223# case #3
224#
225############################################################
226#
227# Input:
228#
229# - GIT_WORK_TREE is set
230# - GIT_DIR is set
231# - core.worktree is not set
232# - .git is a directory
233# - core.bare is not set, cwd is outside .git
234#
235# Output:
236#
237# - worktree is set to $GIT_WORK_TREE
238# - cwd is at worktree root
239# - prefix is calculated
240# - git_dir is set to $GIT_DIR
241# - cwd can be outside worktree
242
243test_expect_success '#3: setup' '
244 unset GIT_DIR GIT_WORK_TREE &&
245 mkdir 3 3/sub 3/sub/sub 3.wt 3.wt/sub 3/wt 3/wt/sub &&
246 cd 3 && git init && cd ..
247'
248
249test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=root at root' '
250 cat >3/expected <<EOF &&
251setup: git_dir: .git
252setup: worktree: $TRASH_DIRECTORY/3
253setup: cwd: $TRASH_DIRECTORY/3
254setup: prefix: (null)
255EOF
256 test_repo 3 .git "$TRASH_DIRECTORY/3"
257'
258
259test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=root(rel) at root' '
260 cat >3/expected <<EOF &&
261setup: git_dir: .git
262setup: worktree: $TRASH_DIRECTORY/3
263setup: cwd: $TRASH_DIRECTORY/3
264setup: prefix: (null)
265EOF
266 test_repo 3 .git .
267'
268
269test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=root at root' '
270 cat >3/expected <<EOF &&
271setup: git_dir: $TRASH_DIRECTORY/3/.git
272setup: worktree: $TRASH_DIRECTORY/3
273setup: cwd: $TRASH_DIRECTORY/3
274setup: prefix: (null)
275EOF
276 test_repo 3 "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY/3"
277'
278
279test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=root(rel) at root' '
280 cat >3/expected <<EOF &&
281setup: git_dir: $TRASH_DIRECTORY/3/.git
282setup: worktree: $TRASH_DIRECTORY/3
283setup: cwd: $TRASH_DIRECTORY/3
284setup: prefix: (null)
285EOF
286 test_repo 3 "$TRASH_DIRECTORY/3/.git" .
287'
288
289test_expect_success '#3: GIT_DIR(rel), GIT_WORKTREE=root in subdir' '
290 cat >3/sub/sub/expected <<EOF &&
291setup: git_dir: $TRASH_DIRECTORY/3/.git
292setup: worktree: $TRASH_DIRECTORY/3
293setup: cwd: $TRASH_DIRECTORY/3
294setup: prefix: sub/sub/
295EOF
296 test_repo 3/sub/sub ../../.git "$TRASH_DIRECTORY/3"
297'
298
299test_expect_success '#3: GIT_DIR(rel), GIT_WORKTREE=root(rel) in subdir' '
300 cat >3/sub/sub/expected <<EOF &&
301setup: git_dir: $TRASH_DIRECTORY/3/.git
302setup: worktree: $TRASH_DIRECTORY/3
303setup: cwd: $TRASH_DIRECTORY/3
304setup: prefix: sub/sub/
305EOF
306 test_repo 3/sub/sub ../../.git ../..
307'
308
309test_expect_success '#3: GIT_DIR, GIT_WORKTREE=root in subdir' '
310 cat >3/sub/expected <<EOF &&
311setup: git_dir: $TRASH_DIRECTORY/3/.git
312setup: worktree: $TRASH_DIRECTORY/3
313setup: cwd: $TRASH_DIRECTORY/3
314setup: prefix: sub/
315EOF
316 test_repo 3/sub "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY/3"
317'
318
319test_expect_success '#3: GIT_DIR, GIT_WORKTREE=root(rel) in subdir' '
320 cat >3/sub/sub/expected <<EOF &&
321setup: git_dir: $TRASH_DIRECTORY/3/.git
322setup: worktree: $TRASH_DIRECTORY/3
323setup: cwd: $TRASH_DIRECTORY/3
324setup: prefix: sub/sub/
325EOF
326 test_repo 3/sub/sub "$TRASH_DIRECTORY/3/.git" ../..
327'
328
329test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=wt at root' '
330 cat >3/expected <<EOF &&
331setup: git_dir: .git
332setup: worktree: $TRASH_DIRECTORY/3/wt
333setup: cwd: $TRASH_DIRECTORY/3
334setup: prefix: (null)
335EOF
336 test_repo 3 .git "$TRASH_DIRECTORY/3/wt"
337'
338
339test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) at root' '
340 cat >3/expected <<EOF &&
341setup: git_dir: .git
342setup: worktree: $TRASH_DIRECTORY/3/wt
343setup: cwd: $TRASH_DIRECTORY/3
344setup: prefix: (null)
345EOF
346 test_repo 3 .git wt
347'
348
349test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=wt(rel) at root' '
350 cat >3/expected <<EOF &&
351setup: git_dir: $TRASH_DIRECTORY/3/.git
352setup: worktree: $TRASH_DIRECTORY/3/wt
353setup: cwd: $TRASH_DIRECTORY/3
354setup: prefix: (null)
355EOF
356 test_repo 3 "$TRASH_DIRECTORY/3/.git" wt
357'
358
359test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=wt at root' '
360 cat >3/expected <<EOF &&
361setup: git_dir: $TRASH_DIRECTORY/3/.git
362setup: worktree: $TRASH_DIRECTORY/3/wt
363setup: cwd: $TRASH_DIRECTORY/3
364setup: prefix: (null)
365EOF
366 test_repo 3 "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY/3/wt"
367'
368
369test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=wt in subdir' '
370 cat >3/sub/sub/expected <<EOF &&
371setup: git_dir: ../../.git
372setup: worktree: $TRASH_DIRECTORY/3/wt
373setup: cwd: $TRASH_DIRECTORY/3/sub/sub
374setup: prefix: (null)
375EOF
376 test_repo 3/sub/sub ../../.git "$TRASH_DIRECTORY/3/wt"
377'
378
379test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) in subdir' '
380 cat >3/sub/sub/expected <<EOF &&
381setup: git_dir: ../../.git
382setup: worktree: $TRASH_DIRECTORY/3/wt
383setup: cwd: $TRASH_DIRECTORY/3/sub/sub
384setup: prefix: (null)
385EOF
386 test_repo 3/sub/sub ../../.git ../../wt
387'
388
389test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=wt(rel) in subdir' '
390 cat >3/sub/sub/expected <<EOF &&
391setup: git_dir: $TRASH_DIRECTORY/3/.git
392setup: worktree: $TRASH_DIRECTORY/3/wt
393setup: cwd: $TRASH_DIRECTORY/3/sub/sub
394setup: prefix: (null)
395EOF
396 test_repo 3/sub/sub "$TRASH_DIRECTORY/3/.git" ../../wt
397'
398
399test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=wt in subdir' '
400 cat >3/sub/sub/expected <<EOF &&
401setup: git_dir: $TRASH_DIRECTORY/3/.git
402setup: worktree: $TRASH_DIRECTORY/3/wt
403setup: cwd: $TRASH_DIRECTORY/3/sub/sub
404setup: prefix: (null)
405EOF
406 test_repo 3/sub/sub "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY/3/wt"
407'
408
409test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=.. at root' '
410 cat >3/expected <<EOF &&
411setup: git_dir: $TRASH_DIRECTORY/3/.git
412setup: worktree: $TRASH_DIRECTORY
413setup: cwd: $TRASH_DIRECTORY
414setup: prefix: 3/
415EOF
416 test_repo 3 .git "$TRASH_DIRECTORY"
417'
418
419test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=..(rel) at root' '
420 cat >3/expected <<EOF &&
421setup: git_dir: $TRASH_DIRECTORY/3/.git
422setup: worktree: $TRASH_DIRECTORY
423setup: cwd: $TRASH_DIRECTORY
424setup: prefix: 3/
425EOF
426 test_repo 3 .git ..
427'
428
429test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=..(rel) at root' '
430 cat >3/expected <<EOF &&
431setup: git_dir: $TRASH_DIRECTORY/3/.git
432setup: worktree: $TRASH_DIRECTORY
433setup: cwd: $TRASH_DIRECTORY
434setup: prefix: 3/
435EOF
436 test_repo 3 "$TRASH_DIRECTORY/3/.git" ..
437'
438
439test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=.. at root' '
440 cat >3/expected <<EOF &&
441setup: git_dir: $TRASH_DIRECTORY/3/.git
442setup: worktree: $TRASH_DIRECTORY
443setup: cwd: $TRASH_DIRECTORY
444setup: prefix: 3/
445EOF
446 test_repo 3 "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY"
447'
448
449test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=.. in subdir' '
450 cat >3/sub/sub/expected <<EOF &&
451setup: git_dir: $TRASH_DIRECTORY/3/.git
452setup: worktree: $TRASH_DIRECTORY
453setup: cwd: $TRASH_DIRECTORY
454setup: prefix: 3/sub/sub/
455EOF
456 test_repo 3/sub/sub ../../.git "$TRASH_DIRECTORY"
457'
458
459test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=..(rel) in subdir' '
460 cat >3/sub/sub/expected <<EOF &&
461setup: git_dir: $TRASH_DIRECTORY/3/.git
462setup: worktree: $TRASH_DIRECTORY
463setup: cwd: $TRASH_DIRECTORY
464setup: prefix: 3/sub/sub/
465EOF
466 test_repo 3/sub/sub ../../.git ../../..
467'
468
469test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=..(rel) in subdir' '
470 cat >3/sub/sub/expected <<EOF &&
471setup: git_dir: $TRASH_DIRECTORY/3/.git
472setup: worktree: $TRASH_DIRECTORY
473setup: cwd: $TRASH_DIRECTORY
474setup: prefix: 3/sub/sub/
475EOF
476 test_repo 3/sub/sub "$TRASH_DIRECTORY/3/.git" ../../../
477'
478
479test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=.. in subdir' '
480 cat >3/sub/sub/expected <<EOF &&
481setup: git_dir: $TRASH_DIRECTORY/3/.git
482setup: worktree: $TRASH_DIRECTORY
483setup: cwd: $TRASH_DIRECTORY
484setup: prefix: 3/sub/sub/
485EOF
486 test_repo 3/sub/sub "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY"
487'
488
489#
490# case #4
491#
492############################################################
493#
494# Input:
495#
496# - GIT_WORK_TREE is not set
497# - GIT_DIR is not set
498# - core.worktree is set
499# - .git is a directory
500# - core.bare is not set, cwd is outside .git
501#
502# Output:
503#
504# core.worktree is ignored -> #0
505
506test_expect_success '#4: setup' '
507 unset GIT_DIR GIT_WORK_TREE &&
508 mkdir 4 4/sub &&
509 cd 4 &&
510 git init &&
511 git config core.worktree non-existent &&
512 cd ..
513'
514
515test_expect_failure '#4: at root' '
516 cat >4/expected <<EOF &&
517setup: git_dir: .git
518setup: worktree: $TRASH_DIRECTORY/4
519setup: cwd: $TRASH_DIRECTORY/4
520setup: prefix: (null)
521EOF
522 test_repo 4
523'
524
525test_expect_failure '#4: in subdir' '
526 cat >4/sub/expected <<EOF &&
527setup: git_dir: .git
528setup: worktree: $TRASH_DIRECTORY/4
529setup: cwd: $TRASH_DIRECTORY/4
530setup: prefix: sub/
531EOF
532 test_repo 4/sub
533'
534
535#
536# case #5
537#
538############################################################
539#
540# Input:
541#
542# - GIT_WORK_TREE is set
543# - GIT_DIR is not set
544# - core.worktree is set
545# - .git is a directory
546# - core.bare is not set, cwd is outside .git
547#
548# Output:
549#
550# GIT_WORK_TREE/core.worktree are ignored -> #0
551
552test_expect_success '#5: setup' '
553 unset GIT_DIR GIT_WORK_TREE &&
554 mkdir 5 5/sub &&
555 cd 5 &&
556 git init &&
557 git config core.worktree non-existent &&
558 GIT_WORK_TREE=non-existent-too &&
559 export GIT_WORK_TREE &&
560 cd ..
561'
562
563test_expect_failure '#5: at root' '
564 cat >5/expected <<EOF &&
565setup: git_dir: .git
566setup: worktree: $TRASH_DIRECTORY/5
567setup: cwd: $TRASH_DIRECTORY/5
568setup: prefix: (null)
569EOF
570 test_repo 5
571'
572
573test_expect_failure '#5: in subdir' '
574 cat >5/sub/expected <<EOF &&
575setup: git_dir: .git
576setup: worktree: $TRASH_DIRECTORY/5
577setup: cwd: $TRASH_DIRECTORY/5
578setup: prefix: sub/
579EOF
580 test_repo 5/sub
581'
582
583test_done