]> git.ipfire.org Git - thirdparty/git.git/blobdiff - contrib/completion/git-completion.bash
completion: bash: improve alias loop detection
[thirdparty/git.git] / contrib / completion / git-completion.bash
index 0a96ad87e7b6d8723175d3b97c18921ddc737d7b..1ed03623cd754b1182ed7f6b3d58f9e913c18b7b 100644 (file)
@@ -416,14 +416,13 @@ __gitcomp_builtin ()
        local options
        eval "options=\${$var-}"
 
-       local completion_helper
-       if [ "$GIT_COMPLETION_SHOW_ALL" = "1" ]; then
-               completion_helper="--git-completion-helper-all"
-       else
-               completion_helper="--git-completion-helper"
-       fi
-
        if [ -z "$options" ]; then
+               local completion_helper
+               if [ "$GIT_COMPLETION_SHOW_ALL" = "1" ]; then
+                       completion_helper="--git-completion-helper-all"
+               else
+                       completion_helper="--git-completion-helper"
+               fi
                # leading and trailing spaces are significant to make
                # option removal work correctly.
                options=" $incl $(__git ${cmd/_/ } $completion_helper) " || return
@@ -1121,26 +1120,44 @@ __git_pretty_aliases ()
 # __git_aliased_command requires 1 argument
 __git_aliased_command ()
 {
-       local word cmdline=$(__git config --get "alias.$1")
-       for word in $cmdline; do
-               case "$word" in
-               \!gitk|gitk)
-                       echo "gitk"
-                       return
-                       ;;
-               \!*)    : shell command alias ;;
-               -*)     : option ;;
-               *=*)    : setting env ;;
-               git)    : git itself ;;
-               \(\))   : skip parens of shell function definition ;;
-               {)      : skip start of shell helper function ;;
-               :)      : skip null command ;;
-               \'*)    : skip opening quote after sh -c ;;
-               *)
-                       echo "$word"
+       local cur=$1 last list word cmdline
+
+       while [[ -n "$cur" ]]; do
+               if [[ "$list" == *" $cur "* ]]; then
+                       # loop detected
                        return
-               esac
+               fi
+
+               cmdline=$(__git config --get "alias.$cur")
+               list=" $cur $list"
+               last=$cur
+               cur=
+
+               for word in $cmdline; do
+                       case "$word" in
+                       \!gitk|gitk)
+                               cur="gitk"
+                               break
+                               ;;
+                       \!*)    : shell command alias ;;
+                       -*)     : option ;;
+                       *=*)    : setting env ;;
+                       git)    : git itself ;;
+                       \(\))   : skip parens of shell function definition ;;
+                       {)      : skip start of shell helper function ;;
+                       :)      : skip null command ;;
+                       \'*)    : skip opening quote after sh -c ;;
+                       *)
+                               cur="$word"
+                               break
+                       esac
+               done
        done
+
+       cur=$last
+       if [[ "$cur" != "$1" ]]; then
+               echo "$cur"
+       fi
 }
 
 # Check whether one of the given words is present on the command line,
@@ -1467,14 +1484,15 @@ _git_bundle ()
 # Helper function to decide whether or not we should enable DWIM logic for
 # git-switch and git-checkout.
 #
-# To decide between the following rules in priority order
-# 1) the last provided of "--guess" or "--no-guess" explicitly enable or
-#    disable completion of DWIM logic respectively.
-# 2) If the --no-track option is provided, take this as a hint to disable the
-#    DWIM completion logic
-# 3) If GIT_COMPLETION_CHECKOUT_NO_GUESS is set, disable the DWIM completion
-#    logic, as requested by the user.
-# 4) Enable DWIM logic otherwise.
+# To decide between the following rules in decreasing priority order:
+# - the last provided of "--guess" or "--no-guess" explicitly enable or
+#   disable completion of DWIM logic respectively.
+# - If checkout.guess is false, disable completion of DWIM logic.
+# - If the --no-track option is provided, take this as a hint to disable the
+#   DWIM completion logic
+# - If GIT_COMPLETION_CHECKOUT_NO_GUESS is set, disable the DWIM completion
+#   logic, as requested by the user.
+# - Enable DWIM logic otherwise.
 #
 __git_checkout_default_dwim_mode ()
 {
@@ -1485,11 +1503,17 @@ __git_checkout_default_dwim_mode ()
        fi
 
        # --no-track disables DWIM, but with lower priority than
-       # --guess/--no-guess
+       # --guess/--no-guess/checkout.guess
        if [ -n "$(__git_find_on_cmdline "--no-track")" ]; then
                dwim_opt=""
        fi
 
+       # checkout.guess = false disables DWIM, but with lower priority than
+       # --guess/--no-guess
+       if [ "$(__git config --type=bool checkout.guess)" = "false" ]; then
+               dwim_opt=""
+       fi
+
        # Find the last provided --guess or --no-guess
        last_option="$(__git_find_last_on_cmdline "--guess --no-guess")"
        case "$last_option" in
@@ -1688,8 +1712,13 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
                        --submodule --submodule= --ignore-submodules
                        --indent-heuristic --no-indent-heuristic
                        --textconv --no-textconv
+                       --patch --no-patch
 "
 
+__git_diff_difftool_options="--cached --staged --pickaxe-all --pickaxe-regex
+                       --base --ours --theirs --no-index --relative --merge-base
+                       $__git_diff_common_options"
+
 _git_diff ()
 {
        __git_has_doubledash && return
@@ -1712,10 +1741,7 @@ _git_diff ()
                return
                ;;
        --*)
-               __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
-                       --base --ours --theirs --no-index
-                       $__git_diff_common_options
-                       "
+               __gitcomp "$__git_diff_difftool_options"
                return
                ;;
        esac
@@ -1737,11 +1763,7 @@ _git_difftool ()
                return
                ;;
        --*)
