git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH 0/2] add case insensitivity option to bash completion
@ 2022-11-05 17:28 Alison Winters via GitGitGadget
  2022-11-05 17:28 ` [PATCH 1/2] completion: add optional ignore-case when matching refs Alison Winters via GitGitGadget
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: Alison Winters via GitGitGadget @ 2022-11-05 17:28 UTC (permalink / raw)
  To: git; +Cc: Alison Winters

In 3bb16a8bf2 (tag, branch, for-each-ref: add --ignore-case for sorting and
filtering, 2016-12-04), support was added for filtering and sorting refs in
a case insensitive way. This is a behavior that seems appropriate to enable
with shell completion. Many shells provide case insensitive completion as an
option, even on filesystems that remain case sensitive.

This patch adds a new variable that, when set, will allow Bash completion to
use the --ignore-case option to match refs. Additionally, some basic support
is implemented to match pseudorefs like HEAD.

Alison Winters (2):
  completion: add optional ignore-case when matching refs
  completion: add case-insensitive match of pseudorefs

 contrib/completion/git-completion.bash | 51 ++++++++++++++++++++++++--
 t/t9902-completion.sh                  | 32 ++++++++++++++++
 2 files changed, 80 insertions(+), 3 deletions(-)


base-commit: 3b08839926fcc7cc48cf4c759737c1a71af430c1
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1374%2Falisonatwork%2Fbash-insensitive-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1374/alisonatwork/bash-insensitive-v1
Pull-Request: https://github.com/git/git/pull/1374
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/2] completion: add optional ignore-case when matching refs
  2022-11-05 17:28 [PATCH 0/2] add case insensitivity option to bash completion Alison Winters via GitGitGadget
@ 2022-11-05 17:28 ` Alison Winters via GitGitGadget
  2022-11-20 20:24   ` SZEDER Gábor
  2022-11-05 17:28 ` [PATCH 2/2] completion: add case-insensitive match of pseudorefs Alison Winters via GitGitGadget
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Alison Winters via GitGitGadget @ 2022-11-05 17:28 UTC (permalink / raw)
  To: git; +Cc: Alison Winters, Alison Winters

From: Alison Winters <alisonatwork@outlook.com>

If GIT_COMPLETION_IGNORE_CASE=1 is set, --ignore-case will be added to
git for-each-ref calls so that branches and tags can be matched case
insensitively.

Signed-off-by: Alison Winters <alisonatwork@outlook.com>
---
 contrib/completion/git-completion.bash | 41 ++++++++++++++++++++++++++
 t/t9902-completion.sh                  | 16 ++++++++++
 2 files changed, 57 insertions(+)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index ba5c395d2d8..8ed96a5b8b6 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -58,6 +58,11 @@
 #
 #     When set to "1" suggest all options, including options which are
 #     typically hidden (e.g. '--allow-empty' for 'git commit').
+#
+#   GIT_COMPLETION_IGNORE_CASE
+#
+#     When set to "1", suggest refs that match case insensitively (e.g.,
+#     completing "FOO" on "git checkout f<TAB>").
 
 case "$COMP_WORDBREAKS" in
 *:*) : great ;;
@@ -644,8 +649,15 @@ __git_complete_index_file ()
 __git_heads ()
 {
 	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
+	local ignore_case=""
+
+	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
+	then
+		ignore_case="--ignore-case"
+	fi
 
 	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
+			$ignore_case \
 			"refs/heads/$cur_*" "refs/heads/$cur_*/**"
 }
 
@@ -657,8 +669,15 @@ __git_heads ()
 __git_remote_heads ()
 {
 	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
+	local ignore_case=""
+
+	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
+	then
+		ignore_case="--ignore-case"
+	fi
 
 	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
+			$ignore_case \
 			"refs/remotes/$cur_*" "refs/remotes/$cur_*/**"
 }
 
@@ -667,8 +686,15 @@ __git_remote_heads ()
 __git_tags ()
 {
 	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
+	local ignore_case=""
+
+	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
+	then
+		ignore_case="--ignore-case"
+	fi
 
 	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
+			$ignore_case \
 			"refs/tags/$cur_*" "refs/tags/$cur_*/**"
 }
 
@@ -682,12 +708,19 @@ __git_dwim_remote_heads ()
 {
 	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
 	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
+	local ignore_case=""
+
+	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
+	then
+		ignore_case="--ignore-case"
+	fi
 
 	# employ the heuristic used by git checkout and git switch
 	# Try to find a remote branch that cur_es the completion word
 	# but only output if the branch name is unique
 	__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
 		--sort="refname:strip=3" \
+		$ignore_case \
 		"refs/remotes/*/$cur_*" "refs/remotes/*/$cur_*/**" | \
 	uniq -u
 }
@@ -713,6 +746,7 @@ __git_refs ()
 	local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}"
 	local match="${4-}"
 	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
+	local ignore_case=""
 
 	__git_find_repo_path
 	dir="$__git_repo_path"
@@ -735,6 +769,11 @@ __git_refs ()
 		fi
 	fi
 
+	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
+	then
+		ignore_case="--ignore-case"
+	fi
+
 	if [ "$list_refs_from" = path ]; then
 		if [[ "$cur_" == ^* ]]; then
 			pfx="$pfx^"
@@ -765,6 +804,7 @@ __git_refs ()
 			;;
 		esac
 		__git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \
+			$ignore_case \
 			"${refs[@]}"
 		if [ -n "$track" ]; then
 			__git_dwim_remote_heads "$pfx" "$match" "$sfx"
@@ -787,6 +827,7 @@ __git_refs ()
 			$match*)	echo "${pfx}HEAD$sfx" ;;
 			esac
 			__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
+				$ignore_case \
 				"refs/remotes/$remote/$match*" \
 				"refs/remotes/$remote/$match*/**"
 		else
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 43de868b800..f62a395d827 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2255,6 +2255,22 @@ test_expect_success 'checkout completes ref names' '
 	EOF
 '
 
+test_expect_success 'checkout does not match ref names of a different case' '
+	test_completion "git checkout M" ""
+'
+
+test_expect_success 'checkout matches case insensitively with GIT_COMPLETION_IGNORE_CASE' '
+	(
+		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+		GIT_COMPLETION_IGNORE_CASE=1 && export GIT_COMPLETION_IGNORE_CASE &&
+		test_completion "git checkout M" <<-\EOF
+		main Z
+		mybranch Z
+		mytag Z
+		EOF
+	)
+'
+
 test_expect_success 'git -C <path> checkout uses the right repo' '
 	test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
 	branch-in-other Z
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/2] completion: add case-insensitive match of pseudorefs
  2022-11-05 17:28 [PATCH 0/2] add case insensitivity option to bash completion Alison Winters via GitGitGadget
  2022-11-05 17:28 ` [PATCH 1/2] completion: add optional ignore-case when matching refs Alison Winters via GitGitGadget
@ 2022-11-05 17:28 ` Alison Winters via GitGitGadget
  2022-11-20 20:42   ` SZEDER Gábor
  2022-11-08  3:00 ` [PATCH 0/2] add case insensitivity option to bash completion Taylor Blau
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Alison Winters via GitGitGadget @ 2022-11-05 17:28 UTC (permalink / raw)
  To: git; +Cc: Alison Winters, Alison Winters

