Completing full refs currently only works when the full ref stands on in its own on the command line, but doesn't work when the current word to be completed contains a prefix before the full ref, e.g. '--option=refs/<TAB>' or 'master..refs/bis<TAB>'. The reason is that __git_refs() looks at the current word to be completed ($cur) as a whole to decide whether it has to list full (if it starts with 'refs/') or short refs (otherwise). However, $cur also holds said '--option=' or 'master..' prefixes, which of course throw off this decision. Luckily, the default action is to list short refs, that's why completing short refs happens to work even after a 'master..<TAB>' prefix and similar cases. Pass only the ref part of the current word to be completed to __git_refs() as a new positional parameter, so it can make the right decision even if the whole current word contains some kind of a prefix. Make this new parameter the 4. positional parameter and leave the 3. as an ignored placeholder for now (it will be used later in this patch series). Signed-off-by: SZEDER Gábor <szeder.dev@xxxxxxxxx> --- contrib/completion/git-completion.bash | 21 ++++++++++++++------- t/t9902-completion.sh | 31 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 7f19e2a4f..67a03cfd4 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -354,6 +354,8 @@ __git_tags () # Can be the name of a configured remote, a path, or a URL. # 2: In addition to local refs, list unique branches from refs/remotes/ for # 'git checkout's tracking DWIMery (optional; ignored, if set but empty). +# 3: Currently ignored. +# 4: The current ref to be completed (optional). # # Use __git_complete_refs() instead. __git_refs () @@ -361,6 +363,7 @@ __git_refs () local i hash dir track="${2-}" local list_refs_from=path remote="${1-}" local format refs pfx + local cur_="${4-$cur}" __git_find_repo_path dir="$__git_repo_path" @@ -384,14 +387,17 @@ __git_refs () fi if [ "$list_refs_from" = path ]; then - case "$cur" in + case "$cur_" in refs|refs/*) format="refname" - refs="${cur%/*}" + refs="${cur_%/*}" track="" ;; *) - [[ "$cur" == ^* ]] && pfx="^" + if [[ "$cur_" == ^* ]]; then + pfx="^" + cur_=${cur_#^} + fi for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do if [ -e "$dir/$i" ]; then echo $pfx$i; fi done @@ -411,16 +417,16 @@ __git_refs () while read -r entry; do eval "$entry" ref="${ref#*/}" - if [[ "$ref" == "$cur"* ]]; then + if [[ "$ref" == "$cur_"* ]]; then echo "$ref" fi done | sort | uniq -u fi return fi - case "$cur" in + case "$cur_" in refs|refs/*) - __git ls-remote "$remote" "$cur*" | \ + __git ls-remote "$remote" "$cur_*" | \ while read -r hash i; do case "$i" in *^{}) ;; @@ -475,7 +481,8 @@ __git_complete_refs () shift done - __gitcomp_nl "$(__git_refs "$remote" "$track")" "$pfx" "$cur_" "$sfx" + __gitcomp_nl "$(__git_refs "$remote" "$track" "" "$cur_")" \ + "$pfx" "$cur_" "$sfx" } # __git_refs2 requires 1 argument (to pass to __git_refs) diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index 50c534072..8fe748839 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -775,6 +775,37 @@ test_expect_success '__git_refs - unique remote branches for git checkout DWIMer test_cmp expected "$actual" ' +test_expect_success '__git_refs - after --opt=' ' + cat >expected <<-EOF && + HEAD + master + matching-branch + other/branch-in-other + other/master-in-other + matching-tag + EOF + ( + cur="--opt=" && + __git_refs "" "" "" "" >"$actual" + ) && + test_cmp expected "$actual" +' + +test_expect_success '__git_refs - after --opt= - full refs' ' + cat >expected <<-EOF && + refs/heads/master + refs/heads/matching-branch + refs/remotes/other/branch-in-other + refs/remotes/other/master-in-other + refs/tags/matching-tag + EOF + ( + cur="--opt=refs/" && + __git_refs "" "" "" refs/ >"$actual" + ) && + test_cmp expected "$actual" +' + test_expect_success '__git_complete_refs - simple' ' sed -e "s/Z$//g" >expected <<-EOF && HEAD Z -- 2.11.0.555.g967c1bcb3