git-completion.bash: pass $__git_subcommand_idx from __git_main()

Many completion functions perform hardcoded comparisons with $cword. This fails in the case where the main git command is given arguments (e.g. `git -C . bundle<TAB>` would fail to complete its subcommands). Even _git_worktree(), which uses __git_find_on_cmdline(), could still fail. With something like `git -C add worktree move<TAB>`, the subcommand would be incorrectly identified as "add" instead of "move". Assign $__git_subcommand_idx in __git_main(), where the git subcommand is actually found and the corresponding completion function is called. Use this variable to replace hardcoded comparisons with $cword. Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Denton Liu committed Mar 24, 2021 at 01:36 UTC e94fb4404280c07a668b4669c072983cdd079592
1 file changed +11 -12
contrib/completion/git-completion.bash
+11 -12
@@ -1474,12 +1474,12 @@ _git_branch ()
1474
1475 _git_bundle ()
1476 {
1477 - local cmd="${words[2]}"
1477 + local cmd="${words[__git_subcommand_idx+1]}"
1478 case "$cword" in
1479 - 2)
1479 + $((__git_subcommand_idx+1)))
1480 __gitcomp "create list-heads verify unbundle"
1481 ;;
1482 - 3)
1482 + $((__git_subcommand_idx+2)))
1483 # looking for a file
1484 ;;
1485 *)
@@ -1894,7 +1894,7 @@ _git_grep ()
1894 esac
1895
1896 case "$cword,$prev" in
1897 - 2,*|*,-*)
1897 + $((__git_subcommand_idx+1)),*|*,-*)
1898 __git_complete_symbol && return
1899 ;;
1900 esac
@@ -3058,7 +3058,7 @@ _git_stash ()
3058 branch,--*)
3059 ;;
3060 branch,*)
3061 - if [ $cword -eq 3 ]; then
3061 + if [ $cword -eq $((__git_subcommand_idx+2)) ]; then
3062 __git_complete_refs
3063 else
3064 __gitcomp_nl "$(__git stash list \
@@ -3277,11 +3277,9 @@ __git_complete_worktree_paths ()
3277 _git_worktree ()
3278 {
3279 local subcommands="add list lock move prune remove unlock"
3280 - local subcommand subcommand_idx
3280 + local subcommand
3281
3282 - subcommand="$(__git_find_on_cmdline --show-idx "$subcommands")"
3283 - subcommand_idx="${subcommand% *}"
3284 - subcommand="${subcommand#* }"
3282 + subcommand="$(__git_find_on_cmdline "$subcommands")"
3283
3284 case "$subcommand,$cur" in
3285 ,*)
@@ -3306,7 +3304,7 @@ _git_worktree ()
3304 # be either the 'add' subcommand, the unstuck
3305 # argument of an option (e.g. branch for -b|-B), or
3306 # the path for the new worktree.
3309 - if [ $cword -eq $((subcommand_idx+1)) ]; then
3307 + if [ $cword -eq $((__git_subcommand_idx+2)) ]; then
3308 # Right after the 'add' subcommand: have to
3309 # complete the path, so fall back to Bash
3310 # filename completion.
@@ -3330,7 +3328,7 @@ _git_worktree ()
3328 __git_complete_worktree_paths
3329 ;;
3330 move,*)
3333 - if [ $cword -eq $((subcommand_idx+1)) ]; then
3331 + if [ $cword -eq $((__git_subcommand_idx+2)) ]; then
3332 # The first parameter must be an existing working
3333 # tree to be moved.
3334 __git_complete_worktree_paths
@@ -3398,6 +3396,7 @@ __git_main ()
3396 {
3397 local i c=1 command __git_dir __git_repo_path
3398 local __git_C_args C_args_count=0
3399 + local __git_subcommand_idx
3400
3401 while [ $c -lt $cword ]; do
3402 i="${words[c]}"
@@ -3412,7 +3411,7 @@ __git_main ()
3411 __git_C_args[C_args_count++]="${words[c]}"
3412 ;;
3413 -*) ;;
3415 - *) command="$i"; break ;;
3414 + *) command="$i"; __git_subcommand_idx="$c"; break ;;
3415 esac
3416 ((c++))
3417 done