mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #25398 from zeertzjq/vim-9.0.1946
vim-patch:9.0.{0607,1946,1947}: filename expansion using ** in bash may fail
This commit is contained in:
commit
1117d29b20
@ -356,7 +356,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|.
|
||||
|
@ -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++;
|
||||
|
@ -108,6 +108,22 @@ func CheckNotBSD()
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Command to check for not running on a MacOS
|
||||
command CheckNotMac call CheckNotMac()
|
||||
func CheckNotMac()
|
||||
if has('mac')
|
||||
throw 'Skipped: does not work on MacOS'
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Command to check for not running on a MacOS M1 system.
|
||||
command CheckNotMacM1 call CheckNotMacM1()
|
||||
func CheckNotMacM1()
|
||||
if has('mac') && system('uname -a') =~ '\<arm64\>'
|
||||
throw 'Skipped: does not work on MacOS M1'
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Command to check that making screendumps is supported.
|
||||
" Caller must source screendump.vim
|
||||
command CheckScreendump call CheckScreendump()
|
||||
|
@ -3281,4 +3281,26 @@ func Test_fullcommand()
|
||||
call assert_equal('', fullcommand(10))
|
||||
endfunc
|
||||
|
||||
" Test for glob() with shell special patterns
|
||||
func Test_glob_extended_bash()
|
||||
CheckExecutable bash
|
||||
CheckNotMSWindows
|
||||
CheckNotMac " The default version of bash is old on macOS.
|
||||
|
||||
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
|
||||
|
@ -379,7 +379,8 @@ endfunc
|
||||
" Test verbose message before echo command
|
||||
func Test_echo_verbose_system()
|
||||
CheckRunVimInTerminal
|
||||
CheckUnix
|
||||
CheckUnix " needs the "seq" command
|
||||
CheckNotMac " doesn't use /tmp
|
||||
|
||||
let buf = RunVimInTerminal('', {'rows': 10})
|
||||
call term_sendkeys(buf, ":4 verbose echo system('seq 20')\<CR>")
|
||||
|
Loading…
Reference in New Issue
Block a user