Git development
 help / color / mirror / Atom feed
From: "Zakariyah Ali via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Zakariyah Ali <zakariyahali100@gmail.com>,
	Zakariyah Ali <zakariyahali100@gmail.com>,
	Zakariyah Ali <zakariyahali100@gmail.com>
Subject: [PATCH v3 2/2] completion: hide dotfiles by default for path completion
Date: Sat, 20 Jun 2026 17:55:56 +0000	[thread overview]
Message-ID: <7482ee46454606a0883117d6cded6df809de710c.1781978156.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2311.v3.git.git.1781978156.gitgitgadget@gmail.com>

From: Zakariyah Ali <zakariyahali100@gmail.com>

The previous implementation required callers to explicitly pass a
"hide-dotfiles" flag to __git_complete_index_file to avoid cluttering
completions with hidden files. This led to inconsistent behavior across
commands (e.g., `git add` and `git mv` behaved differently) and forced
callers to maintain repetitive logic.

As suggested by Junio C Hamano, this commit simplifies the logic:
1. __git_complete_index_file now unconditionally hides dotfiles when
   no match pattern is provided.
2. The awk loop in __git_index_files is refactored to check the dotfile
   condition in a single, obvious place after handling path dequoting,
   removing the previous duplication.
3. Callers no longer need to pass "hide-dotfiles".

This provides a cleaner API and ensures a consistent, expected behavior
where dotfiles are hidden unless explicitly requested by typing a dot.

Signed-off-by: Zakariyah Ali <zakariyahali100@gmail.com>
---
 contrib/completion/git-completion.bash | 65 ++++++++++++--------------
 t/t9902-completion.sh                  |  9 +++-
 2 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index e8f8fab125..b0b1b3c27a 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -638,20 +638,23 @@ __git_ls_files_helper ()
 }
 
 
-# __git_index_files accepts 1 to 4 arguments:
+# __git_index_files accepts 1 to 3 arguments:
 # 1: Options to pass to ls-files (required).
 # 2: A directory path (optional).
 #    If provided, only files within the specified directory are listed.
 #    Sub directories are never recursed.  Path must have a trailing
 #    slash.
 # 3: List only paths matching this path component (optional).
-# 4: Hide paths whose first component starts with a dot if this is
-#    "hide-dotfiles" and the third argument is empty (optional).
+#
+# If the third argument is empty, paths that begin with a dot (dotfiles)
+# are hidden. This matches user expectations where dotfiles are considered
+# hidden configuration files/directories and shouldn't clutter default
+# completions unless explicitly requested by typing a dot.
 __git_index_files ()
 {
-	local root="$2" match="$3" hide_dotfiles="${4-}"
+	local root="$2" match="$3"
 	local hide_dotfiles_awk=0
-	if [ "$hide_dotfiles" = "hide-dotfiles" ] && [ -z "$match" ]; then
+	if [ -z "$match" ]; then
 		hide_dotfiles_awk=1
 	fi
 
@@ -661,28 +664,22 @@ __git_index_files ()
 	}
 	END {
 		for (p in paths) {
-			if (substr(p, 1, 1) != "\"") {
-				# No special characters, easy!
-				if (hide_dotfiles == 1 && substr(p, 1, 1) == ".")
+			if (substr(p, 1, 1) == "\"") {
+				# The path is quoted.
+				p = dequote(p)
+				if (p == "")
 					continue
-				print pfx p
-				continue
-			}
-
-			# The path is quoted.
-			p = dequote(p)
-			if (p == "")
-				continue
 
-			# Even when a directory name itself does not contain
-			# any special characters, it will still be quoted if
-			# any of its (stripped) trailing path components do.
-			# Because of this we may have seen the same directory
-			# both quoted and unquoted.
-			if (p in paths)
-				# We have seen the same directory unquoted,
-				# skip it.
-				continue
+				# Even when a directory name itself does not contain
+				# any special characters, it will still be quoted if
+				# any of its (stripped) trailing path components do.
+				# Because of this we may have seen the same directory
+				# both quoted and unquoted.
+				if (p in paths)
+					# We have seen the same directory unquoted,
+					# skip it.
+					continue
+			}
 
 			if (hide_dotfiles == 1 && substr(p, 1, 1) == ".")
 				continue
@@ -731,15 +728,13 @@ __git_index_files ()
 	}'
 }
 
