git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] completion: fix completion after 'git -C path'

From
SZEDER Gábor <szeder@ira.uka.de>
Date
Oct 5, 2015, 12:02 UTC
Message-ID
<1444046535-18316-1-git-send-email-szeder@ira.uka.de>

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 the completion script in various ways:

 - If 'path' happens to match one of the commands supported by the
   completion script, then its options 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 lets Bash to fall back to filename
   completion.
 - Otherwise, if 'path' contains such unallowed characters, then it
   leads to a more or less ugly error 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, shut up standard error of the 'declare' commands looking for the associated completion function and of the 'git config' query for the aliased command, so if git learns a new option with a mandatory argument in the future, then at least the command line will not be utterly disrupted by those error messages.

Note, that this change merely fixes the breakage related to 'git -C path', but the completion script will not take it into account as it does '--git-dir path'.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-completion.bash | 8 ++++----
 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 482ca84b45..80dc717fe2 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -763,7 +763,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)
@@ -2571,7 +2571,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
@@ -2604,13 +2604,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 2ba62fbc17..f5a669918d 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -480,7 +480,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' '
-- 
2.6.0.rc2.22.g7128296
Next: Michael J Gruber
Message 1 of 3 in “completion: fix completion after 'git -C path'”
  1. completion: fix completion after 'git -C path'SZEDER Gábor, Oct 5, 2015
  2. Michael J GruberOct 6, 2015
  3. SZEDER GáborOct 6, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.