aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShougo <Shougo.Matsu@gmail.com>2021-05-07 21:07:13 +0900
committerGitHub <noreply@github.com>2021-05-07 08:07:13 -0400
commit4be0e92db01a502863ac4bb26dd0fee16d833145 (patch)
treee6e578f6d598769c2a465974c07c29eca1aadddf
parent17434b88b4892218386b49b400e7eb6d265000ff (diff)
downloadrneovim-4be0e92db01a502863ac4bb26dd0fee16d833145.tar.gz
rneovim-4be0e92db01a502863ac4bb26dd0fee16d833145.tar.bz2
rneovim-4be0e92db01a502863ac4bb26dd0fee16d833145.zip
vim-patch:8.1.1378: delete() can not handle a file name that looks like a pattern (#12784)
Problem: Delete() can not handle a file name that looks like a pattern. Solution: Use readdir() instead of appending "/*" and expanding wildcards. (Ken Takata, closes vim/vim#4424, closes vim/vim#696) https://github.com/vim/vim/commit/701ff0a3e53d253d7300c385e582659bbff7860d
-rw-r--r--src/nvim/eval/funcs.c62
-rw-r--r--src/nvim/fileio.c109
-rw-r--r--src/nvim/testdir/test_arglist.vim18
-rw-r--r--src/nvim/testdir/test_command_count.vim2
-rw-r--r--src/nvim/testdir/test_functions.vim19
-rw-r--r--src/nvim/testdir/test_quickfix.vim10
-rw-r--r--src/nvim/testdir/test_registers.vim3
-rw-r--r--test/functional/legacy/011_autocommands_spec.lua2
-rw-r--r--test/functional/legacy/delete_spec.lua78
-rw-r--r--test/functional/legacy/packadd_spec.lua1
10 files changed, 135 insertions, 169 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 60af592108..b3df081932 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -6628,37 +6628,6 @@ static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// Evaluate "expr" for readdir().
-static varnumber_T readdir_checkitem(typval_T *expr, const char *name)
-{
- typval_T save_val;
- typval_T rettv;
- typval_T argv[2];
- varnumber_T retval = 0;
- bool error = false;
-
- prepare_vimvar(VV_VAL, &save_val);
- set_vim_var_string(VV_VAL, name, -1);
- argv[0].v_type = VAR_STRING;
- argv[0].vval.v_string = (char_u *)name;
-
- if (eval_expr_typval(expr, argv, 1, &rettv) == FAIL) {
- goto theend;
- }
-
- retval = tv_get_number_chk(&rettv, &error);
- if (error) {
- retval = -1;
- }
-
- tv_clear(&rettv);
-
-theend:
- set_vim_var_string(VV_VAL, NULL, 0);
- restore_vimvar(VV_VAL, &save_val);
- return retval;
-}
-
// "readdir()" function
static void f_readdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
@@ -6670,43 +6639,14 @@ static void f_readdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_list_alloc_ret(rettv, kListLenUnknown);
path = tv_get_string(&argvars[0]);
expr = &argvars[1];
- ga_init(&ga, (int)sizeof(char *), 20);
if (!os_scandir(&dir, path)) {
smsg(_(e_notopen), path);
} else {
- for (;;) {
- bool ignore;
-
- path = os_scandir_next(&dir);
- if (path == NULL) {
- break;
- }
-
- ignore = (path[0] == '.'
- && (path[1] == NUL || (path[1] == '.' && path[2] == NUL)));
- if (!ignore && expr->v_type != VAR_UNKNOWN) {
- varnumber_T r = readdir_checkitem(expr, path);
-
- if (r < 0) {
- break;
- }
- if (r == 0) {
- ignore = true;
- }
- }
-
- if (!ignore) {
- ga_grow(&ga, 1);
- ((char **)ga.ga_data)[ga.ga_len++] = xstrdup(path);
- }
- }
-
- os_closedir(&dir);
+ readdir_core(&ga, &dir, expr, true);
}
if (rettv->vval.v_list != NULL && ga.ga_len > 0) {
- sort_strings((char_u **)ga.ga_data, ga.ga_len);
for (int i = 0; i < ga.ga_len; i++) {
path = ((const char **)ga.ga_data)[i];
tv_list_append_string(rettv->vval.v_list, path, -1);
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 29c29a2884..2037ba5f19 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -5204,38 +5204,113 @@ static void vim_maketempdir(void)
(void)umask(umask_save);
}
+// Evaluate "expr" for readdir().
+static varnumber_T readdir_checkitem(typval_T *expr, const char *name)
+{
+ typval_T save_val;
+ typval_T rettv;
+ typval_T argv[2];
+ varnumber_T retval = 0;
+ bool error = false;
+
+ prepare_vimvar(VV_VAL, &save_val);
+ set_vim_var_string(VV_VAL, name, -1);
+ argv[0].v_type = VAR_STRING;
+ argv[0].vval.v_string = (char_u *)name;
+
+ if (eval_expr_typval(expr, argv, 1, &rettv) == FAIL) {
+ goto theend;
+ }
+
+ retval = tv_get_number_chk(&rettv, &error);
+ if (error) {
+ retval = -1;
+ }
+
+ tv_clear(&rettv);
+
+theend:
+ set_vim_var_string(VV_VAL, NULL, 0);
+ restore_vimvar(VV_VAL, &save_val);
+ return retval;
+}
+
+/// Core part of "readdir()" function.
+/// Retrieve the list of files/directories of "dirp" into "gap".
+void readdir_core(
+ garray_T *gap,
+ Directory *dirp,
+ typval_T *expr,
+ bool is_checkitem)
+{
+ ga_init(gap, (int)sizeof(char *), 20);
+
+ for (;;) {
+ bool ignore;
+
+ const char *path = os_scandir_next(dirp);
+ if (path == NULL) {
+ break;
+ }
+
+ ignore = (path[0] == '.'
+ && (path[1] == NUL || (path[1] == '.' && path[2] == NUL)));
+ if (!ignore && expr != NULL && expr->v_type != VAR_UNKNOWN
+ && is_checkitem) {
+ varnumber_T r = readdir_checkitem(expr, path);
+
+ if (r < 0) {
+ break;
+ }
+ if (r == 0) {
+ ignore = true;
+ }
+ }
+
+ if (!ignore) {
+ ga_grow(gap, 1);
+ ((char **)gap->ga_data)[gap->ga_len++] = xstrdup(path);
+ }
+ }
+
+ if (gap->ga_len > 0) {
+ sort_strings((char_u **)gap->ga_data, gap->ga_len);
+ }
+
+ os_closedir(dirp);
+}
+
/// Delete "name" and everything in it, recursively.
/// @param name The path which should be deleted.
/// @return 0 for success, -1 if some file was not deleted.
int delete_recursive(const char *name)
{
int result = 0;
+ char *exp = (char *)vim_strsave((char_u *)name);
+ Directory dir;
- if (os_isrealdir(name)) {
- snprintf((char *)NameBuff, MAXPATHL, "%s/*", name); // NOLINT
-
- char_u **files;
- int file_count;
- char_u *exp = vim_strsave(NameBuff);
- if (gen_expand_wildcards(1, &exp, &file_count, &files,
- EW_DIR | EW_FILE | EW_SILENT | EW_ALLLINKS
- | EW_DODOT | EW_EMPTYOK) == OK) {
- for (int i = 0; i < file_count; i++) {
- if (delete_recursive((const char *)files[i]) != 0) {
- result = -1;
- }
+ if (os_isrealdir(name) && os_scandir(&dir, exp)) {
+ garray_T ga;
+
+ readdir_core(&ga, &dir, NULL, false);
+
+ for (int i = 0; i < ga.ga_len; i++) {
+ vim_snprintf((char *)NameBuff, MAXPATHL, "%s/%s", exp,
+ ((char_u **)ga.ga_data)[i]);
+ if (delete_recursive((const char *)NameBuff) != 0) {
+ result = -1;
}
- FreeWild(file_count, files);
- } else {
- result = -1;
}
- xfree(exp);
+ ga_clear_strings(&ga);
+
os_rmdir(name);
} else {
result = os_remove(name) == 0 ? 0 : -1;
}
+ xfree(exp);
+
return result;
}
diff --git a/src/nvim/testdir/test_arglist.vim b/src/nvim/testdir/test_arglist.vim
index a1ef8325ec..08e578a226 100644
--- a/src/nvim/testdir/test_arglist.vim
+++ b/src/nvim/testdir/test_arglist.vim
@@ -26,6 +26,8 @@ func Test_argidx()
endfunc
func Test_argadd()
+ call Reset_arglist()
+
%argdelete
argadd a b c
call assert_equal(0, argidx())
@@ -103,6 +105,11 @@ func Init_abc()
next
endfunc
+func Reset_arglist()
+ cd
+ args a | %argd
+endfunc
+
func Assert_argc(l)
call assert_equal(len(a:l), argc())
let i = 0
@@ -115,8 +122,7 @@ endfunc
" Test for [count]argument and [count]argdelete commands
" Ported from the test_argument_count.in test script
func Test_argument()
- " Clean the argument list
- arga a | %argd
+ call Reset_arglist()
let save_hidden = &hidden
set hidden
@@ -244,8 +250,7 @@ endfunc
" Test for 0argadd and 0argedit
" Ported from the test_argument_0count.in test script
func Test_zero_argadd()
- " Clean the argument list
- arga a | %argd
+ call Reset_arglist()
arga a b c d
2argu
@@ -272,10 +277,6 @@ func Test_zero_argadd()
call assert_equal('file with spaces', expand('%'))
endfunc
-func Reset_arglist()
- args a | %argd
-endfunc
-
" Test for argc()
func Test_argc()
call Reset_arglist()
@@ -408,6 +409,7 @@ endfunc
" Test for the :argdelete command
func Test_argdelete()
call Reset_arglist()
+
args aa a aaa b bb
argdelete a*
call assert_equal(['b', 'bb'], argv())
diff --git a/src/nvim/testdir/test_command_count.vim b/src/nvim/testdir/test_command_count.vim
index 55b230373f..36ff4cd1bb 100644
--- a/src/nvim/testdir/test_command_count.vim
+++ b/src/nvim/testdir/test_command_count.vim
@@ -103,6 +103,8 @@ endfunc
func Test_command_count_2()
silent! %argd
+ cd
+
arga a b c d
call assert_fails('5argu', 'E16:')
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 93f567b3a0..c280aedffb 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -1402,6 +1402,10 @@ func Test_bufadd_bufload()
endfunc
func Test_readdir()
+ if isdirectory('Xdir')
+ call delete('Xdir', 'rf')
+ endif
+
call mkdir('Xdir')
call writefile([], 'Xdir/foo.txt')
call writefile([], 'Xdir/bar.txt')
@@ -1456,4 +1460,19 @@ func Test_default_arg_value()
call assert_equal('msg', HasDefault())
endfunc
+func Test_delete_rf()
+ call mkdir('Xdir')
+ call writefile([], 'Xdir/foo.txt')
+ call writefile([], 'Xdir/bar.txt')
+ call mkdir('Xdir/[a-1]') " issue #696
+ call writefile([], 'Xdir/[a-1]/foo.txt')
+ call writefile([], 'Xdir/[a-1]/bar.txt')
+ call assert_true(filereadable('Xdir/foo.txt'))
+ call assert_true(filereadable('Xdir/[a-1]/foo.txt'))
+
+ call assert_equal(0, delete('Xdir', 'rf'))
+ call assert_false(filereadable('Xdir/foo.txt'))
+ call assert_false(filereadable('Xdir/[a-1]/foo.txt'))
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index da949f5940..16b6a5f464 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -1011,10 +1011,9 @@ endfunc
" Tests for %D and %X errorformat options
func Test_efm_dirstack()
" Create the directory stack and files
- call mkdir('dir1')
- call mkdir('dir1/a')
- call mkdir('dir1/a/b')
- call mkdir('dir1/c')
+ call mkdir('dir1/a', 'p')
+ call mkdir('dir1/a/b', 'p')
+ call mkdir('dir1/c', 'p')
call mkdir('dir2')
let lines =<< trim [DATA]
@@ -3485,6 +3484,9 @@ func Xqftick_tests(cchar)
\ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
+ if isdirectory("Xone")
+ call delete("Xone", 'rf')
+ endif
call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
Xfile Xone
call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
diff --git a/src/nvim/testdir/test_registers.vim b/src/nvim/testdir/test_registers.vim
index 53069b3d31..bcadb84ced 100644
--- a/src/nvim/testdir/test_registers.vim
+++ b/src/nvim/testdir/test_registers.vim
@@ -43,6 +43,9 @@ func Test_yank_shows_register()
endfunc
func Test_display_registers()
+ " Disable clipboard
+ let g:clipboard = {}
+
e file1
e file2
call setline(1, ['foo', 'bar'])
diff --git a/test/functional/legacy/011_autocommands_spec.lua b/test/functional/legacy/011_autocommands_spec.lua
index 7cc31dc787..c9c004eec1 100644
--- a/test/functional/legacy/011_autocommands_spec.lua
+++ b/test/functional/legacy/011_autocommands_spec.lua
@@ -70,7 +70,7 @@ describe('file reading, writing and bufnew and filter autocommands', function()
feed_command('let $GZIP = ""')
--execute('au FileChangedShell * echo "caught FileChangedShell"')
feed_command('set bin')
- feed_command("au FileReadPost *.gz '[,']!gzip -d")
+ feed_command("au FileReadPost *.gz '[,']!GZIP= gzip -d")
-- Read and decompress the testfile.
feed_command('$r Xtestfile.gz')
expect('\n'..text1)
diff --git a/test/functional/legacy/delete_spec.lua b/test/functional/legacy/delete_spec.lua
index f2ced8942d..3d2c4a7d91 100644
--- a/test/functional/legacy/delete_spec.lua
+++ b/test/functional/legacy/delete_spec.lua
@@ -17,33 +17,6 @@ describe('Test for delete()', function()
eq(-1, eval("delete('Xfile')"))
end)
- it('directory delete', function()
- command("call mkdir('Xdir1')")
- eq(1, eval("isdirectory('Xdir1')"))
- eq(0, eval("delete('Xdir1', 'd')"))
- eq(0, eval("isdirectory('Xdir1')"))
- eq(-1, eval("delete('Xdir1', 'd')"))
- end)
- it('recursive delete', function()
- command("call mkdir('Xdir1')")
- command("call mkdir('Xdir1/subdir')")
- command("call mkdir('Xdir1/empty')")
- command('split Xdir1/Xfile')
- command("call setline(1, ['a', 'b'])")
- command('w')
- command('w Xdir1/subdir/Xfile')
- command('close')
-
- eq(1, eval("isdirectory('Xdir1')"))
- eq(eval("['a', 'b']"), eval("readfile('Xdir1/Xfile')"))
- eq(1, eval("isdirectory('Xdir1/subdir')"))
- eq(eval("['a', 'b']"), eval("readfile('Xdir1/subdir/Xfile')"))
- eq(1, eval("isdirectory('Xdir1/empty')"))
- eq(0, eval("delete('Xdir1', 'rf')"))
- eq(0, eval("isdirectory('Xdir1')"))
- eq(-1, eval("delete('Xdir1', 'd')"))
- end)
-
it('symlink delete', function()
source([[
split Xfile
@@ -63,55 +36,4 @@ describe('Test for delete()', function()
eq(-1, eval("delete('Xlink')"))
eq(0, eval("delete('Xfile')"))
end)
-
- it('symlink directory delete', function()
- command("call mkdir('Xdir1')")
- if helpers.iswin() then
- command("silent !mklink /j Xlink Xdir1")
- else
- command("silent !ln -s Xdir1 Xlink")
- end
- eq(1, eval("isdirectory('Xdir1')"))
- eq(1, eval("isdirectory('Xlink')"))
- -- Delete the link, not the directory
- eq(0, eval("delete('Xlink')"))
- eq(-1, eval("delete('Xlink')"))
- eq(0, eval("delete('Xdir1', 'd')"))
- end)
-
- it('symlink recursive delete', function()
- source([[
- call mkdir('Xdir3')
- call mkdir('Xdir3/subdir')
- call mkdir('Xdir4')
- split Xdir3/Xfile
- call setline(1, ['a', 'b'])
- w
- w Xdir3/subdir/Xfile
- w Xdir4/Xfile
- close
- if has('win32')
- silent !mklink /j Xdir3\Xlink Xdir4
- else
- silent !ln -s ../Xdir4 Xdir3/Xlink
- endif
- ]])
-
- eq(1, eval("isdirectory('Xdir3')"))
- eq(eval("['a', 'b']"), eval("readfile('Xdir3/Xfile')"))
- eq(1, eval("isdirectory('Xdir3/subdir')"))
- eq(eval("['a', 'b']"), eval("readfile('Xdir3/subdir/Xfile')"))
- eq(1, eval("isdirectory('Xdir4')"))
- eq(1, eval("isdirectory('Xdir3/Xlink')"))
- eq(eval("['a', 'b']"), eval("readfile('Xdir4/Xfile')"))
-
- eq(0, eval("delete('Xdir3', 'rf')"))
- eq(0, eval("isdirectory('Xdir3')"))
- eq(-1, eval("delete('Xdir3', 'd')"))
- -- symlink is deleted, not the directory it points to
- eq(1, eval("isdirectory('Xdir4')"))
- eq(eval("['a', 'b']"), eval("readfile('Xdir4/Xfile')"))
- eq(0, eval("delete('Xdir4/Xfile')"))
- eq(0, eval("delete('Xdir4', 'd')"))
- end)
end)
diff --git a/test/functional/legacy/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua
index 609f825177..3c84105c6b 100644
--- a/test/functional/legacy/packadd_spec.lua
+++ b/test/functional/legacy/packadd_spec.lua
@@ -20,6 +20,7 @@ describe('packadd', function()
func SetUp()
let s:topdir = expand(getcwd() . '/Xdir')
+ call delete(s:topdir, 'rf')
exe 'set packpath=' . s:topdir
let s:plugdir = expand(s:topdir . '/pack/mine/opt/mytest')
endfunc