contrib / completion / git-completion.bashon commit daemon: do not die on older clients. (83543a2)
   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
 296complete -o default -o nospace -F _git git
 297complete -o default            -F _gitk gitk
 298complete -o default            -F _git_branch git-branch
 299complete -o default -o nospace -F _git_cat_file git-cat-file
 300complete -o default            -F _git_checkout git-checkout
 301complete -o default -o nospace -F _git_diff git-diff
 302complete -o default            -F _git_diff_tree git-diff-tree
 303complete -o default -o nospace -F _git_fetch git-fetch
 304complete -o default -o nospace -F _git_log git-log
 305complete -o default            -F _git_ls_remote git-ls-remote
 306complete -o default -o nospace -F _git_ls_tree git-ls-tree
 307complete -o default            -F _git_merge_base git-merge-base
 308complete -o default -o nospace -F _git_pull git-pull
 309complete -o default -o nospace -F _git_push git-push
 310complete -o default            -F _git_show git-show
 311complete -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#
 317complete -o default -o nospace -F _git_cat_file git-cat-file.exe
 318complete -o default -o nospace -F _git_diff git-diff.exe
 319complete -o default -o nospace -F _git_diff_tree git-diff-tree.exe
 320complete -o default -o nospace -F _git_log git-log.exe
 321complete -o default -o nospace -F _git_ls_tree git-ls-tree.exe
 322complete -o default            -F _git_merge_base git-merge-base.exe
 323complete -o default -o nospace -F _git_push git-push.exe
 324complete -o default -o nospace -F _git_log git-whatchanged.exe