From: Alison Winters <alisonatwork@outlook.com>

When GIT_COMPLETION_IGNORE_CASE=1, also allow lowercase completion text
like "head" to match HEAD and other pseudorefs.

Signed-off-by: Alison Winters <alisonatwork@outlook.com>
---
 contrib/completion/git-completion.bash | 10 +++++++---
 t/t9902-completion.sh                  | 16 ++++++++++++++++
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 8ed96a5b8b6..161327057da 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -745,6 +745,7 @@ __git_refs ()
 	local format refs
 	local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}"
 	local match="${4-}"
+	local umatch="${4-}"
 	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
 	local ignore_case=""
 
@@ -772,6 +773,8 @@ __git_refs ()
 	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
 	then
 		ignore_case="--ignore-case"
+		# use tr instead of ${match,^^} to preserve bash 3.2 compatibility
+		umatch=$(echo "$match" | tr a-z A-Z 2> /dev/null || echo "$match")
 	fi
 
 	if [ "$list_refs_from" = path ]; then
@@ -780,6 +783,7 @@ __git_refs ()
 			fer_pfx="$fer_pfx^"
 			cur_=${cur_#^}
 			match=${match#^}
+			umatch=${umatch#^}
 		fi
 		case "$cur_" in
 		refs|refs/*)
@@ -790,7 +794,7 @@ __git_refs ()
 		*)
 			for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD REBASE_HEAD CHERRY_PICK_HEAD; do
 				case "$i" in
-				$match*)
+				$match*|$umatch*)
 					if [ -e "$dir/$i" ]; then
 						echo "$pfx$i$sfx"
 					fi
@@ -824,7 +828,7 @@ __git_refs ()
 	*)
 		if [ "$list_refs_from" = remote ]; then
 			case "HEAD" in
-			$match*)	echo "${pfx}HEAD$sfx" ;;
+			$match*|$umatch*)	echo "${pfx}HEAD$sfx" ;;
 			esac
 			__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
 				$ignore_case \
@@ -833,7 +837,7 @@ __git_refs ()
 		else
 			local query_symref
 			case "HEAD" in
-			$match*)	query_symref="HEAD" ;;
+			$match*|$umatch*)	query_symref="HEAD" ;;
 			esac
 			__git ls-remote "$remote" $query_symref \
 				"refs/tags/$match*" "refs/heads/$match*" \
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index f62a395d827..b4c46567fa4 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2271,6 +2271,22 @@ test_expect_success 'checkout matches case insensitively with GIT_COMPLETION_IGN
 	)
 '
 
+test_expect_success 'checkout completes pseudo refs' '
+	test_completion "git checkout H" <<-\EOF
+	HEAD Z
+	EOF
+'
+
+test_expect_success 'checkout completes pseudo refs case insensitively with GIT_COMPLETION_IGNORE_CASE' '
+	(
+		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+		GIT_COMPLETION_IGNORE_CASE=1 && export GIT_COMPLETION_IGNORE_CASE &&
+		test_completion "git checkout h" <<-\EOF
+		HEAD Z
+		EOF
+	)
+'
+
 test_expect_success 'git -C <path> checkout uses the right repo' '
 	test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
 	branch-in-other Z
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/2] add case insensitivity option to bash completion
  2022-11-05 17:28 [PATCH 0/2] add case insensitivity option to bash completion Alison Winters via GitGitGadget
  2022-11-05 17:28 ` [PATCH 1/2] completion: add optional ignore-case when matching refs Alison Winters via GitGitGadget
  2022-11-05 17:28 ` [PATCH 2/2] completion: add case-insensitive match of pseudorefs Alison Winters via GitGitGadget
@ 2022-11-08  3:00 ` Taylor Blau
  2022-11-21  0:26 ` [PATCH v2 " Alison Winters via GitGitGadget
  2022-11-29  2:38 ` [PATCH 0/2] add case insensitivity option to bash completion Junio C Hamano
  4 siblings, 0 replies; 15+ messages in thread
From: Taylor Blau @ 2022-11-08  3:00 UTC (permalink / raw)
  To: Alison Winters via GitGitGadget
  Cc: git, Alison Winters, Jacob Keller, SZEDER Gábor,
	Lessley Dennington

Hi Alison,

On Sat, Nov 05, 2022 at 05:28:33PM +0000, Alison Winters via GitGitGadget wrote:
> Alison Winters (2):
>   completion: add optional ignore-case when matching refs
>   completion: add case-insensitive match of pseudorefs
>
>  contrib/completion/git-completion.bash | 51 ++++++++++++++++++++++++--
>  t/t9902-completion.sh                  | 32 ++++++++++++++++
>  2 files changed, 80 insertions(+), 3 deletions(-)

It looks reasonable to me, but I'm far from an expert on the completion
code ;-).

CC'ing some folks who are going to be more familiar with it than me.

Thanks,
Taylor

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/2] completion: add optional ignore-case when matching refs
  2022-11-05 17:28 ` [PATCH 1/2] completion: add optional ignore-case when matching refs Alison Winters via GitGitGadget
@ 2022-11-20 20:24   ` SZEDER Gábor
  0 siblings, 0 replies; 15+ messages in thread
From: SZEDER Gábor @ 2022-11-20 20:24 UTC (permalink / raw)
  To: Alison Winters via GitGitGadget; +Cc: git, Alison Winters

On Sat, Nov 05, 2022 at 05:28:34PM +0000, Alison Winters via GitGitGadget wrote:
> From: Alison Winters <alisonatwork@outlook.com>
> 
> If GIT_COMPLETION_IGNORE_CASE=1 is set, --ignore-case will be added to
> git for-each-ref calls so that branches and tags can be matched case
> insensitively.
> 
> Signed-off-by: Alison Winters <alisonatwork@outlook.com>
> ---
>  contrib/completion/git-completion.bash | 41 ++++++++++++++++++++++++++
>  t/t9902-completion.sh                  | 16 ++++++++++
>  2 files changed, 57 insertions(+)
> 
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index ba5c395d2d8..8ed96a5b8b6 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -58,6 +58,11 @@
>  #
>  #     When set to "1" suggest all options, including options which are
>  #     typically hidden (e.g. '--allow-empty' for 'git commit').
> +#
> +#   GIT_COMPLETION_IGNORE_CASE
> +#
> +#     When set to "1", suggest refs that match case insensitively (e.g.,
> +#     completing "FOO" on "git checkout f<TAB>").

I wish the commit message and this comment would be more explicit
about only the matching being case insensitive, but the words listed
for completion will all have the same case as the files/refs/etc. that
are being completed.

I've already started writing a reply along the lines of "does this
only work on case-insensitive filesystems?!" before finally realizing
that's not how it works...

>  case "$COMP_WORDBREAKS" in
>  *:*) : great ;;
> @@ -644,8 +649,15 @@ __git_complete_index_file ()
>  __git_heads ()
>  {
>  	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
> +	local ignore_case=""
> +
> +	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
> +	then
> +		ignore_case="--ignore-case"
> +	fi

I find these six lines a bit too verbose for what there are doing,
especially since the same six lines are added a couple of times.  I
think it could be shortened to just a single line with the "use
alternate value" parameter expansion like this:

    local ignore_case=${GIT_COMPLETION_IGNORE_CASE+--ignore-case}

>  	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
> +			$ignore_case \

In fact, we could eliminate that new $ignore_case local variable
entirely by adding that parameter expansion right here.

>  			"refs/heads/$cur_*" "refs/heads/$cur_*/**"
>  }
>  
> @@ -657,8 +669,15 @@ __git_heads ()
>  __git_remote_heads ()
>  {
>  	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
> +	local ignore_case=""
> +
> +	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
> +	then
> +		ignore_case="--ignore-case"
> +	fi
>  
>  	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
> +			$ignore_case \
>  			"refs/remotes/$cur_*" "refs/remotes/$cur_*/**"
>  }
>  
> @@ -667,8 +686,15 @@ __git_remote_heads ()
>  __git_tags ()
>  {
>  	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
> +	local ignore_case=""
> +
> +	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
> +	then
> +		ignore_case="--ignore-case"
> +	fi
>  
>  	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
> +			$ignore_case \
>  			"refs/tags/$cur_*" "refs/tags/$cur_*/**"
>  }
>  
> @@ -682,12 +708,19 @@ __git_dwim_remote_heads ()
>  {
>  	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
>  	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
> +	local ignore_case=""
> +
> +	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
> +	then
> +		ignore_case="--ignore-case"
> +	fi
>  
>  	# employ the heuristic used by git checkout and git switch
>  	# Try to find a remote branch that cur_es the completion word
>  	# but only output if the branch name is unique
>  	__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
>  		--sort="refname:strip=3" \
> +		$ignore_case \
>  		"refs/remotes/*/$cur_*" "refs/remotes/*/$cur_*/**" | \
>  	uniq -u
>  }
> @@ -713,6 +746,7 @@ __git_refs ()
>  	local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}"
>  	local match="${4-}"
>  	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
> +	local ignore_case=""
>  
>  	__git_find_repo_path
>  	dir="$__git_repo_path"
> @@ -735,6 +769,11 @@ __git_refs ()
>  		fi
>  	fi
>  
> +	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
> +	then
> +		ignore_case="--ignore-case"
> +	fi
> +
>  	if [ "$list_refs_from" = path ]; then
>  		if [[ "$cur_" == ^* ]]; then
>  			pfx="$pfx^"
> @@ -765,6 +804,7 @@ __git_refs ()
>  			;;
>  		esac
>  		__git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \
> +			$ignore_case \
>  			"${refs[@]}"
>  		if [ -n "$track" ]; then
>  			__git_dwim_remote_heads "$pfx" "$match" "$sfx"
> @@ -787,6 +827,7 @@ __git_refs ()
>  			$match*)	echo "${pfx}HEAD$sfx" ;;
>  			esac
>  			__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
> +				$ignore_case \
>  				"refs/remotes/$remote/$match*" \
>  				"refs/remotes/$remote/$match*/**"
>  		else
> diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
> index 43de868b800..f62a395d827 100755
> --- a/t/t9902-completion.sh
> +++ b/t/t9902-completion.sh
> @@ -2255,6 +2255,22 @@ test_expect_success 'checkout completes ref names' '
>  	EOF
>  '
>  
> +test_expect_success 'checkout does not match ref names of a different case' '
> +	test_completion "git checkout M" ""
> +'
> +
> +test_expect_success 'checkout matches case insensitively with GIT_COMPLETION_IGNORE_CASE' '
> +	(
> +		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&

I don't think it's necessary to source the completion script here,
because the test script's main shell process has already sourced it,
and its functions are visible in this test's subshell as well.

(Yeah, there are a few test cases near the end that do (re-)source the
completion script, but they do so because they must invalidate the
cache variables used by the completion script; this case-insensitive
match feature, however, doesn't involve any of those cache variables.)

> +		GIT_COMPLETION_IGNORE_CASE=1 && export GIT_COMPLETION_IGNORE_CASE &&

There is no need to export this variable, because only a handful of
completion helper functions look at it, which are invoked in this same
shell process (or perhaps in one of its subshells, but this variable
will be visible there are all the same).

> +		test_completion "git checkout M" <<-\EOF
> +		main Z
> +		mybranch Z
> +		mytag Z
> +		EOF
> +	)
> +'
> +
>  test_expect_success 'git -C <path> checkout uses the right repo' '
>  	test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
>  	branch-in-other Z
> -- 
> gitgitgadget
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/2] completion: add case-insensitive match of pseudorefs
  2022-11-05 17:28 ` [PATCH 2/2] completion: add case-insensitive match of pseudorefs Alison Winters via GitGitGadget
@ 2022-11-20 20:42   ` SZEDER Gábor
  2022-11-20 20:46     ` SZEDER Gábor
  0 siblings, 1 reply; 15+ messages in thread
From: SZEDER Gábor @ 2022-11-20 20:42 UTC (permalink / raw)
  To: Alison Winters via GitGitGadget; +Cc: git, Alison Winters

On Sat, Nov 05, 2022 at 05:28:35PM +0000, Alison Winters via GitGitGadget wrote:
> From: Alison Winters <alisonatwork@outlook.com>
> 
> When GIT_COMPLETION_IGNORE_CASE=1, also allow lowercase completion text
> like "head" to match HEAD and other pseudorefs.
> 
> Signed-off-by: Alison Winters <alisonatwork@outlook.com>
> ---
>  contrib/completion/git-completion.bash | 10 +++++++---
>  t/t9902-completion.sh                  | 16 ++++++++++++++++
>  2 files changed, 23 insertions(+), 3 deletions(-)
> 
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 8ed96a5b8b6..161327057da 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -745,6 +745,7 @@ __git_refs ()
>  	local format refs
>  	local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}"
>  	local match="${4-}"
> +	local umatch="${4-}"

Why 'umatch' and not 'imatch'?

>  	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
>  	local ignore_case=""
>  
> @@ -772,6 +773,8 @@ __git_refs ()
>  	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
>  	then
>  		ignore_case="--ignore-case"
> +		# use tr instead of ${match,^^} to preserve bash 3.2 compatibility

Thank you for keeping compatibility with old versions in mind!

> +		umatch=$(echo "$match" | tr a-z A-Z 2> /dev/null || echo "$match")

Style nit: we usually don't add a space between the redirection
operator and the filename.

>  	fi
>  
>  	if [ "$list_refs_from" = path ]; then
> @@ -780,6 +783,7 @@ __git_refs ()
>  			fer_pfx="$fer_pfx^"
>  			cur_=${cur_#^}
>  			match=${match#^}
> +			umatch=${umatch#^}
>  		fi
>  		case "$cur_" in
>  		refs|refs/*)
> @@ -790,7 +794,7 @@ __git_refs ()
>  		*)
>  			for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD REBASE_HEAD CHERRY_PICK_HEAD; do
>  				case "$i" in
> -				$match*)
> +				$match*|$umatch*)

I find the two patterns here weird.  I suppose it works as intended,
because with GIT_COMPLETION_IGNORE_CASE being unset both $match and
$umatch have the same value, so there is only one pattern after all,
but when GIT_COMPLETION_IGNORE_CASE is set then $umatch contains the
case insensitive pattern...  but I still find it a bit weird :) but I
don't know how to make it less weird without introducing code
duplication, so it's still better than the alternatives.

>  					if [ -e "$dir/$i" ]; then
>  						echo "$pfx$i$sfx"
>  					fi
> @@ -824,7 +828,7 @@ __git_refs ()
>  	*)
>  		if [ "$list_refs_from" = remote ]; then
>  			case "HEAD" in
> -			$match*)	echo "${pfx}HEAD$sfx" ;;
> +			$match*|$umatch*)	echo "${pfx}HEAD$sfx" ;;
>  			esac
>  			__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
>  				$ignore_case \
> @@ -833,7 +837,7 @@ __git_refs ()
>  		else
>  			local query_symref
>  			case "HEAD" in
> -			$match*)	query_symref="HEAD" ;;
> +			$match*|$umatch*)	query_symref="HEAD" ;;
>  			esac
>  			__git ls-remote "$remote" $query_symref \
>  				"refs/tags/$match*" "refs/heads/$match*" \
> diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
> index f62a395d827..b4c46567fa4 100755
> --- a/t/t9902-completion.sh
> +++ b/t/t9902-completion.sh
> @@ -2271,6 +2271,22 @@ test_expect_success 'checkout matches case insensitively with GIT_COMPLETION_IGN
>  	)
>  '
>  
> +test_expect_success 'checkout completes pseudo refs' '
> +	test_completion "git checkout H" <<-\EOF
> +	HEAD Z
> +	EOF
> +'
> +
> +test_expect_success 'checkout completes pseudo refs case insensitively with GIT_COMPLETION_IGNORE_CASE' '
> +	(
> +		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
> +		GIT_COMPLETION_IGNORE_CASE=1 && export GIT_COMPLETION_IGNORE_CASE &&

The same comment about the unnecessary sourcing and exporting on the
previous patch applies here as well.

> +		test_completion "git checkout h" <<-\EOF
> +		HEAD Z
> +		EOF
> +	)
> +'
> +
>  test_expect_success 'git -C <path> checkout uses the right repo' '
>  	test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
>  	branch-in-other Z
> -- 
> gitgitgadget

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/2] completion: add case-insensitive match of pseudorefs
  2022-11-20 20:42   ` SZEDER Gábor