-               __gitcomp_builtin difftool "$__git_diff_common_options
-                                       --base --cached --ours --theirs
-                                       --pickaxe-all --pickaxe-regex
-                                       --relative --staged
-                                       "
+               __gitcomp_builtin difftool "$__git_diff_difftool_options"
                return
                ;;
        esac
@@ -2031,11 +2053,9 @@ _git_log ()
                        --no-walk --no-walk= --do-walk
                        --parents --children
                        --expand-tabs --expand-tabs= --no-expand-tabs
-                       --patch
                        $merge
                        $__git_diff_common_options
                        --pickaxe-all --pickaxe-regex
-                       --patch --no-patch
                        "
                return
                ;;
@@ -2938,7 +2958,7 @@ _git_show ()
                ;;
        --*)
                __gitcomp "--pretty= --format= --abbrev-commit --no-abbrev-commit
-                       --oneline --show-signature --patch
+                       --oneline --show-signature
                        --expand-tabs --expand-tabs= --no-expand-tabs
                        $__git_diff_common_options
                        "
@@ -3021,7 +3041,10 @@ _git_stash ()
                list,--*)
                        __gitcomp "--name-status --oneline --patch-with-stat"
                        ;;
-               show,--*|branch,--*)
+               show,--*)
+                       __gitcomp "$__git_diff_common_options"
+                       ;;
+               branch,--*)
                        ;;
                branch,*)
                        if [ $cword -eq 3 ]; then
@@ -3458,88 +3481,8 @@ __gitk_main ()
        __git_complete_revlist
 }
 
-if [[ -n ${ZSH_VERSION-} ]] &&
-   # Don't define these functions when sourced from 'git-completion.zsh',
-   # it has its own implementations.
-   [[ -z ${GIT_SOURCING_ZSH_COMPLETION-} ]]; then
-       echo "WARNING: this script is deprecated, please see git-completion.zsh" 1>&2
-
-       autoload -U +X compinit && compinit
-
-       __gitcomp ()
-       {
-               emulate -L zsh
-
-               local cur_="${3-$cur}"
-
-               case "$cur_" in
-               --*=)
-                       ;;
-               *)
-                       local c IFS=$' \t\n'
-                       local -a array
-                       for c in ${=1}; do
-                               c="$c${4-}"
-                               case $c in
-                               --*=*|*.) ;;
-                               *) c="$c " ;;
-                               esac
-                               array[${#array[@]}+1]="$c"
-                       done
-                       compset -P '*[=:]'
-                       compadd -Q -S '' -p "${2-}" -a -- array && _ret=0
-                       ;;
-               esac
-       }
-
-       __gitcomp_direct ()
-       {
-               emulate -L zsh
-
-               local IFS=$'\n'
-               compset -P '*[=:]'
-               compadd -Q -- ${=1} && _ret=0
-       }
-
-       __gitcomp_nl ()
-       {
-               emulate -L zsh
-
-               local IFS=$'\n'
-               compset -P '*[=:]'
-               compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0
-       }
-
-       __gitcomp_file_direct ()
-       {
-               emulate -L zsh
-
-               local IFS=$'\n'
-               compset -P '*[=:]'
-               compadd -f -- ${=1} && _ret=0
-       }
-
-       __gitcomp_file ()
-       {
-               emulate -L zsh
-
-               local IFS=$'\n'
-               compset -P '*[=:]'
-               compadd -p "${2-}" -f -- ${=1} && _ret=0
-       }
-
-       _git ()
-       {
-               local _ret=1 cur cword prev
-               cur=${words[CURRENT]}
-               prev=${words[CURRENT-1]}
-               let cword=CURRENT-1
-               emulate ksh -c __${service}_main
-               let _ret && _default && _ret=0
-               return _ret
-       }
-
-       compdef _git git gitk
+if [[ -n ${ZSH_VERSION-} && -z ${GIT_SOURCING_ZSH_COMPLETION-} ]]; then
+       echo "ERROR: this script is obsolete, please see git-completion.zsh" 1>&2
        return
 fi
 
@@ -3561,18 +3504,6 @@ __git_complete ()
                || complete -o default -o nospace -F $wrapper $1
 }
 
-# wrapper for backwards compatibility
-_git ()
-{
-       __git_wrap__git_main
-}
-
-# wrapper for backwards compatibility
-_gitk ()
-{
-       __git_wrap__gitk_main
-}
-
 __git_complete git __git_main
 __git_complete gitk __gitk_main
 
@@ -3580,6 +3511,6 @@ __git_complete gitk __gitk_main
 # when the user has tab-completed the executable name and consequently
 # included the '.exe' suffix.
 #
-if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
-__git_complete git.exe __git_main
+if [ "$OSTYPE" = cygwin ]; then
+       __git_complete git.exe __git_main
 fi