mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 7.4.1114
Problem: delete() does not work well with symbolic links. Solution: Recognize symbolik links.
This commit is contained in:
parent
4119cf80e1
commit
43a34f9f74
@ -2755,13 +2755,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.
|
||||
|
||||
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!
|
||||
A symbolic link itself is deleted, not what it points to.
|
||||
|
||||
The result is a Number, which is 0 if the delete operation was
|
||||
successful and -1 when the deletion failed or partly failed.
|
||||
|
@ -10418,7 +10418,7 @@ f_delete(argvars, rettv)
|
||||
/* delete an empty directory */
|
||||
rettv->vval.v_number = mch_rmdir(name) == 0 ? 0 : -1;
|
||||
else if (STRCMP(flags, "rf") == 0)
|
||||
/* delete an directory recursively */
|
||||
/* delete a directory recursively */
|
||||
rettv->vval.v_number = delete_recursive(name);
|
||||
else
|
||||
EMSG2(_(e_invexpr2), flags);
|
||||
|
14
src/fileio.c
14
src/fileio.c
@ -7294,7 +7294,19 @@ delete_recursive(char_u *name)
|
||||
int i;
|
||||
char_u *exp;
|
||||
|
||||
if (mch_isdir(name))
|
||||
/* A symbolic link to a directory itself is deleted, not the directory it
|
||||
* points to. */
|
||||
if (
|
||||
# if defined(WIN32)
|
||||
mch_isdir(name) && !mch_is_symbolic_link(name)
|
||||
# else
|
||||
# ifdef UNIX
|
||||
mch_isrealdir(name)
|
||||
# else
|
||||
mch_isdir(name)
|
||||
# endif
|
||||
# endif
|
||||
)
|
||||
{
|
||||
vim_snprintf((char *)NameBuff, MAXPATHL, "%s/*", name);
|
||||
exp = vim_strsave(NameBuff);
|
||||
|
@ -2994,7 +2994,7 @@ mch_hide(name)
|
||||
}
|
||||
|
||||
/*
|
||||
* return TRUE if "name" is a directory
|
||||
* return TRUE if "name" is a directory or a symlink to a directory
|
||||
* return FALSE if "name" is not a directory
|
||||
* return FALSE for error
|
||||
*/
|
||||
@ -3015,6 +3015,28 @@ mch_isdir(name)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* return TRUE if "name" is a directory, NOT a symlink to a directory
|
||||
* return FALSE if "name" is not a directory
|
||||
* return FALSE for error
|
||||
*/
|
||||
int
|
||||
mch_isrealdir(name)
|
||||
char_u *name;
|
||||
{
|
||||
struct stat statb;
|
||||
|
||||
if (*name == NUL) /* Some stat()s don't flag "" as an error. */
|
||||
return FALSE;
|
||||
if (lstat((char *)name, &statb))
|
||||
return FALSE;
|
||||
#ifdef _POSIX_SOURCE
|
||||
return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
|
||||
#else
|
||||
return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int executable_file __ARGS((char_u *name));
|
||||
|
||||
/*
|
||||
|
@ -41,6 +41,7 @@ void mch_set_acl __ARGS((char_u *fname, vim_acl_T aclent));
|
||||
void mch_free_acl __ARGS((vim_acl_T aclent));
|
||||
void mch_hide __ARGS((char_u *name));
|
||||
int mch_isdir __ARGS((char_u *name));
|
||||
int mch_isrealdir __ARGS((char_u *name));
|
||||
int mch_can_exe __ARGS((char_u *name, char_u **path, int use_path));
|
||||
int mch_nodetype __ARGS((char_u *name));
|
||||
void mch_early_init __ARGS((void));
|
||||
|
@ -34,3 +34,64 @@ func Test_recursive_delete()
|
||||
call assert_false(isdirectory('Xdir1'))
|
||||
call assert_equal(-1, delete('Xdir1', 'd'))
|
||||
endfunc
|
||||
|
||||
func Test_symlink_delete()
|
||||
if !has('unix')
|
||||
return
|
||||
endif
|
||||
split Xfile
|
||||
call setline(1, ['a', 'b'])
|
||||
wq
|
||||
silent !ln -s Xfile Xlink
|
||||
" Delete the link, not the file
|
||||
call assert_equal(0, delete('Xlink'))
|
||||
call assert_equal(-1, delete('Xlink'))
|
||||
call assert_equal(0, delete('Xfile'))
|
||||
endfunc
|
||||
|
||||
func Test_symlink_dir_delete()
|
||||
if !has('unix')
|
||||
return
|
||||
endif
|
||||
call mkdir('Xdir1')
|
||||
silent !ln -s Xdir1 Xlink
|
||||
call assert_true(isdirectory('Xdir1'))
|
||||
call assert_true(isdirectory('Xlink'))
|
||||
" Delete the link, not the directory
|
||||
call assert_equal(0, delete('Xlink'))
|
||||
call assert_equal(-1, delete('Xlink'))
|
||||
call assert_equal(0, delete('Xdir1', 'd'))
|
||||
endfunc
|
||||
|
||||
func Test_symlink_recursive_delete()
|
||||
if !has('unix')
|
||||
return
|
||||
endif
|
||||
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
|
||||
|
||||
call assert_true(isdirectory('Xdir3'))
|
||||
call assert_equal(['a', 'b'], readfile('Xdir3/Xfile'))
|
||||
call assert_true(isdirectory('Xdir3/subdir'))
|
||||
call assert_equal(['a', 'b'], readfile('Xdir3/subdir/Xfile'))
|
||||
call assert_true(isdirectory('Xdir4'))
|
||||
call assert_true(isdirectory('Xdir3/Xlink'))
|
||||
call assert_equal(['a', 'b'], readfile('Xdir4/Xfile'))
|
||||
|
||||
call assert_equal(0, delete('Xdir3', 'rf'))
|
||||
call assert_false(isdirectory('Xdir3'))
|
||||
call assert_equal(-1, delete('Xdir3', 'd'))
|
||||
" symlink is deleted, not the directory it points to
|
||||
call assert_true(isdirectory('Xdir4'))
|
||||
call assert_equal(['a', 'b'], readfile('Xdir4/Xfile'))
|
||||
call assert_equal(0, delete('Xdir4/Xfile'))
|
||||
call assert_equal(0, delete('Xdir4', 'd'))
|
||||
endfunc
|
||||
|
@ -741,6 +741,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1114,
|
||||
/**/
|
||||
1113,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user