]> git.ipfire.org Git - thirdparty/git.git/commitdiff
completion: handle unusual characters for sparse-checkout
authorLessley Dennington <lessleydennington@gmail.com>
Mon, 7 Feb 2022 17:31:45 +0000 (17:31 +0000)
committerJunio C Hamano <gitster@pobox.com>
Tue, 8 Feb 2022 18:15:43 +0000 (10:15 -0800)
Update the __gitcomp_directories method to de-quote and handle unusual
characters in directory names. Although this initially involved an attempt
to re-use the logic in __git_index_files, this method removed
subdirectories (e.g. folder1/0/ became folder1/), so instead new custom
logic was placed directly in the __gitcomp_directories method.

Note there are two tests for this new functionality - one for spaces and
accents and one for backslashes and tabs. The backslashes and tabs test
uses FUNNYNAMES to avoid running on Windows. This is because:

1. Backslashes are explicitly not allowed in Windows file paths.
2. Although tabs appear to be allowed when creating a file in a Windows
bash shell, they actually are not renderable (and appear as empty boxes
in the shell).

Co-authored-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Co-authored-by: Lessley Dennington <lessleydennington@gmail.com>
Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Lessley Dennington <lessleydennington@gmail.com>
Reviewed-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib/completion/git-completion.bash
t/t9902-completion.sh

index 69ef33b56be947413fbeb64294e4abdc2242db47..23e4c9089089068e4ea73f914cca9c5d1e993f27 100644 (file)
@@ -2988,7 +2988,7 @@ _git_show_branch ()
 
 __gitcomp_directories ()
 {
-       local _tmp_dir _tmp_completions
+       local _tmp_dir _tmp_completions _found=0
 
        # Get the directory of the current token; this differs from dirname
        # in that it keeps up to the final trailing slash.  If no slash found
@@ -2996,20 +2996,18 @@ __gitcomp_directories ()
        [[ "$cur" =~ .*/ ]]
        _tmp_dir=$BASH_REMATCH
 
-       # Find possible directory completions, adding trailing '/' characters
-       _tmp_completions="$(git ls-tree -d --name-only HEAD $_tmp_dir |
-               sed -e s%$%/%)"
-
-       if [[ -n "$_tmp_completions" ]]; then
-               # There were some directory completions, so find ones that
-               # start with "$cur", the current token, and put those in COMPREPLY
-               local i=0 c IFS=$' \t\n'
-               for c in $_tmp_completions; do
+       # Find possible directory completions, adding trailing '/' characters,
+       # de-quoting, and handling unusual characters.
+       while IFS= read -r -d $'\0' c ; do
+               # If there are directory completions, find ones that start
+               # with "$cur", the current token, and put those in COMPREPLY
                if [[ $c == "$cur"* ]]; then
-                       COMPREPLY+=("$c")
+                       COMPREPLY+=("$c/")
+                       _found=1
                fi
-               done
-       elif [[ "$cur" =~ /$ ]]; then
+       done < <(git ls-tree -z -d --name-only HEAD $_tmp_dir)
+
+       if [[ $_found == 0 ]] && [[ "$cur" =~ /$ ]]; then
                # No possible further completions any deeper, so assume we're at
                # a leaf directory and just consider it complete
                __gitcomp_direct_append "$cur "
index f309c7532e2142420401cc521dfab725c1f97fab..96dbda97cfc5d0c47ed7454b344823a94748377d 100755 (executable)
@@ -1505,6 +1505,55 @@ test_expect_success 'cone mode sparse-checkout completes directory names' '
        )
 '
 
+test_expect_success 'cone mode sparse-checkout completes directory names with spaces and accents' '
+       # reset sparse-checkout
+       git -C sparse-checkout sparse-checkout disable &&
+       (
+               cd sparse-checkout &&
+               mkdir "directory with spaces" &&
+               mkdir "directory-with-áccent" &&
+               >"directory with spaces/randomfile" &&
+               >"directory-with-áccent/randomfile" &&
+               git add . &&
+               git commit -m "Add directory with spaces and directory with accent" &&
+               git sparse-checkout set --cone "directory with spaces" \
+                       "directory-with-áccent" &&
+               test_completion "git sparse-checkout add dir" <<-\EOF &&
+               directory with spaces/
+               directory-with-áccent/
+               EOF
+               rm -rf "directory with spaces" &&
+               rm -rf "directory-with-áccent" &&
+               git add . &&
+               git commit -m "Remove directory with spaces and directory with accent"
+       )
+'
+
+# use FUNNYNAMES to avoid running on Windows, which doesn't permit backslashes or tabs in paths
+test_expect_success FUNNYNAMES 'cone mode sparse-checkout completes directory names with backslashes and tabs' '
+       # reset sparse-checkout
+       git -C sparse-checkout sparse-checkout disable &&
+       (
+               cd sparse-checkout &&
+               mkdir "directory\with\backslashes" &&
+               mkdir "$(printf "directory\twith\ttabs")" &&
+               >"directory\with\backslashes/randomfile" &&
+               >"$(printf "directory\twith\ttabs")/randomfile" &&
+               git add . &&
+               git commit -m "Add directory with backslashes and directory with tabs" &&
+               git sparse-checkout set --cone "directory\with\backslashes" \
+                       "$(printf "directory\twith\ttabs")" &&
+               test_completion "git sparse-checkout add dir" <<-\EOF &&
+               directory\with\backslashes/
+               directory       with    tabs/
+               EOF
+               rm -rf "directory\with\backslashes" &&
+               rm -rf "$(printf "directory\twith\ttabs")" &&
+               git add . &&
+               git commit -m "Remove directory with backslashes and directory with tabs"
+       )
+'
+
 test_expect_success 'non-cone mode sparse-checkout uses bash completion' '
        # reset sparse-checkout repo to non-cone mode
        git -C sparse-checkout sparse-checkout disable &&