The compgen Bash-builtin performs expansion on all words in the wordlist given to its -W option, breaking Git's completion script when refs or filenames passed to __gitcomp_nl() contain expandable substrings. At least one user can't use ref completion at all in a repository, which contains tags with metacharacters like Build%20V%20${bamboo.custom.jiraversion.name}%20Build%20721 Such a ref causes a failure in compgen as it tries to expand the variable with invalid name. Unfortunately, compgen has no option to turn off this expansion. However, in __gitcomp_nl() we use only a small subset of compgen's functionality, namely the filtering of matching possible completion words and adding a prefix and/or suffix to each of those words. So, to avoid compgen's problematic expansion we get rid of compgen, and implement the equivalent functionality in a small awk script. The reason for using awk instead of sed is that awk allows plain (i.e. non-regexp) string comparison, making quoting of regexp characters in the current word unnecessary. Note, that such expandable words need quoting to be of any use on the command line. This patch doesn't perform that quoting, but it could be implemented later on top by extending the awk script to unquote $cur and to quote matching words. Nonetheless, this patch still a step forward, because at least refs can be completed even in the presence of one with metacharacters. Also update the function's description a bit. Reported-by: Jeroen Meijer <jjgmeijer@xxxxxxxxxxx> Signed-off-by: SZEDER Gábor <szeder@xxxxxxxxxx> --- awk doesn't have a prefixcmp(). I'm no awk wizard, so I'm not sure this is the right way to do it. contrib/completion/git-completion.bash | 17 +++++++++++++---- t/t9902-completion.sh | 4 ++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index bc0657a2..65196ddd 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -249,19 +249,28 @@ __gitcomp () esac } -# Generates completion reply with compgen from newline-separated possible -# completion words by appending a space to all of them. +# Generates completion reply for the word in $cur from newline-separated +# possible completion words, appending a space to all of them. # It accepts 1 to 4 arguments: # 1: List of possible completion words, separated by a single newline. # 2: A prefix to be added to each possible completion word (optional). -# 3: Generate possible completion matches for this word (optional). +# 3: Generate possible completion matches for this word instead of $cur +# (optional). # 4: A suffix to be appended to each possible completion word instead of # the default space (optional). If specified but empty, nothing is # appended. __gitcomp_nl () { local IFS=$'\n' - COMPREPLY=($(compgen -P "${2-}" -S "${4- }" -W "$1" -- "${3-$cur}")) + COMPREPLY=($(awk -v pfx="${2-}" -v sfx="${4- }" -v cur="${3-$cur}" ' + BEGIN { + FS="\n"; + len=length(cur); + } + { + if (cur == substr($1, 1, len)) + print pfx$1sfx; + }' <<< "$1" )) } __git_heads () diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index a108ec1c..fa289324 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -246,7 +246,7 @@ test_expect_success '__gitcomp_nl - no suffix' ' test_cmp expected out ' -test_expect_failure '__gitcomp_nl - doesnt fail because of invalid variable name' ' +test_expect_success '__gitcomp_nl - doesnt fail because of invalid variable name' ' ( __gitcomp_nl "$invalid_variable_name" ) @@ -383,7 +383,7 @@ test_expect_success 'complete tree filename with spaces' ' EOF ' -test_expect_failure 'complete tree filename with metacharacters' ' +test_expect_success 'complete tree filename with metacharacters' ' echo content >"name with \${meta}" && git add . && git commit -m meta && -- 1.8.0.220.g4d14ece -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html