Skip to content

Commit 336d694

Browse files
szedergitster
authored andcommitted
completion: fix completion after 'git -C <path>'
The main completion function finds the name of the git command by iterating through all the words on the command line in search for the first non-option-looking word. As it is not aware of 'git -C's mandatory path argument, if the '-C <path>' option is present, 'path' will be the first such word and it will be mistaken for a git command. This breaks completion in various ways: - If 'path' happens to match one of the commands supported by the completion script, then options of that command will be offered. - If 'path' doesn't match a supported command and doesn't contain any characters not allowed in Bash identifier names, then the completion script does basically nothing and Bash in turn falls back to filename completion for all subsequent words. - Otherwise, if 'path' does contain such an unallowed character, then it leads to a more or less ugly error message in the middle of the command line. The standard '/' directory separator is such a character, and it happens to trigger one of the uglier errors: $ git -C some/path <TAB>sh.exe": declare: `_git_some/path': not a valid identifier error: invalid key: alias.some/path Fix this by skipping 'git -C's mandatory path argument while iterating over the words on the command line. Extend the relevant test with this case and, while at it, with cases that needed similar treatment in the past ('--git-dir', '-c', '--work-tree' and '--namespace'). Additionally, silence the standard error of the 'declare' builtins looking for the completion function associated with the git command and of the 'git config' query for the aliased command. So if git ever learns a new option with a mandatory argument in the future, then, though the completion script will again misbehave, at least the command line will not be utterly disrupted by those error messages. Signed-off-by: SZEDER Gábor <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7b329b9 commit 336d694

File tree

2 files changed

+10
-5
lines changed

2 files changed

+10
-5
lines changed

contrib/completion/git-completion.bash

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ __git_aliases ()
816816
__git_aliased_command ()
817817
{
818818
local word cmdline=$(git --git-dir="$(__gitdir)" \
819-
config --get "alias.$1")
819+
config --get "alias.$1" 2>/dev/null)
820820
for word in $cmdline; do
821821
case "$word" in
822822
\!gitk|gitk)
@@ -2800,7 +2800,7 @@ __git_main ()
28002800
--git-dir) ((c++)) ; __git_dir="${words[c]}" ;;
28012801
--bare) __git_dir="." ;;
28022802
--help) command="help"; break ;;
2803-
-c|--work-tree|--namespace) ((c++)) ;;
2803+
-c|-C|--work-tree|--namespace) ((c++)) ;;
28042804
-*) ;;
28052805
*) command="$i"; break ;;
28062806
esac
@@ -2844,13 +2844,13 @@ __git_main ()
28442844
fi
28452845

28462846
local completion_func="_git_${command//-/_}"
2847-
declare -f $completion_func >/dev/null && $completion_func && return
2847+
declare -f $completion_func >/dev/null 2>/dev/null && $completion_func && return
28482848

28492849
local expansion=$(__git_aliased_command "$command")
28502850
if [ -n "$expansion" ]; then
28512851
words[1]=$expansion
28522852
completion_func="_git_${expansion//-/_}"
2853-
declare -f $completion_func >/dev/null && $completion_func
2853+
declare -f $completion_func >/dev/null 2>/dev/null && $completion_func
28542854
fi
28552855
}
28562856

t/t9902-completion.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,12 @@ test_expect_success 'general options plus command' '
755755
test_completion "git --namespace=foo check" "checkout " &&
756756
test_completion "git --paginate check" "checkout " &&
757757
test_completion "git --info-path check" "checkout " &&
758-
test_completion "git --no-replace-objects check" "checkout "
758+
test_completion "git --no-replace-objects check" "checkout " &&
759+
test_completion "git --git-dir some/path check" "checkout " &&
760+
test_completion "git -c conf.var=value check" "checkout " &&
761+
test_completion "git -C some/path check" "checkout " &&
762+
test_completion "git --work-tree some/path check" "checkout " &&
763+
test_completion "git --namespace name/space check" "checkout "
759764
'
760765

761766
test_expect_success 'git --help completion' '

0 commit comments

Comments
 (0)