From fd6d9bec145924ba704b34f0788b239bff9d2898 Mon Sep 17 00:00:00 2001 From: Lessley Dennington Date: Mon, 7 Feb 2022 17:31:43 +0000 Subject: completion: address sparse-checkout issues Correct multiple issues with tab completion of the git sparse-checkout command. These issues were: 1. git sparse-checkout previously resulted in an incomplete list of subcommands (it was missing reapply and add). 2. Subcommand options were not tab-completable. 3. git sparse-checkout set and git sparse-checkout add showed both file names and directory names. While this may be a less surprising behavior for non-cone mode, cone mode sparse checkouts should complete only directory names. Note that while the new strategy of just using git ls-tree to complete on directory names is simple and a step in the right direction, it does have some caveats. These are: 1. Likelihood of poor performance in large monorepos (as a result of recursively completing directory names). 2. Inability to handle paths containing unusual characters. These caveats will be fixed by subsequent commits in this series. Signed-off-by: Lessley Dennington Reviewed-by: Elijah Newren Signed-off-by: Junio C Hamano --- contrib/completion/git-completion.bash | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'contrib') diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 377d6c5494..ebeffaa982 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -2988,7 +2988,7 @@ _git_show_branch () _git_sparse_checkout () { - local subcommands="list init set disable" + local subcommands="list init set disable add reapply" local subcommand="$(__git_find_on_cmdline "$subcommands")" if [ -z "$subcommand" ]; then __gitcomp "$subcommands" @@ -2996,14 +2996,14 @@ _git_sparse_checkout () fi case "$subcommand,$cur" in - init,--*) - __gitcomp "--cone" - ;; - set,--*) - __gitcomp "--stdin" - ;; - *) + *,--*) + __gitcomp_builtin sparse-checkout_$subcommand "" "--" ;; + set,*|add,*) + if [ "$(__git config core.sparseCheckoutCone)" == "true" ] || + [ -n "$(__git_find_on_cmdline --cone)" ]; then + __gitcomp "$(git ls-tree -d -r HEAD --name-only)" + fi esac } -- cgit v1.2.3 From c5f5c5082f813a875c213445135a24c2507021dd Mon Sep 17 00:00:00 2001 From: Lessley Dennington Date: Mon, 7 Feb 2022 17:31:44 +0000 Subject: completion: improve sparse-checkout cone mode directory completion Use new __gitcomp_directories method to complete directory names in cone mode sparse-checkouts. This method addresses the caveat of poor performance in monorepos from the previous commit (by completing only one level of directories). The unusual character caveat from the previous commit will be fixed by the final commit in this series. Co-authored-by: Elijah Newren Co-authored-by: Lessley Dennington Signed-off-by: Lessley Dennington Reviewed-by: Elijah Newren Signed-off-by: Junio C Hamano --- contrib/completion/git-completion.bash | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'contrib') diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index ebeffaa982..69ef33b56b 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -2986,6 +2986,36 @@ _git_show_branch () __git_complete_revlist } +__gitcomp_directories () +{ + local _tmp_dir _tmp_completions + + # 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 + # that's fine too. + [[ "$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 + if [[ $c == "$cur"* ]]; then + COMPREPLY+=("$c") + fi + done + elif [[ "$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 " + fi +} + _git_sparse_checkout () { local subcommands="list init set disable add reapply" @@ -3002,7 +3032,7 @@ _git_sparse_checkout () set,*|add,*) if [ "$(__git config core.sparseCheckoutCone)" == "true" ] || [ -n "$(__git_find_on_cmdline --cone)" ]; then - __gitcomp "$(git ls-tree -d -r HEAD --name-only)" + __gitcomp_directories fi esac } -- cgit v1.2.3 From 48803821b1712687d6e06e9d7a0e911eabecf4d1 Mon Sep 17 00:00:00 2001 From: Lessley Dennington Date: Mon, 7 Feb 2022 17:31:45 +0000 Subject: completion: handle unusual characters for sparse-checkout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Co-authored-by: Lessley Dennington Helped-by: Ævar Arnfjörð Bjarmason Signed-off-by: Lessley Dennington Reviewed-by: Elijah Newren Signed-off-by: Junio C Hamano --- contrib/completion/git-completion.bash | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'contrib') diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 69ef33b56b..23e4c90890 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -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 " -- cgit v1.2.3