Skip to content

Commit 053650d

Browse files
committed
Merge branch 'aw/complete-case-insensitive'
Introduce a case insensitive mode to the Bash completion helpers. * aw/complete-case-insensitive: completion: add case-insensitive match of pseudorefs completion: add optional ignore-case when matching refs
2 parents 4e09e0d + 9de31f7 commit 053650d

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

contrib/completion/git-completion.bash

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@
5858
#
5959
# When set to "1" suggest all options, including options which are
6060
# typically hidden (e.g. '--allow-empty' for 'git commit').
61+
#
62+
# GIT_COMPLETION_IGNORE_CASE
63+
#
64+
# When set, uses for-each-ref '--ignore-case' to find refs that match
65+
# case insensitively, even on systems with case sensitive file systems
66+
# (e.g., completing tag name "FOO" on "git checkout f<TAB>").
6167

6268
case "$COMP_WORDBREAKS" in
6369
*:*) : great ;;
@@ -646,6 +652,7 @@ __git_heads ()
646652
local pfx="${1-}" cur_="${2-}" sfx="${3-}"
647653

648654
__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
655+
${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
649656
"refs/heads/$cur_*" "refs/heads/$cur_*/**"
650657
}
651658

@@ -659,6 +666,7 @@ __git_remote_heads ()
659666
local pfx="${1-}" cur_="${2-}" sfx="${3-}"
660667

661668
__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
669+
${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
662670
"refs/remotes/$cur_*" "refs/remotes/$cur_*/**"
663671
}
664672

@@ -669,6 +677,7 @@ __git_tags ()
669677
local pfx="${1-}" cur_="${2-}" sfx="${3-}"
670678

671679
__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
680+
${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
672681
"refs/tags/$cur_*" "refs/tags/$cur_*/**"
673682
}
674683

@@ -688,6 +697,7 @@ __git_dwim_remote_heads ()
688697
# but only output if the branch name is unique
689698
__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
690699
--sort="refname:strip=3" \
700+
${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
691701
"refs/remotes/*/$cur_*" "refs/remotes/*/$cur_*/**" | \
692702
uniq -u
693703
}
@@ -712,6 +722,7 @@ __git_refs ()
712722
local format refs
713723
local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}"
714724
local match="${4-}"
725+
local umatch="${4-}"
715726
local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
716727

717728
__git_find_repo_path
@@ -735,12 +746,19 @@ __git_refs ()
735746
fi
736747
fi
737748

749+
if test "${GIT_COMPLETION_IGNORE_CASE:+1}" = "1"
750+
then
751+
# uppercase with tr instead of ${match,^^} for bash 3.2 compatibility
752+
umatch=$(echo "$match" | tr a-z A-Z 2>/dev/null || echo "$match")
753+
fi
754+
738755
if [ "$list_refs_from" = path ]; then
739756
if [[ "$cur_" == ^* ]]; then
740757
pfx="$pfx^"
741758
fer_pfx="$fer_pfx^"
742759
cur_=${cur_#^}
743760
match=${match#^}
761+
umatch=${umatch#^}
744762
fi
745763
case "$cur_" in
746764
refs|refs/*)
@@ -751,7 +769,7 @@ __git_refs ()
751769
*)
752770
for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD REBASE_HEAD CHERRY_PICK_HEAD; do
753771
case "$i" in
754-
$match*)
772+
$match*|$umatch*)
755773
if [ -e "$dir/$i" ]; then
756774
echo "$pfx$i$sfx"
757775
fi
@@ -765,6 +783,7 @@ __git_refs ()
765783
;;
766784
esac
767785
__git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \
786+
${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
768787
"${refs[@]}"
769788
if [ -n "$track" ]; then
770789
__git_dwim_remote_heads "$pfx" "$match" "$sfx"
@@ -784,15 +803,16 @@ __git_refs ()
784803
*)
785804
if [ "$list_refs_from" = remote ]; then
786805
case "HEAD" in
787-
$match*) echo "${pfx}HEAD$sfx" ;;
806+
$match*|$umatch*) echo "${pfx}HEAD$sfx" ;;
788807
esac
789808
__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
809+
${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
790810
"refs/remotes/$remote/$match*" \
791811
"refs/remotes/$remote/$match*/**"
792812
else
793813
local query_symref
794814
case "HEAD" in
795-
$match*) query_symref="HEAD" ;;
815+
$match*|$umatch*) query_symref="HEAD" ;;
796816
esac
797817
__git ls-remote "$remote" $query_symref \
798818
"refs/tags/$match*" "refs/heads/$match*" \

t/t9902-completion.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,6 +2255,36 @@ test_expect_success 'checkout completes ref names' '
22552255
EOF
22562256
'
22572257

2258+
test_expect_success 'checkout does not match ref names of a different case' '
2259+
test_completion "git checkout M" ""
2260+
'
2261+
2262+
test_expect_success 'checkout matches case insensitively with GIT_COMPLETION_IGNORE_CASE' '
2263+
(
2264+
GIT_COMPLETION_IGNORE_CASE=1 &&
2265+
test_completion "git checkout M" <<-\EOF
2266+
main Z
2267+
mybranch Z
2268+
mytag Z
2269+
EOF
2270+
)
2271+
'
2272+
2273+
test_expect_success 'checkout completes pseudo refs' '
2274+
test_completion "git checkout H" <<-\EOF
2275+
HEAD Z
2276+
EOF
2277+
'
2278+
2279+
test_expect_success 'checkout completes pseudo refs case insensitively with GIT_COMPLETION_IGNORE_CASE' '
2280+
(
2281+
GIT_COMPLETION_IGNORE_CASE=1 &&
2282+
test_completion "git checkout h" <<-\EOF
2283+
HEAD Z
2284+
EOF
2285+
)
2286+
'
2287+
22582288
test_expect_success 'git -C <path> checkout uses the right repo' '
22592289
test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
22602290
branch-in-other Z

0 commit comments

Comments
 (0)