]> git.ipfire.org Git - thirdparty/git.git/commitdiff
completion: hide dotfiles by default for path completion
authorZakariyah Ali <zakariyahali100@gmail.com>
Sat, 20 Jun 2026 17:55:56 +0000 (17:55 +0000)
committerJunio C Hamano <gitster@pobox.com>
Sun, 21 Jun 2026 01:02:48 +0000 (18:02 -0700)
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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib/completion/git-completion.bash
t/t9902-completion.sh

index e8f8fab125b42b004e672cc28bddeb37f96f3c70..b0b1b3c27aa61b13f50c5fb29b3367e42d210073 100644 (file)
@@ -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 ()
index 02aaf71876ea0aefe6b07346d8a39a2c36f52b42..7a7594455ca02eb1a46dafbb8853273da37a1f2e 100755 (executable)
@@ -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 &&