aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJurica Bradaric <jbradaric@gmail.com>2016-02-28 12:44:59 +0100
committerJurica Bradaric <jbradaric@gmail.com>2016-04-20 08:25:51 +0200
commit88a735166b7ee1eadaf6d46be11804dc0e1a251a (patch)
tree2b39c525bb9120f6cc192106f0f93d7b4ca9016a
parent50a7517a6deb7d8eaa02bf718e273b7058066d89 (diff)
downloadrneovim-88a735166b7ee1eadaf6d46be11804dc0e1a251a.tar.gz
rneovim-88a735166b7ee1eadaf6d46be11804dc0e1a251a.tar.bz2
rneovim-88a735166b7ee1eadaf6d46be11804dc0e1a251a.zip
vim-patch:7.4.1114
Problem: delete() does not work well with symbolic links. Solution: Recognize symbolik links. https://github.com/vim/vim/commit/43a34f9f74fdce462fa250baab620264c28b6165
-rw-r--r--runtime/doc/eval.txt7
-rw-r--r--src/nvim/os/fs.c17
-rw-r--r--src/nvim/tempfile.c2
-rw-r--r--src/nvim/version.c2
-rw-r--r--test/functional/legacy/delete_spec.lua57
5 files changed, 80 insertions, 5 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 9437491623..fea9423df2 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2772,13 +2772,14 @@ deepcopy({expr}[, {noref}]) *deepcopy()* *E698*
delete({fname} [, {flags}]) *delete()*
Without {flags} or with {flags} empty: Deletes the file by the
- name {fname}.
+ name {fname}. This also works when {fname} is a symbolic link.
+ A symbolic link itself is deleted, not what it points to.
When {flags} is "d": Deletes the directory by the name
- {fname}. This fails when {fname} is not empty.
+ {fname}. This fails when directory {fname} is not empty.
When {flags} is "rf": Deletes the directory by the name
- {fname} and everything in it, recursively. Be careful!
+ {fname} and everything in it, recursively. BE CAREFUL!
The result is a Number, which is 0 if the delete operation was
successful and -1 when the deletion failed or partly failed.
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 34d8fde4f1..bc2d37764d 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -59,6 +59,23 @@ int os_dirname(char_u *buf, size_t len)
return OK;
}
+/// Check if the given path is a directory and not a symlink to a directory.
+/// @return `true` if `name` is a directory and NOT a symlink to a directory.
+/// `false` if `name` is not a directory or if an error occurred.
+bool os_isrealdir(const char_u *name)
+ FUNC_ATTR_NONNULL_ALL
+{
+ uv_fs_t request;
+ if (uv_fs_lstat(&fs_loop, &request, (char *)name, NULL) != kLibuvSuccess) {
+ return false;
+ }
+ if (S_ISLNK(request.statbuf.st_mode)) {
+ return false;
+ } else {
+ return S_ISDIR(request.statbuf.st_mode);
+ }
+}
+
/// Check if the given path is a directory or not.
///
/// @return `true` if `fname` is a directory.
diff --git a/src/nvim/tempfile.c b/src/nvim/tempfile.c
index 882dbe32f2..5b6268168d 100644
--- a/src/nvim/tempfile.c
+++ b/src/nvim/tempfile.c
@@ -63,7 +63,7 @@ int delete_recursive(char_u *name)
{
int result = 0;
- if (os_isdir(name)) {
+ if (os_isrealdir(name)) {
snprintf((char *)NameBuff, MAXPATHL, "%s/*", name);
char_u **files;
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 2828442611..235d74de76 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -250,7 +250,7 @@ static int included_patches[] = {
// 1117,
// 1116,
// 1115 NA
- // 1114,
+ 1114,
1113,
1112,
// 1111,
diff --git a/test/functional/legacy/delete_spec.lua b/test/functional/legacy/delete_spec.lua
index 01b06d606f..b524af3338 100644
--- a/test/functional/legacy/delete_spec.lua
+++ b/test/functional/legacy/delete_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local source = helpers.source
local eq, eval, execute, expect = helpers.eq, helpers.eval, helpers.execute, helpers.expect
describe('Test for delete()', function()
@@ -38,4 +39,60 @@ describe('Test for delete()', function()
eq(0, eval("isdirectory('Xdir1')"))
eq(-1, eval("delete('Xdir1', 'd')"))
end)
+
+ it('symlink delete', function()
+ source([[
+ split Xfile
+ call setline(1, ['a', 'b'])
+ wq
+ silent !ln -s Xfile Xlink
+ ]])
+ -- Delete the link, not the file
+ eq(0, eval("delete('Xlink')"))
+ eq(-1, eval("delete('Xlink')"))
+ eq(0, eval("delete('Xfile')"))
+ end)
+
+ it('symlink directory delete', function()
+ execute("call mkdir('Xdir1')")
+ execute("silent !ln -s Xdir1 Xlink")
+ 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
+ silent !ln -s ../Xdir4 Xdir3/Xlink
+ ]])
+
+ 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)