@ 2022-11-20 20:46     ` SZEDER Gábor
  0 siblings, 0 replies; 15+ messages in thread
From: SZEDER Gábor @ 2022-11-20 20:46 UTC (permalink / raw)
  To: Alison Winters via GitGitGadget; +Cc: git, Alison Winters

On Sun, Nov 20, 2022 at 09:42:32PM +0100, SZEDER Gábor wrote:
> On Sat, Nov 05, 2022 at 05:28:35PM +0000, Alison Winters via GitGitGadget wrote:
> > From: Alison Winters <alisonatwork@outlook.com>
> > 
> > When GIT_COMPLETION_IGNORE_CASE=1, also allow lowercase completion text
> > like "head" to match HEAD and other pseudorefs.
> > 
> > Signed-off-by: Alison Winters <alisonatwork@outlook.com>
> > ---
> >  contrib/completion/git-completion.bash | 10 +++++++---
> >  t/t9902-completion.sh                  | 16 ++++++++++++++++
> >  2 files changed, 23 insertions(+), 3 deletions(-)
> > 
> > diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> > index 8ed96a5b8b6..161327057da 100644
> > --- a/contrib/completion/git-completion.bash
> > +++ b/contrib/completion/git-completion.bash
> > @@ -745,6 +745,7 @@ __git_refs ()
> >  	local format refs
> >  	local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}"
> >  	local match="${4-}"
> > +	local umatch="${4-}"
> 
> Why 'umatch' and not 'imatch'?

Gah, because it's all _u_pper case, as can be seen in the next hunk,
that's why.

> >  	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
> >  	local ignore_case=""
> >  
> > @@ -772,6 +773,8 @@ __git_refs ()
> >  	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
> >  	then
> >  		ignore_case="--ignore-case"
> > +		# use tr instead of ${match,^^} to preserve bash 3.2 compatibility
> 
> Thank you for keeping compatibility with old versions in mind!
> 
> > +		umatch=$(echo "$match" | tr a-z A-Z 2> /dev/null || echo "$match")
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 0/2] add case insensitivity option to bash completion
  2022-11-05 17:28 [PATCH 0/2] add case insensitivity option to bash completion Alison Winters via GitGitGadget
                   ` (2 preceding siblings ...)
  2022-11-08  3:00 ` [PATCH 0/2] add case insensitivity option to bash completion Taylor Blau
@ 2022-11-21  0:26 ` Alison Winters via GitGitGadget
  2022-11-21  0:26   ` [PATCH v2 1/2] completion: add optional ignore-case when matching refs Alison Winters via GitGitGadget
  2022-11-21  0:26   ` [PATCH v2 2/2] completion: add case-insensitive match of pseudorefs Alison Winters via GitGitGadget
  2022-11-29  2:38 ` [PATCH 0/2] add case insensitivity option to bash completion Junio C Hamano
  4 siblings, 2 replies; 15+ messages in thread
From: Alison Winters via GitGitGadget @ 2022-11-21  0:26 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, SZEDER Gábor, Alison Winters

In 3bb16a8bf2 (tag, branch, for-each-ref: add --ignore-case for sorting and
filtering, 2016-12-04), support was added for filtering and sorting refs in
a case insensitive way. This is a behavior that seems appropriate to enable
with shell completion. Many shells provide case insensitive completion as an
option, even on filesystems that remain case sensitive.

This patch adds a new variable that, when set, will allow Bash completion to
use the --ignore-case option to match refs. Additionally, some basic support
is implemented to match pseudorefs like HEAD.

Changes since v1:

 * Improved comments and commit messages to clarify behavior on case
   sensitive filesystems
 * Replaced some lengthy if blocks with inline substitution
 * As a result of the above change, GIT_COMPLETION_IGNORE_CASE no longer
   needs to be set to "1" and now just needs to be present in the
   environment to work
 * Removed unnecessary exports in tests

Alison Winters (2):
  completion: add optional ignore-case when matching refs
  completion: add case-insensitive match of pseudorefs

 contrib/completion/git-completion.bash | 26 +++++++++++++++++++---
 t/t9902-completion.sh                  | 30 ++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 3 deletions(-)


base-commit: a0789512c5a4ae7da935cd2e419f253cb3cb4ce7
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1374%2Falisonatwork%2Fbash-insensitive-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1374/alisonatwork/bash-insensitive-v2
Pull-Request: https://github.com/git/git/pull/1374

Range-diff vs v1:

 1:  cef9a12b575 ! 1:  a261a94877a completion: add optional ignore-case when matching refs
     @@ Metadata
       ## Commit message ##
          completion: add optional ignore-case when matching refs
      
     -    If GIT_COMPLETION_IGNORE_CASE=1 is set, --ignore-case will be added to
     -    git for-each-ref calls so that branches and tags can be matched case
     -    insensitively.
     +    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>
      
     @@ contrib/completion/git-completion.bash
      +#
      +#   GIT_COMPLETION_IGNORE_CASE
      +#
     -+#     When set to "1", suggest refs that match case insensitively (e.g.,
     -+#     completing "FOO" on "git checkout f<TAB>").
     ++#     When set, uses for-each-ref '--ignore-case' to find refs that match
     ++#     case insensitively, even on systems with case sensitive file systems
     ++#     (e.g., completing tag name "FOO" on "git checkout f<TAB>").
       
       case "$COMP_WORDBREAKS" in
       *:*) : great ;;
     -@@ contrib/completion/git-completion.bash: __git_complete_index_file ()
     - __git_heads ()
     - {
     +@@ contrib/completion/git-completion.bash: __git_heads ()
       	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
     -+	local ignore_case=""
     -+
     -+	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
     -+	then
     -+		ignore_case="--ignore-case"
     -+	fi
       
       	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
     -+			$ignore_case \
     ++			${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
       			"refs/heads/$cur_*" "refs/heads/$cur_*/**"
       }
       
     -@@ contrib/completion/git-completion.bash: __git_heads ()
     - __git_remote_heads ()
     - {
     +@@ contrib/completion/git-completion.bash: __git_remote_heads ()
       	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
     -+	local ignore_case=""
     -+
     -+	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
     -+	then
     -+		ignore_case="--ignore-case"
     -+	fi
       
       	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
     -+			$ignore_case \
     ++			${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
       			"refs/remotes/$cur_*" "refs/remotes/$cur_*/**"
       }
       
     -@@ contrib/completion/git-completion.bash: __git_remote_heads ()
     - __git_tags ()
     - {
     +@@ contrib/completion/git-completion.bash: __git_tags ()
       	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
     -+	local ignore_case=""
     -+
     -+	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
     -+	then
     -+		ignore_case="--ignore-case"
     -+	fi
       
       	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
     -+			$ignore_case \
     ++			${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
       			"refs/tags/$cur_*" "refs/tags/$cur_*/**"
       }
       
      @@ contrib/completion/git-completion.bash: __git_dwim_remote_heads ()
     - {
     - 	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
     - 	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
     -+	local ignore_case=""
     -+
     -+	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
     -+	then
     -+		ignore_case="--ignore-case"
     -+	fi
     - 
     - 	# employ the heuristic used by git checkout and git switch
     - 	# Try to find a remote branch that cur_es the completion word
       	# but only output if the branch name is unique
       	__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
       		--sort="refname:strip=3" \
     -+		$ignore_case \
     ++		${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
       		"refs/remotes/*/$cur_*" "refs/remotes/*/$cur_*/**" | \
       	uniq -u
       }
     -@@ contrib/completion/git-completion.bash: __git_refs ()
     - 	local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}"
     - 	local match="${4-}"
     - 	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
     -+	local ignore_case=""
     - 
     - 	__git_find_repo_path
     - 	dir="$__git_repo_path"
     -@@ contrib/completion/git-completion.bash: __git_refs ()
     - 		fi
     - 	fi
     - 
     -+	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
     -+	then
     -+		ignore_case="--ignore-case"
     -+	fi
     -+
     - 	if [ "$list_refs_from" = path ]; then
     - 		if [[ "$cur_" == ^* ]]; then
     - 			pfx="$pfx^"
      @@ contrib/completion/git-completion.bash: __git_refs ()
       			;;
       		esac
       		__git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \
     -+			$ignore_case \
     ++			${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
       			"${refs[@]}"
       		if [ -n "$track" ]; then
       			__git_dwim_remote_heads "$pfx" "$match" "$sfx"
     @@ contrib/completion/git-completion.bash: __git_refs ()
       			$match*)	echo "${pfx}HEAD$sfx" ;;
       			esac
       			__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
     -+				$ignore_case \
     ++				${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
       				"refs/remotes/$remote/$match*" \
       				"refs/remotes/$remote/$match*/**"
       		else
     @@ t/t9902-completion.sh: test_expect_success 'checkout completes ref names' '
      +
      +test_expect_success 'checkout matches case insensitively with GIT_COMPLETION_IGNORE_CASE' '
      +	(
     -+		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
     -+		GIT_COMPLETION_IGNORE_CASE=1 && export GIT_COMPLETION_IGNORE_CASE &&
     ++		GIT_COMPLETION_IGNORE_CASE=1 &&
      +		test_completion "git checkout M" <<-\EOF
      +		main Z
      +		mybranch Z
 2:  c455e855395 ! 2:  480f6554c93 completion: add case-insensitive match of pseudorefs
     @@ Metadata
       ## Commit message ##
          completion: add case-insensitive match of pseudorefs
      
     -    When GIT_COMPLETION_IGNORE_CASE=1, also allow lowercase completion text
     -    like "head" to match HEAD and other pseudorefs.
     +    When GIT_COMPLETION_IGNORE_CASE is set, also allow lowercase completion
     +    text like "head" to match uppercase HEAD and other pseudorefs.
      
          Signed-off-by: Alison Winters <alisonatwork@outlook.com>
      
     @@ contrib/completion/git-completion.bash: __git_refs ()
       	local match="${4-}"
      +	local umatch="${4-}"
       	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
     - 	local ignore_case=""
       
     + 	__git_find_repo_path
      @@ contrib/completion/git-completion.bash: __git_refs ()
     - 	if test "${GIT_COMPLETION_IGNORE_CASE-}" = "1"
     - 	then
     - 		ignore_case="--ignore-case"
     -+		# use tr instead of ${match,^^} to preserve bash 3.2 compatibility
     -+		umatch=$(echo "$match" | tr a-z A-Z 2> /dev/null || echo "$match")
     + 		fi
       	fi
       
     ++	if test "${GIT_COMPLETION_IGNORE_CASE:+1}" = "1"
     ++	then
     ++		# uppercase with tr instead of ${match,^^} for bash 3.2 compatibility
     ++		umatch=$(echo "$match" | tr a-z A-Z 2>/dev/null || echo "$match")
     ++	fi
     ++
       	if [ "$list_refs_from" = path ]; then
     -@@ contrib/completion/git-completion.bash: __git_refs ()
     + 		if [[ "$cur_" == ^* ]]; then
     + 			pfx="$pfx^"
       			fer_pfx="$fer_pfx^"
       			cur_=${cur_#^}
       			match=${match#^}
     @@ contrib/completion/git-completion.bash: __git_refs ()
      +			$match*|$umatch*)	echo "${pfx}HEAD$sfx" ;;
       			esac
       			__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
     - 				$ignore_case \
     + 				${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
      @@ contrib/completion/git-completion.bash: __git_refs ()
       		else
       			local query_symref
     @@ t/t9902-completion.sh: test_expect_success 'checkout matches case insensitively
      +
      +test_expect_success 'checkout completes pseudo refs case insensitively with GIT_COMPLETION_IGNORE_CASE' '
      +	(
     -+		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
     -+		GIT_COMPLETION_IGNORE_CASE=1 && export GIT_COMPLETION_IGNORE_CASE &&
     ++		GIT_COMPLETION_IGNORE_CASE=1 &&
      +		test_completion "git checkout h" <<-\EOF
      +		HEAD Z
      +		EOF

-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 1/2] completion: add optional ignore-case when matching refs
  2022-11-21  0:26 ` [PATCH v2 " Alison Winters via GitGitGadget
@ 2022-11-21  0:26   ` Alison Winters via GitGitGadget
  2022-11-21  0:26   ` [PATCH v2 2/2] completion: add case-insensitive match of pseudorefs Alison Winters via GitGitGadget
  1 sibling, 0 replies; 15+ messages in thread
From: Alison Winters via GitGitGadget @ 2022-11-21  0:26 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, SZEDER Gábor, Alison Winters, Alison Winters

From: Alison Winters <alisonatwork@outlook.com>

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>
---
 contrib/completion/git-completion.bash | 12 ++++++++++++
 t/t9902-completion.sh                  | 15 +++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index ba5c395d2d8..7dcf4b63562 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -58,6 +58,12 @@
 #
 #     When set to "1" suggest all options, including options which are
 #     typically hidden (e.g. '--allow-empty' for 'git commit').
+#
+#   GIT_COMPLETION_IGNORE_CASE
+#
+#     When set, uses for-each-ref '--ignore-case' to find refs that match
+#     case insensitively, even on systems with case sensitive file systems
+#     (e.g., completing tag name "FOO" on "git checkout f<TAB>").
 
 case "$COMP_WORDBREAKS" in
 *:*) : great ;;
