[RFC] vim-patch:8.1.1378: delete() can not handle a file name that looks li… (#16268)

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)
701ff0a3e5

Cherry-pick a change to Test_delete_rf() from patch 8.1.1921.

Co-authored-by: zeertzjq <zeertzjq@outlook.com>
This commit is contained in:
Shougo
2022-04-03 21:27:46 +09:00
committed by GitHub
parent 6786b6afad
commit e9e16655af
5 changed files with 115 additions and 99 deletions

View File

@@ -6702,15 +6702,21 @@ 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)
/// Evaluate "expr" (= "context") for readdir().
static varnumber_T readdir_checkitem(void *context, const char *name)
FUNC_ATTR_NONNULL_ALL
{
typval_T *expr = (typval_T *)context;
typval_T save_val;
typval_T rettv;
typval_T argv[2];
varnumber_T retval = 0;
bool error = false;
if (expr->v_type == VAR_UNKNOWN) {
return 1;
}
prepare_vimvar(VV_VAL, &save_val);
set_vim_var_string(VV_VAL, name, -1);
argv[0].v_type = VAR_STRING;
@@ -6736,54 +6742,16 @@ theend:
/// "readdir()" function
static void f_readdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
typval_T *expr;
const char *path;
garray_T ga;
Directory dir;
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);
}
if (rettv->vval.v_list != NULL && ga.ga_len > 0) {
sort_strings((char_u **)ga.ga_data, ga.ga_len);
const char *path = tv_get_string(&argvars[0]);
typval_T *expr = &argvars[1];
garray_T ga;
int ret = readdir_core(&ga, path, (void *)expr, readdir_checkitem);
if (ret == OK && ga.ga_len > 0) {
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);
const char *p = ((const char **)ga.ga_data)[i];
tv_list_append_string(rettv->vval.v_list, p, -1);
}
}
ga_clear_strings(&ga);