bash completion: fix completion issues with fetch, pull, and push
authorJay Soffian <jaysoffian@gmail.com>
Fri, 6 Mar 2009 04:39:31 +0000 (23:39 -0500)
committerJunio C Hamano <gitster@pobox.com>
Sun, 8 Mar 2009 04:19:45 +0000 (20:19 -0800)
Sverre Rabbelier noticed a completion issue with push:

 $ git push ori<tab>
 git push origin

 $ git push -f ori<tab>
 git push -f origin/

Markus Heidelberg pointed out that the issue extends to fetch and pull.

The reason is that the current code naively assumes that if
COMP_CWORD=2, it should complete a remote name, otherwise it should
complete a refspec. This assumption fails if there are any --options.

This patch fixes that issue by instead scanning COMP_CWORDS to see if
the remote has been completed yet (we now assume the first non-dashed
argument is the remote). The new logic is factored into a function,
shared by fetch, pull, and push.

The new function also properly handles '.' as the remote.

Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
Acked-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib/completion/git-completion.bash

index f234c34304181d0c6b00349be3bd9c14d1e538ea..e8c4be2e818ca30a87e7c11f10442c4c7862346f 100755 (executable)
@@ -387,6 +387,63 @@ __git_complete_revlist ()
        esac
 }
 
+__git_complete_remote_or_refspec ()
+{
+       local cmd="${COMP_WORDS[1]}"
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+       local i c=2 remote="" pfx="" lhs=1
+       while [ $c -lt $COMP_CWORD ]; do
+               i="${COMP_WORDS[c]}"
+               case "$i" in
+               -*) ;;
+               *) remote="$i"; break ;;
+               esac
+               c=$((++c))
+       done
+       if [ -z "$remote" ]; then
+               __gitcomp "$(__git_remotes)"
+               return
+       fi
+       [ "$remote" = "." ] && remote=
+       case "$cur" in
+       *:*)
+               case "$COMP_WORDBREAKS" in
+               *:*) : great ;;
+               *)   pfx="${cur%%:*}:" ;;
+               esac
+               cur="${cur#*:}"
+               lhs=0
+               ;;
+       +*)
+               pfx="+"
+               cur="${cur#+}"
+               ;;
+       esac
+       case "$cmd" in
+       fetch)
+               if [ $lhs = 1 ]; then
+                       __gitcomp "$(__git_refs2 "$remote")" "$pfx" "$cur"
+               else
+                       __gitcomp "$(__git_refs)" "$pfx" "$cur"
+               fi
+               ;;
+       pull)
+               if [ $lhs = 1 ]; then
+                       __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
+               else
+                       __gitcomp "$(__git_refs)" "$pfx" "$cur"
+               fi
+               ;;
+       push)
+               if [ $lhs = 1 ]; then
+                       __gitcomp "$(__git_refs)" "$pfx" "$cur"
+               else
+                       __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
+               fi
+               ;;
+       esac
+}
+
 __git_all_commands ()
 {
        if [ -n "${__git_all_commandlist-}" ]; then
@@ -832,25 +889,7 @@ _git_diff ()
 
 _git_fetch ()
 {
-       local cur="${COMP_WORDS[COMP_CWORD]}"
-
-       if [ "$COMP_CWORD" = 2 ]; then
-               __gitcomp "$(__git_remotes)"
-       else
-               case "$cur" in
-               *:*)
-                       local pfx=""
-                       case "$COMP_WORDBREAKS" in
-                       *:*) : great ;;
-                       *)   pfx="${cur%%:*}:" ;;
-                       esac
-                       __gitcomp "$(__git_refs)" "$pfx" "${cur#*:}"
-                       ;;
-               *)
-                       __gitcomp "$(__git_refs2 "${COMP_WORDS[2]}")"
-                       ;;
-               esac
-       fi
+       __git_complete_remote_or_refspec
 }
 
 _git_format_patch ()
@@ -1120,40 +1159,12 @@ _git_name_rev ()
 
 _git_pull ()
 {
-       local cur="${COMP_WORDS[COMP_CWORD]}"
-
-       if [ "$COMP_CWORD" = 2 ]; then
-               __gitcomp "$(__git_remotes)"
-       else
-               __gitcomp "$(__git_refs "${COMP_WORDS[2]}")"
-       fi
+       __git_complete_remote_or_refspec
 }
 
 _git_push ()
 {
-       local cur="${COMP_WORDS[COMP_CWORD]}"
-
-       if [ "$COMP_CWORD" = 2 ]; then
-               __gitcomp "$(__git_remotes)"
-       else
-               case "$cur" in
-               *:*)
-                       local pfx=""
-                       case "$COMP_WORDBREAKS" in
-                       *:*) : great ;;
-                       *)   pfx="${cur%%:*}:" ;;
-                       esac
-
-                       __gitcomp "$(__git_refs "${COMP_WORDS[2]}")" "$pfx" "${cur#*:}"
-                       ;;
-               +*)
-                       __gitcomp "$(__git_refs)" + "${cur#+}"
-                       ;;
-               *)
-                       __gitcomp "$(__git_refs)"
-                       ;;
-               esac
-       fi
+       __git_complete_remote_or_refspec
 }
 
 _git_rebase ()