@@ -646,6 +652,7 @@ __git_heads ()
 	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
 
 	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
+			${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
 			"refs/heads/$cur_*" "refs/heads/$cur_*/**"
 }
 
@@ -659,6 +666,7 @@ __git_remote_heads ()
 	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
 
 	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
+			${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
 			"refs/remotes/$cur_*" "refs/remotes/$cur_*/**"
 }
 
@@ -669,6 +677,7 @@ __git_tags ()
 	local pfx="${1-}" cur_="${2-}" sfx="${3-}"
 
 	__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
+			${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
 			"refs/tags/$cur_*" "refs/tags/$cur_*/**"
 }
 
@@ -688,6 +697,7 @@ __git_dwim_remote_heads ()
 	# but only output if the branch name is unique
 	__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
 		--sort="refname:strip=3" \
+		${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
 		"refs/remotes/*/$cur_*" "refs/remotes/*/$cur_*/**" | \
 	uniq -u
 }
@@ -765,6 +775,7 @@ __git_refs ()
 			;;
 		esac
 		__git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \
+			${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
 			"${refs[@]}"
 		if [ -n "$track" ]; then
 			__git_dwim_remote_heads "$pfx" "$match" "$sfx"
@@ -787,6 +798,7 @@ __git_refs ()
 			$match*)	echo "${pfx}HEAD$sfx" ;;
 			esac
 			__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