-# __git_complete_index_file accepts 1 or 2 arguments:
-# 1: the options to pass to ls-file
-# 2: Hide paths whose first component starts with a dot if this is
-#    "hide-dotfiles" and the current word is empty (optional).
+# __git_complete_index_file accepts 1 argument:
+# 1: the options to pass to ls-files
 #
 # The exception is --committable, which finds the files appropriate commit.
 __git_complete_index_file ()
 {
-	local dequoted_word pfx="" cur_ hide_dotfiles="${2-}"
+	local dequoted_word pfx="" cur_
 
 	__git_dequote "$cur"
 
@@ -752,7 +747,7 @@ __git_complete_index_file ()
 		cur_="$dequoted_word"
 	esac
 
-	__gitcomp_file_direct "$(__git_index_files "$1" "$pfx" "$cur_" "$hide_dotfiles")"
+	__gitcomp_file_direct "$(__git_index_files "$1" "$pfx" "$cur_")"
 }
 
 # Lists branches from the local repository.
@@ -2176,7 +2171,7 @@ _git_ls_files ()
 
 	# XXX ignore options like --modified and always suggest all cached
 	# files.
-	__git_complete_index_file "--cached" hide-dotfiles
+	__git_complete_index_file "--cached"
 }
 
 _git_ls_remote ()
@@ -2409,9 +2404,9 @@ _git_mv ()
 	if [ $(__git_count_arguments "mv") -gt 0 ]; then
 		# We need to show both cached and untracked files (including
 		# empty directories) since this may not be the last argument.
-		__git_complete_index_file "--cached --others --directory" hide-dotfiles
+		__git_complete_index_file "--cached --others --directory"
 	else
-		__git_complete_index_file "--cached" hide-dotfiles
+		__git_complete_index_file "--cached"
 	fi
 }
 
@@ -3231,7 +3226,7 @@ _git_rm ()
 		;;
 	esac
 
-	__git_complete_index_file "--cached" hide-dotfiles
+	__git_complete_index_file "--cached"
 }
 
 _git_shortlog ()
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 02aaf71876..7a7594455c 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2360,6 +2360,7 @@ test_expect_success 'setup for path completion tests' '
 	      "spaces in dir" \
 	      árvíztűrő &&
 	touch simple-dir/simple-file \
+	      simple-dir/.dotfile-in-dir \
 	      "spaces in dir/spaces in file" \
 	      "árvíztűrő/Сайн яваарай" &&
 	if test_have_prereq !MINGW &&
@@ -2380,6 +2381,11 @@ test_expect_success '__git_complete_index_file - simple' '
 	test_path_completion simple-dir/simple simple-dir/simple-file
 '
 
+test_expect_success '__git_complete_index_file - dotfiles' '
+	test_path_completion "simple-dir/" "simple-dir/simple-file" &&
+	test_path_completion "simple-dir/." "simple-dir/.dotfile-in-dir"
+'
+
 test_expect_success \
     '__git_complete_index_file - escaped characters on cmdline' '
 	test_path_completion spac "spaces in dir" &&  # Bash will turn this
@@ -2789,7 +2795,8 @@ test_expect_success 'complete files' '
 	echo "out_sorted" >> .gitignore &&
 
 	git add .gitignore &&
-	test_completion "git commit " ".gitignore" &&
+	test_completion "git commit " "" &&
+	test_completion "git commit ." ".gitignore" &&
 
 	git commit -m ignore &&
 
-- 
gitgitgadget

  parent reply	other threads:[~2026-06-20 17:56 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-24  2:36 [PATCH] completion: hide dotfiles for selected path completion Zakariyah Ali via GitGitGadget
2026-05-24 12:08 ` Junio C Hamano
2026-05-26 15:23 ` [PATCH v2] " Zakariyah Ali via GitGitGadget
2026-05-27  3:22   ` Junio C Hamano
2026-06-03 18:09   ` Follow-up and appreciation regarding Git contributions Zakariyah Ali
2026-06-10 18:56   ` [PATCH v2] completion: hide dotfiles for selected path completion Junio C Hamano
2026-06-20 17:55   ` [PATCH v3 0/2] " Zakariyah Ali via GitGitGadget
2026-06-20 17:55     ` [PATCH v3 1/2] " Zakariyah Ali via GitGitGadget
2026-06-20 17:55     ` Zakariyah Ali via GitGitGadget [this message]
2026-06-21  1:17     ` [PATCH v3 0/2] " Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7482ee46454606a0883117d6cded6df809de710c.1781978156.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=zakariyahali100@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox