patch 9.0.1946: filename expansion using ** in bash may fail

Commit: 
https://github.com/vim/vim/commit/9eb1ce531527a7177d16373b0f8689bbcd3d5f73
Author: Christian Brabandt <c...@256bit.org>
Date:   Wed Sep 27 19:08:25 2023 +0200

    patch 9.0.1946: filename expansion using ** in bash may fail
    
    Problem:  filename expansion using ** in bash may fail
    Solution: Try to enable the globstar setting
    
    Starting with bash 4.0 it supports extended globbing using the globstar
    shell option. This makes matching recursively below a certain directory
    using the ** pattern work as expected nowadays.  However, we need to
    explicitly enable this using the 'shopt -s globstar' bash command.
    
    So let's check the bash environment variable $BASH_VERSINFO (which is
    supported since bash 3.0 and conditionally enable the globstar option,
    if the major version is at least 4. For older bashs, this at least
    shouldn't cause errors (unless one is using really ancient bash 2.X or
    something).
    
    closes: #13002
    closes: #13144
    
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt
index da9aeb7fe..46279110a 100644
--- a/runtime/doc/editing.txt
+++ b/runtime/doc/editing.txt
@@ -1,4 +1,4 @@
-*editing.txt*   For Vim version 9.0.  Last change: 2023 Apr 23
+*editing.txt*   For Vim version 9.0.  Last change: 2023 Sep 22
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -385,7 +385,9 @@ as a wildcard when "[" is in the 'isfname' option.  A 
simple way to avoid this
 is to use "path\[[]abc]", this matches the file "path\[abc]".
 
                                        *starstar-wildcard*
-Expanding "**" is possible on Unix, Win32, macOS and a few other systems.
+Expanding "**" is possible on Unix, Win32, macOS and a few other systems (but
+it may depend on your 'shell' setting. It's known to work correctly for zsh; 
for
+bash this requires at least bash version >= 4.X).
 This allows searching a directory tree.  This goes up to 100 directories deep.
 Note there are some commands where this works slightly differently, see
 |file-searching|.
diff --git a/src/os_unix.c b/src/os_unix.c
index 45c6b440a..c5a54e419 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -6701,14 +6701,17 @@ mch_expand_wildcards(
 #define STYLE_GLOB     1       // use "glob", for csh
 #define STYLE_VIMGLOB  2       // use "vimglob", for Posix sh
 #define STYLE_PRINT    3       // use "print -N", for zsh
-#define STYLE_BT       4       // `cmd` expansion, execute the pattern
-                               // directly
+#define STYLE_BT       4       // `cmd` expansion, execute the pattern directly
+#define STYLE_GLOBSTAR 5       // use extended shell glob for bash (this uses 
extended
+                               // globbing functionality using globstar, needs 
bash > 4)
     int                shell_style = STYLE_ECHO;
     int                check_spaces;
     static int did_find_nul = FALSE;
     int                ampersand = FALSE;
                // vimglob() function to define for Posix shell
     static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo 
\"$1\"; shift; done }; vimglob >";
+               // vimglob() function with globstar setting enabled, only for 
bash >= 4.X
+    static char *sh_globstar_opt = "[[ ${BASH_VERSINFO[0]} -ge 4 ]] && shopt 
-s globstar; ";
 
     *num_file = 0;     // default: no files found
     *file = NULL;