+				${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
 				"refs/remotes/$remote/$match*" \
 				"refs/remotes/$remote/$match*/**"
 		else
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 43de868b800..d89d0a93a2a 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2255,6 +2255,21 @@ test_expect_success 'checkout completes ref names' '
 	EOF
 '
 
+test_expect_success 'checkout does not match ref names of a different case' '
+	test_completion "git checkout M" ""
+'
+
+test_expect_success 'checkout matches case insensitively with GIT_COMPLETION_IGNORE_CASE' '
+	(
+		GIT_COMPLETION_IGNORE_CASE=1 &&
+		test_completion "git checkout M" <<-\EOF
+		main Z
+		mybranch Z
+		mytag Z
+		EOF
+	)
+'
+
 test_expect_success 'git -C <path> checkout uses the right repo' '
 	test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
 	branch-in-other Z
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 2/2] completion: add case-insensitive match of pseudorefs
  2022-11-21  0:26 ` [PATCH v2 " Alison Winters via GitGitGadget
  2022-11-21  0:26   ` [PATCH v2 1/2] completion: add optional ignore-case when matching refs Alison Winters via GitGitGadget
@ 2022-11-21  0:26   ` Alison Winters via GitGitGadget
  1 sibling, 0 replies; 15+ messages in thread
From: Alison Winters via GitGitGadget @ 2022-11-21  0:26 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, SZEDER Gábor, Alison Winters, Alison Winters

From: Alison Winters <alisonatwork@outlook.com>

When GIT_COMPLETION_IGNORE_CASE is set, also allow lowercase completion
text like "head" to match uppercase HEAD and other pseudorefs.

Signed-off-by: Alison Winters <alisonatwork@outlook.com>
---
 contrib/completion/git-completion.bash | 14 +++++++++++---
 t/t9902-completion.sh                  | 15 +++++++++++++++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 7dcf4b63562..dc95c34cc85 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -722,6 +722,7 @@ __git_refs ()
 	local format refs
 	local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}"
 	local match="${4-}"
+	local umatch="${4-}"
 	local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
 
 	__git_find_repo_path
@@ -745,12 +746,19 @@ __git_refs ()
 		fi
 	fi
 
+	if test "${GIT_COMPLETION_IGNORE_CASE:+1}" = "1"
+	then
+		# uppercase with tr instead of ${match,^^} for bash 3.2 compatibility
+		umatch=$(echo "$match" | tr a-z A-Z 2>/dev/null || echo "$match")
+	fi
+
 	if [ "$list_refs_from" = path ]; then
 		if [[ "$cur_" == ^* ]]; then
 			pfx="$pfx^"
 			fer_pfx="$fer_pfx^"
 			cur_=${cur_#^}
 			match=${match#^}
+			umatch=${umatch#^}
 		fi
 		case "$cur_" in
 		refs|refs/*)
@@ -761,7 +769,7 @@ __git_refs ()
 		*)
 			for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD REBASE_HEAD CHERRY_PICK_HEAD; do
 				case "$i" in
-				$match*)
+				$match*|$umatch*)
 					if [ -e "$dir/$i" ]; then
 						echo "$pfx$i$sfx"
 					fi
@@ -795,7 +803,7 @@ __git_refs ()
 	*)
 		if [ "$list_refs_from" = remote ]; then
 			case "HEAD" in
-			$match*)	echo "${pfx}HEAD$sfx" ;;
+			$match*|$umatch*)	echo "${pfx}HEAD$sfx" ;;
 			esac
 			__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
 				${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \
@@ -804,7 +812,7 @@ __git_refs ()
 		else
 			local query_symref
 			case "HEAD" in
-			$match*)	query_symref="HEAD" ;;
+			$match*|$umatch*)	query_symref="HEAD" ;;
 			esac
 			__git ls-remote "$remote" $query_symref \
 				"refs/tags/$match*" "refs/heads/$match*" \
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index d89d0a93a2a..d6c0478d98b 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2270,6 +2270,21 @@ test_expect_success 'checkout matches case insensitively with GIT_COMPLETION_IGN
 	)
 '
 
+test_expect_success 'checkout completes pseudo refs' '
+	test_completion "git checkout H" <<-\EOF
+	HEAD Z
+	EOF
+'
+
+test_expect_success 'checkout completes pseudo refs case insensitively with GIT_COMPLETION_IGNORE_CASE' '
+	(
+		GIT_COMPLETION_IGNORE_CASE=1 &&
+		test_completion "git checkout h" <<-\EOF
+		HEAD Z
+		EOF
+	)
+'
+
 test_expect_success 'git -C <path> checkout uses the right repo' '
 	test_completion "git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b" <<-\EOF
 	branch-in-other Z
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/2] add case insensitivity option to bash completion
  2022-11-05 17:28 [PATCH 0/2] add case insensitivity option to bash completion Alison Winters via GitGitGadget
                   ` (3 preceding siblings ...)
  2022-11-21  0:26 ` [PATCH v2 " Alison Winters via GitGitGadget
@ 2022-11-29  2:38 ` Junio C Hamano
  2022-11-29 15:56   ` Alison Winters
  4 siblings, 1 reply; 15+ messages in thread
From: Junio C Hamano @ 2022-11-29  2:38 UTC (permalink / raw)
  To: Alison Winters via GitGitGadget, Johannes Schindelin,
	Ævar Arnfjörð Bjarmason, Sibi Siddharthan
  Cc: git, Alison Winters

"Alison Winters via GitGitGadget" <gitgitgadget@gmail.com> writes:

> In 3bb16a8bf2 (tag, branch, for-each-ref: add --ignore-case for sorting and
> filtering, 2016-12-04), support was added for filtering and sorting refs in
> a case insensitive way. This is a behavior that seems appropriate to enable
> with shell completion. Many shells provide case insensitive completion as an
> option, even on filesystems that remain case sensitive.
>
> This patch adds a new variable that, when set, will allow Bash completion to
> use the --ignore-case option to match refs. Additionally, some basic support
> is implemented to match pseudorefs like HEAD.

I did not try to figure out the reason but the topic with its tests
seem to break in 'seen' the linux-cmake-ctest CI job.

  https://github.com/git/git/actions/runs/3570230611/jobs/6001013549

but the same test does not break under usual "make test".

Can people who are interested in the cmake-ctest stuff take a look?

It is tempting to eject the ab/cmake-nix-and-ci topic that is
already in 'next', under the theory that what that topic does to the
tests "works" for some tests but not for others, and this topic is
an unfortunate collateral damage whose tests weren't something the
other topic supports well.  If the cmake-ctest stuff is in such a
shape, then it may have been a bit premature to merge it down.

Thanks.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/2] add case insensitivity option to bash completion
  2022-11-29  2:38 ` [PATCH 0/2] add case insensitivity option to bash completion Junio C Hamano
