Merge branch 'cm/remote-mediawiki'
[git] / t / t9902-completion.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2012 Felipe Contreras
4 #
5
6 test_description='test bash completion'
7
8 . ./lib-bash.sh
9
10 complete ()
11 {
12         # do nothing
13         return 0
14 }
15
16 # Be careful when updating this list:
17 #
18 # (1) The build tree may have build artifact from different branch, or
19 #     the user's $PATH may have a random executable that may begin
20 #     with "git-check" that are not part of the subcommands this build
21 #     will ship, e.g.  "check-ignore".  The tests for completion for
22 #     subcommand names tests how "check" is expanded; we limit the
23 #     possible candidates to "checkout" and "check-attr" to make sure
24 #     "check-attr", which is known by the filter function as a
25 #     subcommand to be thrown out, while excluding other random files
26 #     that happen to begin with "check" to avoid letting them get in
27 #     the way.
28 #
29 # (2) A test makes sure that common subcommands are included in the
30 #     completion for "git <TAB>", and a plumbing is excluded.  "add",
31 #     "filter-branch" and "ls-files" are listed for this.
32
33 GIT_TESTING_COMMAND_COMPLETION='add checkout check-attr filter-branch ls-files'
34
35 . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash"
36
37 # We don't need this function to actually join words or do anything special.
38 # Also, it's cleaner to avoid touching bash's internal completion variables.
39 # So let's override it with a minimal version for testing purposes.
40 _get_comp_words_by_ref ()
41 {
42         while [ $# -gt 0 ]; do
43                 case "$1" in
44                 cur)
45                         cur=${_words[_cword]}
46                         ;;
47                 prev)
48                         prev=${_words[_cword-1]}
49                         ;;
50                 words)
51                         words=("${_words[@]}")
52                         ;;
53                 cword)
54                         cword=$_cword
55                         ;;
56                 esac
57                 shift
58         done
59 }
60
61 print_comp ()
62 {
63         local IFS=$'\n'
64         echo "${COMPREPLY[*]}" > out
65 }
66
67 run_completion ()
68 {
69         local -a COMPREPLY _words
70         local _cword
71         _words=( $1 )
72         test "${1: -1}" == ' ' && _words+=('')
73         (( _cword = ${#_words[@]} - 1 ))
74         __git_wrap__git_main && print_comp
75 }
76
77 # Test high-level completion
78 # Arguments are:
79 # 1: typed text so far (cur)
80 # 2: expected completion
81 test_completion ()
82 {
83         if test $# -gt 1
84         then
85                 printf '%s\n' "$2" >expected
86         else
87                 sed -e 's/Z$//' >expected
88         fi &&
89         run_completion "$1" &&
90         test_cmp expected out
91 }
92
93 # Test __gitcomp.
94 # The first argument is the typed text so far (cur); the rest are
95 # passed to __gitcomp.  Expected output comes is read from the
96 # standard input, like test_completion().
97 test_gitcomp ()
98 {
99         local -a COMPREPLY &&
100         sed -e 's/Z$//' >expected &&
101         cur="$1" &&
102         shift &&
103         __gitcomp "$@" &&
104         print_comp &&
105         test_cmp expected out
106 }
107
108 # Test __gitcomp_nl
109 # Arguments are:
110 # 1: current word (cur)
111 # -: the rest are passed to __gitcomp_nl
112 test_gitcomp_nl ()
113 {
114         local -a COMPREPLY &&
115         sed -e 's/Z$//' >expected &&
116         cur="$1" &&
117         shift &&
118         __gitcomp_nl "$@" &&
119         print_comp &&
120         test_cmp expected out
121 }
122
123 invalid_variable_name='${foo.bar}'
124
125 test_expect_success '__gitcomp - trailing space - options' '
126         test_gitcomp "--re" "--dry-run --reuse-message= --reedit-message=
127                 --reset-author" <<-EOF
128         --reuse-message=Z
129         --reedit-message=Z
130         --reset-author Z
131         EOF
132 '
133
134 test_expect_success '__gitcomp - trailing space - config keys' '
135         test_gitcomp "br" "branch. branch.autosetupmerge
136                 branch.autosetuprebase browser." <<-\EOF
137         branch.Z
138         branch.autosetupmerge Z
139         branch.autosetuprebase Z
140         browser.Z
141         EOF
142 '
143
144 test_expect_success '__gitcomp - option parameter' '
145         test_gitcomp "--strategy=re" "octopus ours recursive resolve subtree" \
146                 "" "re" <<-\EOF
147         recursive Z
148         resolve Z
149         EOF
150 '
151
152 test_expect_success '__gitcomp - prefix' '
153         test_gitcomp "branch.me" "remote merge mergeoptions rebase" \
154                 "branch.maint." "me" <<-\EOF
155         branch.maint.merge Z
156         branch.maint.mergeoptions Z
157         EOF
158 '
159
160 test_expect_success '__gitcomp - suffix' '
161         test_gitcomp "branch.me" "master maint next pu" "branch." \
162                 "ma" "." <<-\EOF
163         branch.master.Z
164         branch.maint.Z
165         EOF
166 '
167
168 test_expect_success '__gitcomp - doesnt fail because of invalid variable name' '
169         __gitcomp "$invalid_variable_name"
170 '
171
172 read -r -d "" refs <<-\EOF
173 maint
174 master
175 next
176 pu
177 EOF
178
179 test_expect_success '__gitcomp_nl - trailing space' '
180         test_gitcomp_nl "m" "$refs" <<-EOF
181         maint Z
182         master Z
183         EOF
184 '
185
186 test_expect_success '__gitcomp_nl - prefix' '
187         test_gitcomp_nl "--fixup=m" "$refs" "--fixup=" "m" <<-EOF
188         --fixup=maint Z
189         --fixup=master Z
190         EOF
191 '
192
193 test_expect_success '__gitcomp_nl - suffix' '
194         test_gitcomp_nl "branch.ma" "$refs" "branch." "ma" "." <<-\EOF
195         branch.maint.Z
196         branch.master.Z
197         EOF
198 '
199
200 test_expect_success '__gitcomp_nl - no suffix' '
201         test_gitcomp_nl "ma" "$refs" "" "ma" "" <<-\EOF
202         maintZ
203         masterZ
204         EOF
205 '
206
207 test_expect_success '__gitcomp_nl - doesnt fail because of invalid variable name' '
208         __gitcomp_nl "$invalid_variable_name"
209 '
210
211 test_expect_success 'basic' '
212         run_completion "git " &&
213         # built-in
214         grep -q "^add \$" out &&
215         # script
216         grep -q "^filter-branch \$" out &&
217         # plumbing
218         ! grep -q "^ls-files \$" out &&
219
220         run_completion "git f" &&
221         ! grep -q -v "^f" out
222 '
223
224 test_expect_success 'double dash "git" itself' '
225         test_completion "git --" <<-\EOF
226         --paginate Z
227         --no-pager Z
228         --git-dir=
229         --bare Z
230         --version Z
231         --exec-path Z
232         --exec-path=
233         --html-path Z
234         --info-path Z
235         --work-tree=
236         --namespace=
237         --no-replace-objects Z
238         --help Z
239         EOF
240 '
241
242 test_expect_success 'double dash "git checkout"' '
243         test_completion "git checkout --" <<-\EOF
244         --quiet Z
245         --ours Z
246         --theirs Z
247         --track Z
248         --no-track Z
249         --merge Z
250         --conflict=
251         --orphan Z
252         --patch Z
253         EOF
254 '
255
256 test_expect_success 'general options' '
257         test_completion "git --ver" "--version " &&
258         test_completion "git --hel" "--help " &&
259         test_completion "git --exe" <<-\EOF &&
260         --exec-path Z
261         --exec-path=
262         EOF
263         test_completion "git --htm" "--html-path " &&
264         test_completion "git --pag" "--paginate " &&
265         test_completion "git --no-p" "--no-pager " &&
266         test_completion "git --git" "--git-dir=" &&
267         test_completion "git --wor" "--work-tree=" &&
268         test_completion "git --nam" "--namespace=" &&
269         test_completion "git --bar" "--bare " &&
270         test_completion "git --inf" "--info-path " &&
271         test_completion "git --no-r" "--no-replace-objects "
272 '
273
274 test_expect_success 'general options plus command' '
275         test_completion "git --version check" "checkout " &&
276         test_completion "git --paginate check" "checkout " &&
277         test_completion "git --git-dir=foo check" "checkout " &&
278         test_completion "git --bare check" "checkout " &&
279         test_completion "git --exec-path=foo check" "checkout " &&
280         test_completion "git --html-path check" "checkout " &&
281         test_completion "git --no-pager check" "checkout " &&
282         test_completion "git --work-tree=foo check" "checkout " &&
283         test_completion "git --namespace=foo check" "checkout " &&
284         test_completion "git --paginate check" "checkout " &&
285         test_completion "git --info-path check" "checkout " &&
286         test_completion "git --no-replace-objects check" "checkout "
287 '
288
289 test_expect_success 'git --help completion' '
290         test_completion "git --help ad" "add " &&
291         test_completion "git --help core" "core-tutorial "
292 '
293
294 test_expect_success 'setup for ref completion' '
295         echo content >file1 &&
296         echo more >file2 &&
297         git add . &&
298         git commit -m one &&
299         git branch mybranch &&
300         git tag mytag
301 '
302
303 test_expect_success 'checkout completes ref names' '
304         test_completion "git checkout m" <<-\EOF
305         master Z
306         mybranch Z
307         mytag Z
308         EOF
309 '
310
311 test_expect_success 'show completes all refs' '
312         test_completion "git show m" <<-\EOF
313         master Z
314         mybranch Z
315         mytag Z
316         EOF
317 '
318
319 test_expect_success '<ref>: completes paths' '
320         test_completion "git show mytag:f" <<-\EOF
321         file1 Z
322         file2 Z
323         EOF
324 '
325
326 test_expect_success 'complete tree filename with spaces' '
327         echo content >"name with spaces" &&
328         git add . &&
329         git commit -m spaces &&
330         test_completion "git show HEAD:nam" <<-\EOF
331         name with spaces Z
332         EOF
333 '
334
335 test_expect_success 'complete tree filename with metacharacters' '
336         echo content >"name with \${meta}" &&
337         git add . &&
338         git commit -m meta &&
339         test_completion "git show HEAD:nam" <<-\EOF
340         name with ${meta} Z
341         name with spaces Z
342         EOF
343 '
344
345 test_expect_success 'send-email' '
346         test_completion "git send-email --cov" "--cover-letter " &&
347         test_completion "git send-email ma" "master "
348 '
349
350 test_expect_success 'complete files' '
351         git init tmp && cd tmp &&
352         test_when_finished "cd .. && rm -rf tmp" &&
353
354         echo "expected" > .gitignore &&
355         echo "out" >> .gitignore &&
356
357         git add .gitignore &&
358         test_completion "git commit " ".gitignore" &&
359
360         git commit -m ignore &&
361
362         touch new &&
363         test_completion "git add " "new" &&
364
365         git add new &&
366         git commit -a -m new &&
367         test_completion "git add " "" &&
368
369         git mv new modified &&
370         echo modify > modified &&
371         test_completion "git add " "modified" &&
372
373         touch untracked &&
374
375         : TODO .gitignore should not be here &&
376         test_completion "git rm " <<-\EOF &&
377         .gitignore
378         modified
379         EOF
380
381         test_completion "git clean " "untracked" &&
382
383         : TODO .gitignore should not be here &&
384         test_completion "git mv " <<-\EOF &&
385         .gitignore
386         modified
387         EOF
388
389         mkdir dir &&
390         touch dir/file-in-dir &&
391         git add dir/file-in-dir &&
392         git commit -m dir &&
393
394         mkdir untracked-dir &&
395
396         : TODO .gitignore should not be here &&
397         test_completion "git mv modified " <<-\EOF &&
398         .gitignore
399         dir
400         modified
401         untracked
402         untracked-dir
403         EOF
404
405         test_completion "git commit " "modified" &&
406
407         : TODO .gitignore should not be here &&
408         test_completion "git ls-files " <<-\EOF
409         .gitignore
410         dir
411         modified
412         EOF
413
414         touch momified &&
415         test_completion "git add mom" "momified"
416 '
417
418 test_expect_failure 'complete with tilde expansion' '
419         git init tmp && cd tmp &&
420         test_when_finished "cd .. && rm -rf tmp" &&
421
422         touch ~/tmp/file &&
423
424         test_completion "git add ~/tmp/" "~/tmp/file"
425 '
426
427 test_done