Skip to content

Commit 3bc7f86

Browse files
committed
Merge branch 'dm/completion-remote-names-fix'
The bash command line completion script (in contrib/) has been updated to cope with remote repository nicknames with slashes in them. * dm/completion-remote-names-fix: completion: fix bugs with slashes in remote names completion: add helper to count path components
2 parents bc5be63 + 778d2f1 commit 3bc7f86

File tree

2 files changed

+226
-29
lines changed

2 files changed

+226
-29
lines changed

contrib/completion/git-completion.bash

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,17 @@ __git_dequote ()
234234
done
235235
}
236236

237+
# Prints the number of slash-separated components in a path.
238+
# 1: Path to count components of.
239+
__git_count_path_components ()
240+
{
241+
local path="$1"
242+
local relative="${path#/}"
243+
relative="${relative%/}"
244+
local slashes="/${relative//[^\/]}"
245+
echo "${#slashes}"
246+
}
247+
237248
# The following function is based on code from:
238249
#
239250
# bash_completion - programmable completion functions for bash 3.2+
@@ -779,16 +790,39 @@ __git_tags ()
779790
__git_dwim_remote_heads ()
780791
{
781792
local pfx="${1-}" cur_="${2-}" sfx="${3-}"
782-
local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
783793

784794
# employ the heuristic used by git checkout and git switch
785795
# Try to find a remote branch that cur_es the completion word
786796
# but only output if the branch name is unique
787-
__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
788-
--sort="refname:strip=3" \
789-
${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
790-
"refs/remotes/*/$cur_*" "refs/remotes/*/$cur_*/**" | \
791-
uniq -u
797+
local awk_script='
798+
function casemap(s) {
799+
if (ENVIRON["IGNORE_CASE"])
800+
return tolower(s)
801+
else
802+
return s
803+
}
804+
BEGIN {
805+
split(ENVIRON["REMOTES"], remotes, /\n/)
806+
for (i in remotes)
807+
remotes[i] = "refs/remotes/" casemap(remotes[i])
808+
cur_ = casemap(ENVIRON["CUR_"])
809+
}
810+
{
811+
ref_case = casemap($0)
812+
for (i in remotes) {
813+
if (index(ref_case, remotes[i] "/" cur_) == 1) {
814+
branch = substr($0, length(remotes[i] "/") + 1)
815+
print ENVIRON["PFX"] branch ENVIRON["SFX"]
816+
break
817+
}
818+
}
819+
}
820+
'
821+
__git for-each-ref --format='%(refname)' refs/remotes/ |
822+
PFX="$pfx" SFX="$sfx" CUR_="$cur_" \
823+
IGNORE_CASE=${GIT_COMPLETION_IGNORE_CASE+1} \
824+
REMOTES="$(__git_remotes | sort -r)" awk "$awk_script" |
825+
sort | uniq -u
792826
}
793827

794828
# Lists refs from the local (by default) or from a remote repository.
@@ -894,7 +928,8 @@ __git_refs ()
894928
case "HEAD" in
895929
$match*|$umatch*) echo "${pfx}HEAD$sfx" ;;
896930
esac
897-
__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
931+
local strip="$(__git_count_path_components "refs/remotes/$remote")"
932+
__git for-each-ref --format="$fer_pfx%(refname:strip=$strip)$sfx" \
898933
${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
899934
"refs/remotes/$remote/$match*" \
900935
"refs/remotes/$remote/$match*/**"

0 commit comments

Comments
 (0)