@ 2022-11-29 15:56   ` Alison Winters
  2022-11-29 17:40     ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 15+ messages in thread
From: Alison Winters @ 2022-11-29 15:56 UTC (permalink / raw)
  To: Junio C Hamano, Alison Winters via GitGitGadget,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason,
	Sibi Siddharthan
  Cc: git

On 2022-11-29 10:38, Junio C Hamano wrote:
 > I did not try to figure out the reason but the topic with its tests
 > seem to break in 'seen' the linux-cmake-ctest CI job.
 >
 > https://github.com/git/git/actions/runs/3570230611/jobs/6001013549
 >
 > but the same test does not break under usual "make test".

I cannot speak for how the changes of the ab/cmake-nix-and-ci impact
the aw/complete-case-insensitive branch, but the failure seems to be
pointing to a test that I have since changed in the v2 patch, on the
suggestion of Szeder Gabor. The variable is no longer exported and
the script is no longer sourced a second time. I don't know if those
v2 changes would change the results of this test, but they might be a
starting point for the other people CC:ed here to consider.

Alison


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/2] add case insensitivity option to bash completion
  2022-11-29 15:56   ` Alison Winters
@ 2022-11-29 17:40     ` Ævar Arnfjörð Bjarmason
  2022-11-30  0:37       ` Alison Winters
  0 siblings, 1 reply; 15+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-11-29 17:40 UTC (permalink / raw)
  To: Alison Winters
  Cc: Junio C Hamano, Alison Winters via GitGitGadget,
	Johannes Schindelin, Sibi Siddharthan, git


