diff options
-rw-r--r-- | src/nvim/eval/funcs.c | 62 | ||||
-rw-r--r-- | src/nvim/fileio.c | 109 | ||||
-rw-r--r-- | src/nvim/testdir/test_arglist.vim | 18 | ||||
-rw-r--r-- | src/nvim/testdir/test_command_count.vim | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_functions.vim | 19 | ||||
-rw-r--r-- | src/nvim/testdir/test_quickfix.vim | 10 | ||||
-rw-r--r-- | src/nvim/testdir/test_registers.vim | 3 | ||||
-rw-r--r-- | test/functional/legacy/011_autocommands_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/legacy/delete_spec.lua | 78 | ||||
-rw-r--r-- | test/functional/legacy/packadd_spec.lua | 1 |
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 |