@@ -6755,6 +6758,8 @@ mch_expand_wildcards(
      *     If we use *zsh, "print -N" will work better than "glob".
      * STYLE_VIMGLOB:  NL separated
      *     If we use *sh*, we define "vimglob()".
+     * STYLE_GLOBSTAR: NL separated
+     *     If we use *bash*, we define "vimglob() and enable globstar option".
      * STYLE_ECHO:     space separated.
      *     A shell we don't know, stay safe and use "echo".
      */
@@ -6769,9 +6774,13 @@ mch_expand_wildcards(
        else if (STRCMP(p_sh + len - 3, "zsh") == 0)
            shell_style = STYLE_PRINT;
     }
-    if (shell_style == STYLE_ECHO && strstr((char *)gettail(p_sh),
-                                                               "sh") != NULL)
-       shell_style = STYLE_VIMGLOB;
+    if (shell_style == STYLE_ECHO)
+    {
+       if (strstr((char *)gettail(p_sh), "bash") != NULL)
+           shell_style = STYLE_GLOBSTAR;
+       else if (strstr((char *)gettail(p_sh), "sh") != NULL)
+           shell_style = STYLE_VIMGLOB;
+    }
 
     // Compute the length of the command.  We need 2 extra bytes: for the
     // optional '&' and for the NUL.
@@ -6779,6 +6788,9 @@ mch_expand_wildcards(
     len = STRLEN(tempname) + 29;
     if (shell_style == STYLE_VIMGLOB)
        len += STRLEN(sh_vimglob_func);
+    else if (shell_style == STYLE_GLOBSTAR)
+       len += STRLEN(sh_vimglob_func)
+            + STRLEN(sh_globstar_opt);
 
     for (i = 0; i < num_pat; ++i)
     {
@@ -6847,6 +6859,11 @@ mch_expand_wildcards(
            STRCAT(command, "print -N >");
        else if (shell_style == STYLE_VIMGLOB)
            STRCAT(command, sh_vimglob_func);
+       else if (shell_style == STYLE_GLOBSTAR)
+       {
+           STRCAT(command, sh_globstar_opt);
+           STRCAT(command, sh_vimglob_func);
+       }
        else
            STRCAT(command, "echo >");
     }
@@ -7031,7 +7048,9 @@ mch_expand_wildcards(
        }
     }
     // file names are separated with NL
-    else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB)
+    else if (shell_style == STYLE_BT ||
+           shell_style == STYLE_VIMGLOB ||
+           shell_style == STYLE_GLOBSTAR)
     {
        buffer[len] = NUL;              // make sure the buffer ends in NUL
        p = buffer;
@@ -7112,7 +7131,7 @@ mch_expand_wildcards(
        (*file)[i] = p;
        // Space or NL separates
        if (shell_style == STYLE_ECHO || shell_style == STYLE_BT
-                                             || shell_style == STYLE_VIMGLOB)
+               || shell_style == STYLE_VIMGLOB || shell_style == 
STYLE_GLOBSTAR)
        {
            while (!(shell_style == STYLE_ECHO && *p == ' ')
                                                   && *p != '
' && *p != NUL)
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim
index 2cc57163d..4ec466685 100644
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -3625,4 +3625,23 @@ func Test_fullcommand()
   call assert_equal('', fullcommand(10))
 endfunc
 
+" Test for glob() with shell special patterns
+func Test_glob_extended_bash()
+  CheckExecutable bash
+  let _shell = &shell
+  set shell=bash
+
+  call mkdir('Xtestglob/foo/bar/src', 'p')
+  call writefile([], 'Xtestglob/foo/bar/src/foo.sh')
+  call writefile([], 'Xtestglob/foo/bar/src/foo.h')
+  call writefile([], 'Xtestglob/foo/bar/src/foo.cpp')
+
+  " Sort output of glob() otherwise we end up with different
+  " ordering depending on whether file system is case-sensitive.
+  let expected = ['Xtestglob/foo/bar/src/foo.cpp', 
'Xtestglob/foo/bar/src/foo.h']
+  call assert_equal(expected, sort(glob('Xtestglob/**/foo.{h,cpp}', 0, 1)))
+  call delete('Xtestglob', 'rf')
+  let &shell=_shell
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index aef4b1a64..d54df70ba 100644
--- a/src/version.c
+++ b/src/version.c
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1946,
 /**/
     1945,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1qlY7u-00EKjQ-Fu%40256bit.org.

Raspunde prin e-mail lui