diff options
author | SZEDER Gábor <szeder.dev@gmail.com> | 2017-02-03 03:48:22 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2017-02-03 22:18:41 -0800 |
commit | 336d694ce4bff3e7cdedb3df1f819280026aa19f (patch) | |
tree | c9f722f7425e1bbcb6754e91af7c492518c8c126 | |
parent | 7b329b9dab276d7a90141a1c9260a6943c9dd007 (diff) | |
download | git-336d694ce4bff3e7cdedb3df1f819280026aa19f.tar.gz |
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 <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | contrib/completion/git-completion.bash | 8 | ||||
-rwxr-xr-x | t/t9902-completion.sh | 7 |
2 files changed, 10 insertions, 5 deletions
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 92231c66da..262760f8c0 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -816,7 +816,7 @@ __git_aliases () __git_aliased_command () { local word cmdline=$(git --git-dir="$(__gitdir)" \ - config --get "alias.$1") + config --get "alias.$1" 2>/dev/null) for word in $cmdline; do case "$word" in \!gitk|gitk) @@ -2800,7 +2800,7 @@ __git_main () --git-dir) ((c++)) ; __git_dir="${words[c]}" ;; --bare) __git_dir="." ;; --help) command="help"; break ;; - -c|--work-tree|--namespace) ((c++)) ;; + -c|-C|--work-tree|--namespace) ((c++)) ;; -*) ;; *) command="$i"; break ;; esac @@ -2844,13 +2844,13 @@ __git_main () fi local completion_func="_git_${command//-/_}" - declare -f $completion_func >/dev/null && $completion_func && return + declare -f $completion_func >/dev/null 2>/dev/null && $completion_func && return local expansion=$(__git_aliased_command "$command") if [ -n "$expansion" ]; then words[1]=$expansion completion_func="_git_${expansion//-/_}" - declare -f $completion_func >/dev/null && $completion_func + declare -f $completion_func >/dev/null 2>/dev/null && $completion_func fi } diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index 500505dca1..be2ed87043 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -755,7 +755,12 @@ test_expect_success 'general options plus command' ' test_completion "git --namespace=foo check" "checkout " && test_completion "git --paginate check" "checkout " && test_completion "git --info-path check" "checkout " && - test_completion "git --no-replace-objects check" "checkout " + test_completion "git --no-replace-objects check" "checkout " && + test_completion "git --git-dir some/path check" "checkout " && + test_completion "git -c conf.var=value check" "checkout " && + test_completion "git -C some/path check" "checkout " && + test_completion "git --work-tree some/path check" "checkout " && + test_completion "git --namespace name/space check" "checkout " ' test_expect_success 'git --help completion' ' |