Merge branch 'svn-fe' of git://repo.or.cz/git/jrn into jn/svn-fe
[gitweb.git] / contrib / completion / git-completion.bash
index 3f7a776a9d92f70d5275fb55a528a46fed2c11fc..b0062bac22347e42dd64047c51dfb2bff92243ef 100755 (executable)
@@ -110,7 +110,8 @@ __git_ps1_show_upstream ()
        local upstream=git legacy="" verbose=""
 
        # get some config options from git-config
-       while read key value; do
+       local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
+       while read -r key value; do
                case "$key" in
                bash.showupstream)
                        GIT_PS1_SHOWUPSTREAM="$value"
@@ -125,7 +126,7 @@ __git_ps1_show_upstream ()
                        upstream=svn+git # default upstream is SVN if available, else git
                        ;;
                esac
-       done < <(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')
+       done <<< "$output"
 
        # parse configuration values
        for option in ${GIT_PS1_SHOWUPSTREAM}; do
@@ -537,42 +538,24 @@ __gitcomp_nl ()
        COMPREPLY=($(compgen -P "${2-}" -S "$suffix" -W "$1" -- "$cur_"))
 }
 
-# __git_heads accepts 0 or 1 arguments (to pass to __gitdir)
 __git_heads ()
 {
-       local cmd i is_hash=y dir="$(__gitdir "${1-}")"
+       local dir="$(__gitdir)"
        if [ -d "$dir" ]; then
                git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
                        refs/heads
                return
        fi
-       for i in $(git ls-remote "${1-}" 2>/dev/null); do
-               case "$is_hash,$i" in
-               y,*) is_hash=n ;;
-               n,*^{}) is_hash=y ;;
-               n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
-               n,*) is_hash=y; echo "$i" ;;
-               esac
-       done
 }
 
-# __git_tags accepts 0 or 1 arguments (to pass to __gitdir)
 __git_tags ()
 {
-       local cmd i is_hash=y dir="$(__gitdir "${1-}")"
+       local dir="$(__gitdir)"
        if [ -d "$dir" ]; then
                git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
                        refs/tags
                return
        fi
-       for i in $(git ls-remote "${1-}" 2>/dev/null); do
-               case "$is_hash,$i" in
-               y,*) is_hash=n ;;
-               n,*^{}) is_hash=y ;;
-               n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
-               n,*) is_hash=y; echo "$i" ;;
-               esac
-       done
 }
 
 # __git_refs accepts 0, 1 (to pass to __gitdir), or 2 arguments
@@ -580,7 +563,7 @@ __git_tags ()
 # by checkout for tracking branches
 __git_refs ()
 {
-       local i is_hash=y dir="$(__gitdir "${1-}")" track="${2-}"
+       local i hash dir="$(__gitdir "${1-}")" track="${2-}"
        local format refs
        if [ -d "$dir" ]; then
                case "$cur" in
@@ -606,7 +589,7 @@ __git_refs ()
                        local ref entry
                        git --git-dir="$dir" for-each-ref --shell --format="ref=%(refname:short)" \
                                "refs/remotes/" | \
-                       while read entry; do
+                       while read -r entry; do
                                eval "$entry"
                                ref="${ref#*/}"
                                if [[ "$ref" == "$cur"* ]]; then
@@ -616,14 +599,27 @@ __git_refs ()
                fi
                return
        fi
-       for i in $(git ls-remote "$dir" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null); do
-               case "$is_hash,$i" in
-               y,*) is_hash=n ;;
-               n,*^{}) is_hash=y ;;
-               n,refs/*) is_hash=y; echo "${i#refs/*/}" ;;
-               n,*) is_hash=y; echo "$i" ;;
-               esac
-       done
+       case "$cur" in
+       refs|refs/*)
+               git ls-remote "$dir" "$cur*" 2>/dev/null | \
+               while read -r hash i; do
+                       case "$i" in
+                       *^{}) ;;
+                       *) echo "$i" ;;
+                       esac
+               done
+               ;;
+       *)
+               git ls-remote "$dir" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \
+               while read -r hash i; do
+                       case "$i" in
+                       *^{}) ;;
+                       refs/*) echo "${i#refs/*/}" ;;
+                       *) echo "$i" ;;
+                       esac
+               done
+               ;;
+       esac
 }
 
 # __git_refs2 requires 1 argument (to pass to __git_refs)
@@ -638,18 +634,10 @@ __git_refs2 ()
 # __git_refs_remotes requires 1 argument (to pass to ls-remote)
 __git_refs_remotes ()
 {
-       local cmd i is_hash=y
-       for i in $(git ls-remote "$1" 2>/dev/null); do
-               case "$is_hash,$i" in
-               n,refs/heads/*)
-                       is_hash=y
-                       echo "$i:refs/remotes/$1/${i#refs/heads/}"
-                       ;;
-               y,*) is_hash=n ;;
-               n,*^{}) is_hash=y ;;
-               n,refs/tags/*) is_hash=y;;
-               n,*) is_hash=y; ;;
-               esac
+       local i hash
+       git ls-remote "$1" 'refs/heads/*' 2>/dev/null | \
+       while read -r hash i; do
+               echo "$i:refs/remotes/$1/${i#refs/heads/}"
        done
 }
 
@@ -1457,6 +1445,10 @@ _git_gitk ()
        _gitk
 }
 
+__git_match_ctag() {
+       awk "/^${1////\\/}/ { print \$1 }" "$2"
+}
+
 _git_grep ()
 {
        __git_has_doubledash && return
@@ -1479,6 +1471,15 @@ _git_grep ()
                ;;
        esac
 
+       case "$cword,$prev" in
+       2,*|*,-*)
+               if test -r tags; then
+                       __gitcomp_nl "$(__git_match_ctag "$cur" tags)"
+                       return
+               fi
+               ;;
+       esac
+
        __gitcomp_nl "$(__git_refs)"
 }
 
@@ -1862,7 +1863,7 @@ __git_config_get_set_variables ()
        done
 
        git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null |
-       while read line
+       while read -r line
        do
                case "$line" in
                *.*=*)
@@ -1886,6 +1887,10 @@ _git_config ()
        remote.*.fetch)
                local remote="${prev#remote.}"
                remote="${remote%.fetch}"
+               if [ -z "$cur" ]; then
+                       COMPREPLY=("refs/heads/")
+                       return
+               fi
                __gitcomp_nl "$(__git_refs_remotes "$remote")"
                return
                ;;