Merge branch 'aw/cvsimport'
[git] / contrib / completion / git-completion.bash
1 #
2 # bash completion support for core Git.
3 #
4 # Copyright (C) 2006 Shawn Pearce
5 # Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
6 #
7 # The contained completion routines provide support for completing:
8 #
9 #    *) local and remote branch names
10 #    *) local and remote tag names
11 #    *) .git/remotes file names
12 #    *) git 'subcommands'
13 #    *) tree paths within 'ref:path/to/file' expressions
14 #
15 # To use these routines:
16 #
17 #    1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
18 #    2) Added the following line to your .bashrc:
19 #        source ~/.git-completion.sh
20 #
21
22 __git_refs ()
23 {
24         local cmd i is_hash=y
25         if [ -d "$1" ]; then
26                 cmd=git-peek-remote
27         else
28                 cmd=git-ls-remote
29         fi
30         for i in $($cmd "$1" 2>/dev/null); do
31                 case "$is_hash,$i" in
32                 y,*) is_hash=n ;;
33                 n,*^{}) is_hash=y ;;
34                 n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
35                 n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
36                 n,*) is_hash=y; echo "$i" ;;
37                 esac
38         done
39 }
40
41 __git_refs2 ()
42 {
43         local cmd i is_hash=y
44         if [ -d "$1" ]; then
45                 cmd=git-peek-remote
46         else
47                 cmd=git-ls-remote
48         fi
49         for i in $($cmd "$1" 2>/dev/null); do
50                 case "$is_hash,$i" in
51                 y,*) is_hash=n ;;
52                 n,*^{}) is_hash=y ;;
53                 n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}:${i#refs/tags/}" ;;
54                 n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}:${i#refs/heads/}" ;;
55                 n,*) is_hash=y; echo "$i:$i" ;;
56                 esac
57         done
58 }
59
60 __git_remotes ()
61 {
62         local i REVERTGLOB=$(shopt -p nullglob)
63         shopt -s nullglob
64         for i in .git/remotes/*; do
65                 echo ${i#.git/remotes/}
66         done
67         $REVERTGLOB
68 }
69
70 __git_complete_file ()
71 {
72         local cur="${COMP_WORDS[COMP_CWORD]}"
73         case "$cur" in
74         ?*:*)
75                 local pfx ls ref="$(echo "$cur" | sed 's,:.*$,,')"
76                 cur="$(echo "$cur" | sed 's,^.*:,,')"
77                 case "$cur" in
78                 ?*/*)
79                         pfx="$(echo "$cur" | sed 's,/[^/]*$,,')"
80                         cur="$(echo "$cur" | sed 's,^.*/,,')"
81                         ls="$ref:$pfx"
82                         pfx="$pfx/"
83                         ;;
84                 *)
85                         ls="$ref"
86                         ;;
87             esac
88                 COMPREPLY=($(compgen -P "$pfx" \
89                         -W "$(git-ls-tree "$ls" \
90                                 | sed '/^100... blob /s,^.*     ,,
91                                        /^040000 tree /{
92                                            s,^.*        ,,
93                                            s,$,/,
94                                        }
95                                        s/^.*    //')" \
96                         -- "$cur"))
97                 ;;
98         *)
99                 COMPREPLY=($(compgen -W "$(__git_refs .)" -- "$cur"))
100                 ;;
101         esac
102 }
103
104 _git_branch ()
105 {
106         local cur="${COMP_WORDS[COMP_CWORD]}"
107         COMPREPLY=($(compgen -W "-l -f -d -D $(__git_refs .)" -- "$cur"))
108 }
109
110 _git_cat_file ()
111 {
112         local cur="${COMP_WORDS[COMP_CWORD]}"
113         case "${COMP_WORDS[0]},$COMP_CWORD" in
114         git-cat-file*,1)
115                 COMPREPLY=($(compgen -W "-p -t blob tree commit tag" -- "$cur"))
116                 ;;
117         git,2)
118                 COMPREPLY=($(compgen -W "-p -t blob tree commit tag" -- "$cur"))
119                 ;;
120         *)
121                 __git_complete_file
122                 ;;
123         esac
124 }
125
126 _git_checkout ()
127 {
128         local cur="${COMP_WORDS[COMP_CWORD]}"
129         COMPREPLY=($(compgen -W "-l -b $(__git_refs .)" -- "$cur"))
130 }
131
132 _git_diff ()
133 {
134         __git_complete_file
135 }
136
137 _git_diff_tree ()
138 {
139         local cur="${COMP_WORDS[COMP_CWORD]}"
140         COMPREPLY=($(compgen -W "-r -p -M $(__git_refs .)" -- "$cur"))
141 }
142
143 _git_fetch ()
144 {
145         local cur="${COMP_WORDS[COMP_CWORD]}"
146
147         case "${COMP_WORDS[0]},$COMP_CWORD" in
148         git-fetch*,1)
149                 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
150                 ;;
151         git,2)
152                 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
153                 ;;
154         *)
155                 case "$cur" in
156                 *:*)
157                 cur=$(echo "$cur" | sed 's/^.*://')
158                         COMPREPLY=($(compgen -W "$(__git_refs .)" -- "$cur"))
159                         ;;
160                 *)
161                         local remote
162                         case "${COMP_WORDS[0]}" in
163                         git-fetch) remote="${COMP_WORDS[1]}" ;;
164                         git)       remote="${COMP_WORDS[2]}" ;;
165                         esac
166                         COMPREPLY=($(compgen -W "$(__git_refs2 "$remote")" -- "$cur"))
167                         ;;
168                 esac
169                 ;;
170         esac
171 }
172
173 _git_ls_remote ()
174 {
175         local cur="${COMP_WORDS[COMP_CWORD]}"
176         COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
177 }
178
179 _git_ls_tree ()
180 {
181         __git_complete_file
182 }
183
184 _git_log ()
185 {
186         local cur="${COMP_WORDS[COMP_CWORD]}"
187         case "$cur" in
188         *..*)
189                 local pfx=$(echo "$cur" | sed 's/\.\..*$/../')
190                 cur=$(echo "$cur" | sed 's/^.*\.\.//')
191                 COMPREPLY=($(compgen -P "$pfx" -W "$(__git_refs .)" -- "$cur"))
192                 ;;
193         *)
194                 COMPREPLY=($(compgen -W "$(__git_refs .)" -- "$cur"))
195                 ;;
196         esac
197 }
198
199 _git_merge_base ()
200 {
201         local cur="${COMP_WORDS[COMP_CWORD]}"
202         COMPREPLY=($(compgen -W "$(__git_refs .)" -- "$cur"))
203 }
204
205 _git_pull ()
206 {
207         local cur="${COMP_WORDS[COMP_CWORD]}"
208
209         case "${COMP_WORDS[0]},$COMP_CWORD" in
210         git-pull*,1)
211                 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
212                 ;;
213         git,2)
214                 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
215                 ;;
216         *)
217                 local remote
218                 case "${COMP_WORDS[0]}" in
219                 git-pull)  remote="${COMP_WORDS[1]}" ;;
220                 git)       remote="${COMP_WORDS[2]}" ;;
221                 esac
222                 COMPREPLY=($(compgen -W "$(__git_refs "$remote")" -- "$cur"))
223                 ;;
224         esac
225 }
226
227 _git_push ()
228 {
229         local cur="${COMP_WORDS[COMP_CWORD]}"
230
231         case "${COMP_WORDS[0]},$COMP_CWORD" in
232         git-push*,1)
233                 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
234                 ;;
235         git,2)
236                 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
237                 ;;
238         *)
239                 case "$cur" in
240                 *:*)
241                         local remote
242                         case "${COMP_WORDS[0]}" in
243                         git-push)  remote="${COMP_WORDS[1]}" ;;
244                         git)       remote="${COMP_WORDS[2]}" ;;
245                         esac
246                 cur=$(echo "$cur" | sed 's/^.*://')
247                         COMPREPLY=($(compgen -W "$(__git_refs "$remote")" -- "$cur"))
248                         ;;
249                 *)
250                         COMPREPLY=($(compgen -W "$(__git_refs2 .)" -- "$cur"))
251                         ;;
252                 esac
253                 ;;
254         esac
255 }
256
257 _git_show ()
258 {
259         local cur="${COMP_WORDS[COMP_CWORD]}"
260         COMPREPLY=($(compgen -W "$(__git_refs .)" -- "$cur"))
261 }
262
263 _git ()
264 {
265         if [ $COMP_CWORD = 1 ]; then
266                 COMPREPLY=($(compgen \
267                         -W "--version $(git help -a|egrep '^ ')" \
268                         -- "${COMP_WORDS[COMP_CWORD]}"))
269         else
270                 case "${COMP_WORDS[1]}" in
271                 branch)      _git_branch ;;
272                 cat-file)    _git_cat_file ;;
273                 checkout)    _git_checkout ;;
274                 diff)        _git_diff ;;
275                 diff-tree)   _git_diff_tree ;;
276                 fetch)       _git_fetch ;;
277                 log)         _git_log ;;
278                 ls-remote)   _git_ls_remote ;;
279                 ls-tree)     _git_ls_tree ;;
280                 pull)        _git_pull ;;
281                 push)        _git_push ;;
282                 show)        _git_show ;;
283                 show-branch) _git_log ;;
284                 whatchanged) _git_log ;;
285                 *)           COMPREPLY=() ;;
286                 esac
287         fi
288 }
289
290 _gitk ()
291 {
292         local cur="${COMP_WORDS[COMP_CWORD]}"
293         COMPREPLY=($(compgen -W "--all $(__git_refs .)" -- "$cur"))
294 }
295
296 complete -o default -o nospace -F _git git
297 complete -o default            -F _gitk gitk
298 complete -o default            -F _git_branch git-branch
299 complete -o default -o nospace -F _git_cat_file git-cat-file
300 complete -o default            -F _git_checkout git-checkout
301 complete -o default -o nospace -F _git_diff git-diff
302 complete -o default            -F _git_diff_tree git-diff-tree
303 complete -o default -o nospace -F _git_fetch git-fetch
304 complete -o default -o nospace -F _git_log git-log
305 complete -o default            -F _git_ls_remote git-ls-remote
306 complete -o default -o nospace -F _git_ls_tree git-ls-tree
307 complete -o default            -F _git_merge_base git-merge-base
308 complete -o default -o nospace -F _git_pull git-pull
309 complete -o default -o nospace -F _git_push git-push
310 complete -o default            -F _git_show git-show
311 complete -o default -o nospace -F _git_log git-whatchanged
312
313 # The following are necessary only for Cygwin, and only are needed
314 # when the user has tab-completed the executable name and consequently
315 # included the '.exe' suffix.
316 #
317 complete -o default -o nospace -F _git_cat_file git-cat-file.exe
318 complete -o default -o nospace -F _git_diff git-diff.exe
319 complete -o default -o nospace -F _git_diff_tree git-diff-tree.exe
320 complete -o default -o nospace -F _git_log git-log.exe
321 complete -o default -o nospace -F _git_ls_tree git-ls-tree.exe
322 complete -o default            -F _git_merge_base git-merge-base.exe
323 complete -o default -o nospace -F _git_push git-push.exe
324 complete -o default -o nospace -F _git_log git-whatchanged.exe