vim-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: vim/vim#13002
closes: vim/vim#13144

9eb1ce5315

Co-authored-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
zeertzjq
2023-09-28 05:09:21 +08:00
parent 7f58b2bb6a
commit 92e40f8d18
3 changed files with 44 additions and 6 deletions

View File

@@ -134,6 +134,8 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
#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_GLOBSTAR 5 // use extended shell glob for bash (this uses extended
// globbing functionality with globstar, needs bash > 4)
int shell_style = STYLE_ECHO;
int check_spaces;
static bool did_find_nul = false;
@@ -141,6 +143,9 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
// 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; ";
bool is_fish_shell =
#if defined(UNIX)
@@ -190,6 +195,8 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
// 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".
if (num_pat == 1 && *pat[0] == '`'
@@ -203,9 +210,12 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
shell_style = STYLE_PRINT;
}
}
if (shell_style == STYLE_ECHO
&& strstr(path_tail(p_sh), "sh") != NULL) {
shell_style = STYLE_VIMGLOB;
if (shell_style == STYLE_ECHO) {
if (strstr(path_tail(p_sh), "bash") != NULL) {
shell_style = STYLE_GLOBSTAR;
} else if (strstr(path_tail(p_sh), "sh") != NULL) {
shell_style = STYLE_VIMGLOB;
}
}
// Compute the length of the command. We need 2 extra bytes: for the
@@ -214,6 +224,8 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
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++) {
@@ -281,6 +293,9 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
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 >");
}
@@ -430,7 +445,9 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
p = skipwhite(p); // skip to next entry
}
// 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;
for (i = 0; *p != NUL; i++) { // count number of entries
@@ -496,7 +513,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
(*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 != '\n' && *p != NUL) {
p++;