completion: add optional ignore-case when matching refs

If GIT_COMPLETION_IGNORE_CASE is set, --ignore-case will be added to git for-each-ref calls so that refs can be matched case insensitively, even when running on case sensitive filesystems. Signed-off-by: Alison Winters <alisonatwork@outlook.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Alison Winters committed Nov 21, 2022 at 00:26 UTC 9bab766fb28fae57a229bd90558ec4453ca71be9
2 files changed +27
contrib/completion/git-completion.bash
+12
@@ -58,6 +58,12 @@
58 #
59 # When set to "1" suggest all options, including options which are
60 # 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>").
67
68 case "$COMP_WORDBREAKS" in
69 *:*) : great ;;
@@ -646,6 +652,7 @@ __git_heads ()
652 local pfx="${1-}" cur_="${2-}" sfx="${3-}"
653
654 __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
655 + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
656 "refs/heads/$cur_*" "refs/heads/$cur_*/**"
657 }
658
@@ -659,6 +666,7 @@ __git_remote_heads ()
666 local pfx="${1-}" cur_="${2-}" sfx="${3-}"
667
668 __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
669 + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
670 "refs/remotes/$cur_*" "refs/remotes/$cur_*/**"
671 }
672
@@ -669,6 +677,7 @@ __git_tags ()
677 local pfx="${1-}" cur_="${2-}" sfx="${3-}"
678
679 __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
680 + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
681 "refs/tags/$cur_*" "refs/tags/$cur_*/**"
682 }
683
@@ -688,6 +697,7 @@ __git_dwim_remote_heads ()
697 # but only output if the branch name is unique
698 __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
699 --sort="refname:strip=3" \
700 + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
701 "refs/remotes/*/$cur_*" "refs/remotes/*/$cur_*/**" | \
702 uniq -u
703 }
@@ -765,6 +775,7 @@ __git_refs ()
775 ;;
776 esac
777 __git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \
778 + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
779 "${refs[@]}"
780 if [ -n "$track" ]; then
781 __git_dwim_remote_heads "$pfx" "$match" "$sfx"
@@ -787,6 +798,7 @@ __git_refs ()
798 $match*) echo "${pfx}HEAD$sfx" ;;
799 esac
800 __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
801 + ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
802 "refs/remotes/$remote/$match*" \
803 "refs/remotes/$remote/$match*/**"
804 else
t/t9902-completion.sh
+15
@@ -2255,6 +2255,21 @@ test_expect_success 'checkout completes ref names' '
2255 EOF
2256 '
2257
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 'git -C <path> checkout uses the right repo' '
2274 test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
2275 branch-in-other Z