git prompt: use toplevel to find untracked files
[git] / t / t9903-bash-prompt.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2012 SZEDER Gábor
4 #
5
6 test_description='test git-specific bash prompt functions'
7
8 . ./lib-bash.sh
9
10 . "$GIT_BUILD_DIR/contrib/completion/git-prompt.sh"
11
12 actual="$TRASH_DIRECTORY/actual"
13 c_red='\\[\\e[31m\\]'
14 c_green='\\[\\e[32m\\]'
15 c_lblue='\\[\\e[1;34m\\]'
16 c_clear='\\[\\e[0m\\]'
17
18 test_expect_success 'setup for prompt tests' '
19         git init otherrepo &&
20         echo 1 >file &&
21         git add file &&
22         test_tick &&
23         git commit -m initial &&
24         git tag -a -m msg1 t1 &&
25         git checkout -b b1 &&
26         echo 2 >file &&
27         git commit -m "second b1" file &&
28         echo 3 >file &&
29         git commit -m "third b1" file &&
30         git tag -a -m msg2 t2 &&
31         git checkout -b b2 master &&
32         echo 0 >file &&
33         git commit -m "second b2" file &&
34         echo 00 >file &&
35         git commit -m "another b2" file &&
36         echo 000 >file &&
37         git commit -m "yet another b2" file &&
38         git checkout master
39 '
40
41 test_expect_success 'prompt - branch name' '
42         printf " (master)" >expected &&
43         __git_ps1 >"$actual" &&
44         test_cmp expected "$actual"
45 '
46
47 test_expect_success SYMLINKS 'prompt - branch name - symlink symref' '
48         printf " (master)" >expected &&
49         test_when_finished "git checkout master" &&
50         test_config core.preferSymlinkRefs true &&
51         git checkout master &&
52         __git_ps1 >"$actual" &&
53         test_cmp expected "$actual"
54 '
55
56 test_expect_success 'prompt - unborn branch' '
57         printf " (unborn)" >expected &&
58         git checkout --orphan unborn &&
59         test_when_finished "git checkout master" &&
60         __git_ps1 >"$actual" &&
61         test_cmp expected "$actual"
62 '
63
64 repo_with_newline='repo
65 with
66 newline'
67
68 if mkdir "$repo_with_newline" 2>/dev/null
69 then
70         test_set_prereq FUNNYNAMES
71 else
72         say 'Your filesystem does not allow newlines in filenames.'
73 fi
74
75 test_expect_success FUNNYNAMES 'prompt - with newline in path' '
76         printf " (master)" >expected &&
77         git init "$repo_with_newline" &&
78         test_when_finished "rm -rf \"$repo_with_newline\"" &&
79         mkdir "$repo_with_newline"/subdir &&
80         (
81                 cd "$repo_with_newline/subdir" &&
82                 __git_ps1 >"$actual"
83         ) &&
84         test_cmp expected "$actual"
85 '
86
87 test_expect_success 'prompt - detached head' '
88         printf " ((%s...))" $(git log -1 --format="%h" --abbrev=13 b1^) >expected &&
89         test_config core.abbrev 13 &&
90         git checkout b1^ &&
91         test_when_finished "git checkout master" &&
92         __git_ps1 >"$actual" &&
93         test_cmp expected "$actual"
94 '
95
96 test_expect_success 'prompt - describe detached head - contains' '
97         printf " ((t2~1))" >expected &&
98         git checkout b1^ &&
99         test_when_finished "git checkout master" &&
100         (
101                 GIT_PS1_DESCRIBE_STYLE=contains &&
102                 __git_ps1 >"$actual"
103         ) &&
104         test_cmp expected "$actual"
105 '
106
107 test_expect_success 'prompt - describe detached head - branch' '
108         printf " ((b1~1))" >expected &&
109         git checkout b1^ &&
110         test_when_finished "git checkout master" &&
111         (
112                 GIT_PS1_DESCRIBE_STYLE=branch &&
113                 __git_ps1 >"$actual"
114         ) &&
115         test_cmp expected "$actual"
116 '
117
118 test_expect_success 'prompt - describe detached head - describe' '
119         printf " ((t1-1-g%s))" $(git log -1 --format="%h" b1^) >expected &&
120         git checkout b1^ &&
121         test_when_finished "git checkout master" &&
122         (
123                 GIT_PS1_DESCRIBE_STYLE=describe &&
124                 __git_ps1 >"$actual"
125         ) &&
126         test_cmp expected "$actual"
127 '
128
129 test_expect_success 'prompt - describe detached head - default' '
130         printf " ((t2))" >expected &&
131         git checkout --detach b1 &&
132         test_when_finished "git checkout master" &&
133         __git_ps1 >"$actual" &&
134         test_cmp expected "$actual"
135 '
136
137 test_expect_success 'prompt - inside .git directory' '
138         printf " (GIT_DIR!)" >expected &&
139         (
140                 cd .git &&
141                 __git_ps1 >"$actual"
142         ) &&
143         test_cmp expected "$actual"
144 '
145
146 test_expect_success 'prompt - deep inside .git directory' '
147         printf " (GIT_DIR!)" >expected &&
148         (
149                 cd .git/refs/heads &&
150                 __git_ps1 >"$actual"
151         ) &&
152         test_cmp expected "$actual"
153 '
154
155 test_expect_success 'prompt - inside bare repository' '
156         printf " (BARE:master)" >expected &&
157         git init --bare bare.git &&
158         test_when_finished "rm -rf bare.git" &&
159         (
160                 cd bare.git &&
161                 __git_ps1 >"$actual"
162         ) &&
163         test_cmp expected "$actual"
164 '
165
166 test_expect_success 'prompt - interactive rebase' '
167         printf " (b1|REBASE-i 2/3)" >expected
168         write_script fake_editor.sh <<-\EOF &&
169                 echo "exec echo" >"$1"
170                 echo "edit $(git log -1 --format="%h")" >>"$1"
171                 echo "exec echo" >>"$1"
172         EOF
173         test_when_finished "rm -f fake_editor.sh" &&
174         test_set_editor "$TRASH_DIRECTORY/fake_editor.sh" &&
175         git checkout b1 &&
176         test_when_finished "git checkout master" &&
177         git rebase -i HEAD^ &&
178         test_when_finished "git rebase --abort"
179         __git_ps1 >"$actual" &&
180         test_cmp expected "$actual"
181 '
182
183 test_expect_success 'prompt - rebase merge' '
184         printf " (b2|REBASE-m 1/3)" >expected &&
185         git checkout b2 &&
186         test_when_finished "git checkout master" &&
187         test_must_fail git rebase --merge b1 b2 &&
188         test_when_finished "git rebase --abort" &&
189         __git_ps1 >"$actual" &&
190         test_cmp expected "$actual"
191 '
192
193 test_expect_success 'prompt - rebase' '
194         printf " (b2|REBASE 1/3)" >expected &&
195         git checkout b2 &&
196         test_when_finished "git checkout master" &&
197         test_must_fail git rebase b1 b2 &&
198         test_when_finished "git rebase --abort" &&
199         __git_ps1 >"$actual" &&
200         test_cmp expected "$actual"
201 '
202
203 test_expect_success 'prompt - merge' '
204         printf " (b1|MERGING)" >expected &&
205         git checkout b1 &&
206         test_when_finished "git checkout master" &&
207         test_must_fail git merge b2 &&
208         test_when_finished "git reset --hard" &&
209         __git_ps1 >"$actual" &&
210         test_cmp expected "$actual"
211 '
212
213 test_expect_success 'prompt - cherry-pick' '
214         printf " (master|CHERRY-PICKING)" >expected &&
215         test_must_fail git cherry-pick b1 &&
216         test_when_finished "git reset --hard" &&
217         __git_ps1 >"$actual" &&
218         test_cmp expected "$actual"
219 '
220
221 test_expect_success 'prompt - bisect' '
222         printf " (master|BISECTING)" >expected &&
223         git bisect start &&
224         test_when_finished "git bisect reset" &&
225         __git_ps1 >"$actual" &&
226         test_cmp expected "$actual"
227 '
228
229 test_expect_success 'prompt - dirty status indicator - clean' '
230         printf " (master)" >expected &&
231         (
232                 GIT_PS1_SHOWDIRTYSTATE=y &&
233                 __git_ps1 >"$actual"
234         ) &&
235         test_cmp expected "$actual"
236 '
237
238 test_expect_success 'prompt - dirty status indicator - dirty worktree' '
239         printf " (master *)" >expected &&
240         echo "dirty" >file &&
241         test_when_finished "git reset --hard" &&
242         (
243                 GIT_PS1_SHOWDIRTYSTATE=y &&
244                 __git_ps1 >"$actual"
245         ) &&
246         test_cmp expected "$actual"
247 '
248
249 test_expect_success 'prompt - dirty status indicator - dirty index' '
250         printf " (master +)" >expected &&
251         echo "dirty" >file &&
252         test_when_finished "git reset --hard" &&
253         git add -u &&
254         (
255                 GIT_PS1_SHOWDIRTYSTATE=y &&
256                 __git_ps1 >"$actual"
257         ) &&
258         test_cmp expected "$actual"
259 '
260
261 test_expect_success 'prompt - dirty status indicator - dirty index and worktree' '
262         printf " (master *+)" >expected &&
263         echo "dirty index" >file &&
264         test_when_finished "git reset --hard" &&
265         git add -u &&
266         echo "dirty worktree" >file &&
267         (
268                 GIT_PS1_SHOWDIRTYSTATE=y &&
269                 __git_ps1 >"$actual"
270         ) &&
271         test_cmp expected "$actual"
272 '
273
274 test_expect_success 'prompt - dirty status indicator - before root commit' '
275         printf " (master #)" >expected &&
276         (
277                 GIT_PS1_SHOWDIRTYSTATE=y &&
278                 cd otherrepo &&
279                 __git_ps1 >"$actual"
280         ) &&
281         test_cmp expected "$actual"
282 '
283
284 test_expect_success 'prompt - dirty status indicator - shell variable unset with config disabled' '
285         printf " (master)" >expected &&
286         echo "dirty" >file &&
287         test_when_finished "git reset --hard" &&
288         test_config bash.showDirtyState false &&
289         (
290                 sane_unset GIT_PS1_SHOWDIRTYSTATE &&
291                 __git_ps1 >"$actual"
292         ) &&
293         test_cmp expected "$actual"
294 '
295
296 test_expect_success 'prompt - dirty status indicator - shell variable unset with config enabled' '
297         printf " (master)" >expected &&
298         echo "dirty" >file &&
299         test_when_finished "git reset --hard" &&
300         test_config bash.showDirtyState true &&
301         (
302                 sane_unset GIT_PS1_SHOWDIRTYSTATE &&
303                 __git_ps1 >"$actual"
304         ) &&
305         test_cmp expected "$actual"
306 '
307
308 test_expect_success 'prompt - dirty status indicator - shell variable set with config disabled' '
309         printf " (master)" >expected &&
310         echo "dirty" >file &&
311         test_when_finished "git reset --hard" &&
312         test_config bash.showDirtyState false &&
313         (
314                 GIT_PS1_SHOWDIRTYSTATE=y &&
315                 __git_ps1 >"$actual"
316         ) &&
317         test_cmp expected "$actual"
318 '
319
320 test_expect_success 'prompt - dirty status indicator - shell variable set with config enabled' '
321         printf " (master *)" >expected &&
322         echo "dirty" >file &&
323         test_when_finished "git reset --hard" &&
324         test_config bash.showDirtyState true &&
325         (
326                 GIT_PS1_SHOWDIRTYSTATE=y &&
327                 __git_ps1 >"$actual"
328         ) &&
329         test_cmp expected "$actual"
330 '
331
332 test_expect_success 'prompt - dirty status indicator - not shown inside .git directory' '
333         printf " (GIT_DIR!)" >expected &&
334         echo "dirty" >file &&
335         test_when_finished "git reset --hard" &&
336         (
337                 GIT_PS1_SHOWDIRTYSTATE=y &&
338                 cd .git &&
339                 __git_ps1 >"$actual"
340         ) &&
341         test_cmp expected "$actual"
342 '
343
344 test_expect_success 'prompt - stash status indicator - no stash' '
345         printf " (master)" >expected &&
346         (
347                 GIT_PS1_SHOWSTASHSTATE=y &&
348                 __git_ps1 >"$actual"
349         ) &&
350         test_cmp expected "$actual"
351 '
352
353 test_expect_success 'prompt - stash status indicator - stash' '
354         printf " (master $)" >expected &&
355         echo 2 >file &&
356         git stash &&
357         test_when_finished "git stash drop" &&
358         git pack-refs --all &&
359         (
360                 GIT_PS1_SHOWSTASHSTATE=y &&
361                 __git_ps1 >"$actual"
362         ) &&
363         test_cmp expected "$actual"
364 '
365
366 test_expect_success 'prompt - stash status indicator - not shown inside .git directory' '
367         printf " (GIT_DIR!)" >expected &&
368         echo 2 >file &&
369         git stash &&
370         test_when_finished "git stash drop" &&
371         (
372                 GIT_PS1_SHOWSTASHSTATE=y &&
373                 cd .git &&
374                 __git_ps1 >"$actual"
375         ) &&
376         test_cmp expected "$actual"
377 '
378
379 test_expect_success 'prompt - untracked files status indicator - no untracked files' '
380         printf " (master)" >expected &&
381         (
382                 GIT_PS1_SHOWUNTRACKEDFILES=y &&
383                 cd otherrepo &&
384                 __git_ps1 >"$actual"
385         ) &&
386         test_cmp expected "$actual"
387 '
388
389 test_expect_success 'prompt - untracked files status indicator - untracked files' '
390         printf " (master %%)" >expected &&
391         (
392                 GIT_PS1_SHOWUNTRACKEDFILES=y &&
393                 __git_ps1 >"$actual"
394         ) &&
395         test_cmp expected "$actual"
396 '
397
398 test_expect_success 'prompt - untracked files status indicator - untracked files outside cwd' '
399         printf " (master %%)" >expected &&
400         (
401                 mkdir -p ignored_dir &&
402                 cd ignored_dir &&
403                 GIT_PS1_SHOWUNTRACKEDFILES=y &&
404                 __git_ps1 >"$actual"
405         ) &&
406         test_cmp expected "$actual"
407 '
408
409 test_expect_success 'prompt - untracked files status indicator - shell variable unset with config disabled' '
410         printf " (master)" >expected &&
411         test_config bash.showUntrackedFiles false &&
412         (
413                 sane_unset GIT_PS1_SHOWUNTRACKEDFILES &&
414                 __git_ps1 >"$actual"
415         ) &&
416         test_cmp expected "$actual"
417 '
418
419 test_expect_success 'prompt - untracked files status indicator - shell variable unset with config enabled' '
420         printf " (master)" >expected &&
421         test_config bash.showUntrackedFiles true &&
422         (
423                 sane_unset GIT_PS1_SHOWUNTRACKEDFILES &&
424                 __git_ps1 >"$actual"
425         ) &&
426         test_cmp expected "$actual"
427 '
428
429 test_expect_success 'prompt - untracked files status indicator - shell variable set with config disabled' '
430         printf " (master)" >expected &&
431         test_config bash.showUntrackedFiles false &&
432         (
433                 GIT_PS1_SHOWUNTRACKEDFILES=y &&
434                 __git_ps1 >"$actual"
435         ) &&
436         test_cmp expected "$actual"
437 '
438
439 test_expect_success 'prompt - untracked files status indicator - shell variable set with config enabled' '
440         printf " (master %%)" >expected &&
441         test_config bash.showUntrackedFiles true &&
442         (
443                 GIT_PS1_SHOWUNTRACKEDFILES=y &&
444                 __git_ps1 >"$actual"
445         ) &&
446         test_cmp expected "$actual"
447 '
448
449 test_expect_success 'prompt - untracked files status indicator - not shown inside .git directory' '
450         printf " (GIT_DIR!)" >expected &&
451         (
452                 GIT_PS1_SHOWUNTRACKEDFILES=y &&
453                 cd .git &&
454                 __git_ps1 >"$actual"
455         ) &&
456         test_cmp expected "$actual"
457 '
458
459 test_expect_success 'prompt - format string starting with dash' '
460         printf -- "-master" >expected &&
461         __git_ps1 "-%s" >"$actual" &&
462         test_cmp expected "$actual"
463 '
464
465 test_expect_success 'prompt - pc mode' '
466         printf "BEFORE: (\${__git_ps1_branch_name}):AFTER\\nmaster" >expected &&
467         printf "" >expected_output &&
468         (
469                 __git_ps1 "BEFORE:" ":AFTER" >"$actual" &&
470                 test_cmp expected_output "$actual" &&
471                 printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
472         ) &&
473         test_cmp expected "$actual"
474 '
475
476 test_expect_success 'prompt - bash color pc mode - branch name' '
477         printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear}):AFTER\\nmaster" >expected &&
478         (
479                 GIT_PS1_SHOWCOLORHINTS=y &&
480                 __git_ps1 "BEFORE:" ":AFTER" >"$actual"
481                 printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
482         ) &&
483         test_cmp expected "$actual"
484 '
485
486 test_expect_success 'prompt - bash color pc mode - detached head' '
487         printf "BEFORE: (${c_red}\${__git_ps1_branch_name}${c_clear}):AFTER\\n(%s...)" $(git log -1 --format="%h" b1^) >expected &&
488         git checkout b1^ &&
489         test_when_finished "git checkout master" &&
490         (
491                 GIT_PS1_SHOWCOLORHINTS=y &&
492                 __git_ps1 "BEFORE:" ":AFTER" &&
493                 printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
494         ) &&
495         test_cmp expected "$actual"
496 '
497
498 test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty worktree' '
499         printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_red}*${c_clear}):AFTER\\nmaster" >expected &&
500         echo "dirty" >file &&
501         test_when_finished "git reset --hard" &&
502         (
503                 GIT_PS1_SHOWDIRTYSTATE=y &&
504                 GIT_PS1_SHOWCOLORHINTS=y &&
505                 __git_ps1 "BEFORE:" ":AFTER" &&
506                 printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
507         ) &&
508         test_cmp expected "$actual"
509 '
510
511 test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty index' '
512         printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_green}+${c_clear}):AFTER\\nmaster" >expected &&
513         echo "dirty" >file &&
514         test_when_finished "git reset --hard" &&
515         git add -u &&
516         (
517                 GIT_PS1_SHOWDIRTYSTATE=y &&
518                 GIT_PS1_SHOWCOLORHINTS=y &&
519                 __git_ps1 "BEFORE:" ":AFTER" &&
520                 printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
521         ) &&
522         test_cmp expected "$actual"
523 '
524
525 test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty index and worktree' '
526         printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_red}*${c_green}+${c_clear}):AFTER\\nmaster" >expected &&
527         echo "dirty index" >file &&
528         test_when_finished "git reset --hard" &&
529         git add -u &&
530         echo "dirty worktree" >file &&
531         (
532                 GIT_PS1_SHOWCOLORHINTS=y &&
533                 GIT_PS1_SHOWDIRTYSTATE=y &&
534                 __git_ps1 "BEFORE:" ":AFTER" &&
535                 printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
536         ) &&
537         test_cmp expected "$actual"
538 '
539
540 test_expect_success 'prompt - bash color pc mode - dirty status indicator - before root commit' '
541         printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_green}#${c_clear}):AFTER\\nmaster" >expected &&
542         (
543                 GIT_PS1_SHOWDIRTYSTATE=y &&
544                 GIT_PS1_SHOWCOLORHINTS=y &&
545                 cd otherrepo &&
546                 __git_ps1 "BEFORE:" ":AFTER" &&
547                 printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
548         ) &&
549         test_cmp expected "$actual"
550 '
551
552 test_expect_success 'prompt - bash color pc mode - inside .git directory' '
553         printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear}):AFTER\\nGIT_DIR!" >expected &&
554         echo "dirty" >file &&
555         test_when_finished "git reset --hard" &&
556         (
557                 GIT_PS1_SHOWDIRTYSTATE=y &&
558                 GIT_PS1_SHOWCOLORHINTS=y &&
559                 cd .git &&
560                 __git_ps1 "BEFORE:" ":AFTER" &&
561                 printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
562         ) &&
563         test_cmp expected "$actual"
564 '
565
566 test_expect_success 'prompt - bash color pc mode - stash status indicator' '
567         printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_lblue}\$${c_clear}):AFTER\\nmaster" >expected &&
568         echo 2 >file &&
569         git stash &&
570         test_when_finished "git stash drop" &&
571         (
572                 GIT_PS1_SHOWSTASHSTATE=y &&
573                 GIT_PS1_SHOWCOLORHINTS=y &&
574                 __git_ps1 "BEFORE:" ":AFTER" &&
575                 printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
576         ) &&
577         test_cmp expected "$actual"
578 '
579
580 test_expect_success 'prompt - bash color pc mode - untracked files status indicator' '
581         printf "BEFORE: (${c_green}\${__git_ps1_branch_name}${c_clear} ${c_red}%%${c_clear}):AFTER\\nmaster" >expected &&
582         (
583                 GIT_PS1_SHOWUNTRACKEDFILES=y &&
584                 GIT_PS1_SHOWCOLORHINTS=y &&
585                 __git_ps1 "BEFORE:" ":AFTER" &&
586                 printf "%s\\n%s" "$PS1" "${__git_ps1_branch_name}" >"$actual"
587         ) &&
588         test_cmp expected "$actual"
589 '
590
591 test_expect_success 'prompt - zsh color pc mode' '
592         printf "BEFORE: (%%F{green}master%%f):AFTER" >expected &&
593         (
594                 ZSH_VERSION=5.0.0 &&
595                 GIT_PS1_SHOWCOLORHINTS=y &&
596                 __git_ps1 "BEFORE:" ":AFTER" &&
597                 printf "%s" "$PS1" >"$actual"
598         ) &&
599         test_cmp expected "$actual"
600 '
601
602 test_done