On Tue, Nov 29 2022, Alison Winters wrote:

> On 2022-11-29 10:38, Junio C Hamano wrote:
>> I did not try to figure out the reason but the topic with its tests
>> seem to break in 'seen' the linux-cmake-ctest CI job.
>>
>> https://github.com/git/git/actions/runs/3570230611/jobs/6001013549
>>
>> but the same test does not break under usual "make test".
>
> I cannot speak for how the changes of the ab/cmake-nix-and-ci impact
> the aw/complete-case-insensitive branch, but the failure seems to be
> pointing to a test that I have since changed in the v2 patch, on the
> suggestion of Szeder Gabor. The variable is no longer exported and
> the script is no longer sourced a second time. I don't know if those
> v2 changes would change the results of this test, but they might be a
> starting point for the other people CC:ed here to consider.

The breakage is due to a semantic conflict between the two, which is
solved thusly:
	
	diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
	index d45d820da28..2aa128075ca 100755
	--- a/t/t9902-completion.sh
	+++ b/t/t9902-completion.sh
	@@ -2261,7 +2261,7 @@ test_expect_success 'checkout does not match ref names of a different case' '
	 
	 test_expect_success 'checkout matches case insensitively with GIT_COMPLETION_IGNORE_CASE' '
	 	(
	-		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
	+		. "$GIT_SOURCE_DIR/contrib/completion/git-completion.bash" &&
	 		GIT_COMPLETION_IGNORE_CASE=1 && export GIT_COMPLETION_IGNORE_CASE &&
	 		test_completion "git checkout M" <<-\EOF
	 		main Z
	@@ -2279,7 +2279,7 @@ test_expect_success 'checkout completes pseudo refs' '
	 
	 test_expect_success 'checkout completes pseudo refs case insensitively with GIT_COMPLETION_IGNORE_CASE' '
	 	(
	-		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
	+		. "$GIT_SOURCE_DIR/contrib/completion/git-completion.bash" &&
	 		GIT_COMPLETION_IGNORE_CASE=1 && export GIT_COMPLETION_IGNORE_CASE &&
	 		test_completion "git checkout h" <<-\EOF
	 		HEAD Z

Junio: I don't think this warrants kicking out the cmake topic. This
sort of problem is just going to occur while something like that is
in-flight, or Alison would have otherwise presumably seen it as a CI
failure if based off "master".

With hindsight I could have made e74e51a9154 (cmake & test-lib.sh: add a
$GIT_SOURCE_DIR variable, 2022-11-03) do the migration in two phases,
but I didn't expect another topic to rely on the relatively obscure bits
that were being copied to the $GIT_BUILD_DIR, we weren't exactly
drowning in git-completion.bash patches...

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/2] add case insensitivity option to bash completion
  2022-11-29 17:40     ` Ævar Arnfjörð Bjarmason
@ 2022-11-30  0:37       ` Alison Winters
  2022-11-30  3:08         ` Junio C Hamano
  0 siblings, 1 reply; 15+ messages in thread
From: Alison Winters @ 2022-11-30  0:37 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: Junio C Hamano, Alison Winters via GitGitGadget,
	Johannes Schindelin, Sibi Siddharthan, git

On 2022-11-30 01:40, Ævar Arnfjörð Bjarmason wrote:
 >
 > On Tue, Nov 29 2022, Alison Winters wrote:
 >
 >> On 2022-11-29 10:38, Junio C Hamano wrote:
 >>> I did not try to figure out the reason but the topic with its tests
 >>> seem to break in 'seen' the linux-cmake-ctest CI job.
 >>>
 >>> https://github.com/git/git/actions/runs/3570230611/jobs/6001013549
 >>>
 >>> but the same test does not break under usual "make test".
 >>
 >> I cannot speak for how the changes of the ab/cmake-nix-and-ci impact
 >> the aw/complete-case-insensitive branch, but the failure seems to be
 >> pointing to a test that I have since changed in the v2 patch, on the
 >> suggestion of Szeder Gabor. The variable is no longer exported and
 >> the script is no longer sourced a second time. I don't know if those
 >> v2 changes would change the results of this test, but they might be a
 >> starting point for the other people CC:ed here to consider.
 >
 > The breakage is due to a semantic conflict between the two, which is
 > solved thusly:
 >
 >     diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
 >     index d45d820da28..2aa128075ca 100755
 >     --- a/t/t9902-completion.sh
 >     +++ b/t/t9902-completion.sh
 >     @@ -2261,7 +2261,7 @@ test_expect_success 'checkout does not 
match ref names of a different case' '
 >
 >      test_expect_success 'checkout matches case insensitively with 
GIT_COMPLETION_IGNORE_CASE' '
 >          (
 >     -        . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
 >     +        . 
"$GIT_SOURCE_DIR/contrib/completion/git-completion.bash" &&
 >              GIT_COMPLETION_IGNORE_CASE=1 && export 
GIT_COMPLETION_IGNORE_CASE &&
 >              test_completion "git checkout M" <<-\EOF
 >              main Z
 >     @@ -2279,7 +2279,7 @@ test_expect_success 'checkout completes 
pseudo refs' '
 >
 >      test_expect_success 'checkout completes pseudo refs case 
insensitively with GIT_COMPLETION_IGNORE_CASE' '
 >          (
 >     -        . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
 >     +        . 
"$GIT_SOURCE_DIR/contrib/completion/git-completion.bash" &&
 >              GIT_COMPLETION_IGNORE_CASE=1 && export 
GIT_COMPLETION_IGNORE_CASE &&
 >              test_completion "git checkout h" <<-\EOF
 >              HEAD Z

In this case, I think the easiest solution will be to move the
aw/complete-case-insensitive branch forward to the v2 patch (posted to
the list @ 2022-11-21  0:26 UTC), which no longer includes this line.

Alison

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/2] add case insensitivity option to bash completion
  2022-11-30  0:37       ` Alison Winters
@ 2022-11-30  3:08         ` Junio C Hamano
  0 siblings, 0 replies; 15+ messages in thread
From: Junio C Hamano @ 2022-11-30  3:08 UTC (permalink / raw)
  To: Alison Winters
  Cc: Ævar Arnfjörð Bjarmason,
	Alison Winters via GitGitGadget, Johannes Schindelin,
	Sibi Siddharthan, git

Alison Winters <alisonatwork@outlook.com> writes:

> In this case, I think the easiest solution will be to move the
> aw/complete-case-insensitive branch forward to the v2 patch (posted to
> the list @ 2022-11-21  0:26 UTC), which no longer includes this line.

Indeed.  With <pull.1374.v2.git.git.1668990419.gitgitgadget@gmail.com>
merged on top of a known-good subset of 'seen', cmake-ctest thing did
not fail.

https://github.com/git/git/actions/runs/3579752650/jobs/6021251201

Thanks.

P.S. Ignore the osx-gcc job that was cancelled in the same run; as
this is not the only topic I have to deal with, I submitted a trial
merge into 'seen' of another topic after seeing cmake-ctest job
finish, but because of recent CI change to cancel an earlier job
when a new job is started, it got auto-cancelled (which is mostly a
good thing for regular developer workflow, but not for me X-<)


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2022-11-30  3:09 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-05 17:28 [PATCH 0/2] add case insensitivity option to bash completion Alison Winters via GitGitGadget
2022-11-05 17:28 ` [PATCH 1/2] completion: add optional ignore-case when matching refs Alison Winters via GitGitGadget
2022-11-20 20:24   ` SZEDER Gábor
2022-11-05 17:28 ` [PATCH 2/2] completion: add case-insensitive match of pseudorefs Alison Winters via GitGitGadget
2022-11-20 20:42   ` SZEDER Gábor
2022-11-20 20:46     ` SZEDER Gábor
2022-11-08  3:00 ` [PATCH 0/2] add case insensitivity option to bash completion Taylor Blau
2022-11-21  0:26 ` [PATCH v2 " Alison Winters via GitGitGadget
2022-11-21  0:26   ` [PATCH v2 1/2] completion: add optional ignore-case when matching refs Alison Winters via GitGitGadget
2022-11-21  0:26   ` [PATCH v2 2/2] completion: add case-insensitive match of pseudorefs Alison Winters via GitGitGadget
2022-11-29  2:38 ` [PATCH 0/2] add case insensitivity option to bash completion Junio C Hamano
2022-11-29 15:56   ` Alison Winters
2022-11-29 17:40     ` Ævar Arnfjörð Bjarmason
2022-11-30  0:37       ` Alison Winters
2022-11-30  3:08         ` Junio C Hamano

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).