Subject: [PATCH 11/12] completion: list only matching symbolic and pseudorefs when completing refs

From: SZEDER Gábor <[email-masked]>
Date: Fri, 3 Feb 2017 03:54:04 +0100

The previous changes in this series ensure that __git_refs() lists
only refs that match the current word to be completed, but
non-matching symbolic and pseudo refs still show up in its output.

Filter out non-matching symbolic and pseudo refs as well, so anything
__git_refs() outputs matches the current word to be completed, as it
will allow us to optimize how refs are placed into the COMPREPLY
array.

Signed-off-by: SZEDER Gábor <[email-masked]>
---
 contrib/completion/git-completion.bash | 20 ++++++++++++++++----
 t/t9902-completion.sh                  |  4 ----
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 9f5a6f44e..0ad02cec6 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -355,7 +355,8 @@ __git_tags ()
 # 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).
+# 4: List only refs matching this word instead of the current word being
+#    completed (optional).
 #
 # Use __git_complete_refs() instead.
 __git_refs ()
@@ -399,7 +400,12 @@ __git_refs ()
 			;;
 		*)
 			for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
-				if [ -e "$dir/$i" ]; then echo $pfx$i; fi
+				case "$i" in
+				$cur_*)	if [ -e "$dir/$i" ]; then
+						echo $pfx$i
+					fi
+					;;
+				esac
 			done
 			format="refname:strip=2"
 			refs=("refs/tags/$cur_*" "refs/tags/$cur_*/**"
@@ -432,12 +438,18 @@ __git_refs ()
 		;;
 	*)
 		if [ "$list_refs_from" = remote ]; then
-			echo "HEAD"
+			case "HEAD" in
+			$cur_*)	echo "HEAD" ;;
+			esac
 			__git for-each-ref --format="%(refname:strip=3)" \
 				"refs/remotes/$remote/$cur_*" \
 				"refs/remotes/$remote/$cur_*/**"
 		else
-			__git ls-remote "$remote" HEAD \
+			local query_symref
+			case "HEAD" in
+			$cur_*)	query_symref="HEAD" ;;
+			esac
+			__git ls-remote "$remote" $query_symref \
 				"refs/tags/$cur_*" "refs/heads/$cur_*" \
 				"refs/remotes/$cur_*" |
 			while read -r hash i; do
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 499be5879..5e06acc17 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -847,7 +847,6 @@ test_expect_success 'setup for filtering matching refs' '
 
 test_expect_success '__git_refs - only matching refs' '
 	cat >expected <<-EOF &&
-	HEAD
 	matching-branch
 	matching/branch
 	matching-tag
@@ -874,7 +873,6 @@ test_expect_success '__git_refs - only matching refs - full refs' '
 
 test_expect_success '__git_refs - only matching refs - remote on local file system' '
 	cat >expected <<-EOF &&
-	HEAD
 	master-in-other
 	matching/branch-in-other
 	EOF
@@ -887,7 +885,6 @@ test_expect_success '__git_refs - only matching refs - remote on local file syst
 
 test_expect_success '__git_refs - only matching refs - configured remote' '
 	cat >expected <<-EOF &&
-	HEAD
 	master-in-other
 	matching/branch-in-other
 	EOF
@@ -912,7 +909,6 @@ test_expect_success '__git_refs - only matching refs - remote - full refs' '
 
 test_expect_success '__git_refs - only matching refs - checkout DWIMery' '
 	cat >expected <<-EOF &&
-	HEAD
 	matching-branch
 	matching/branch
 	matching-tag
-- 
2.11.0.555.g967c1bcb3