diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval/funcs.c | 41 | ||||
-rw-r--r-- | src/nvim/eval/userfunc.c | 11 | ||||
-rw-r--r-- | src/nvim/fileio.c | 4 | ||||
-rw-r--r-- | src/nvim/log.c | 2 | ||||
-rw-r--r-- | src/nvim/memline.c | 2 | ||||
-rw-r--r-- | src/nvim/os/fs.c | 11 | ||||
-rw-r--r-- | src/nvim/shada.c | 2 | ||||
-rw-r--r-- | src/nvim/undo.c | 2 |
8 files changed, 59 insertions, 16 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 66fd663e5e..f53b283c79 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4892,6 +4892,9 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) *path_tail_with_sep((char *)dir) = NUL; } + bool defer = false; + bool defer_recurse = false; + char *created = NULL; if (argvars[1].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_UNKNOWN) { prot = (int)tv_get_number_chk(&argvars[2], NULL); @@ -4899,9 +4902,17 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } } - if (strcmp(tv_get_string(&argvars[1]), "p") == 0) { + const char *arg2 = tv_get_string(&argvars[1]); + defer = vim_strchr(arg2, 'D') != NULL; + defer_recurse = vim_strchr(arg2, 'R') != NULL; + if ((defer || defer_recurse) && !can_add_defer()) { + return; + } + + if (vim_strchr(arg2, 'p') != NULL) { char *failed_dir; - int ret = os_mkdir_recurse(dir, prot, &failed_dir); + int ret = os_mkdir_recurse(dir, prot, &failed_dir, + defer || defer_recurse ? &created : NULL); if (ret != 0) { semsg(_(e_mkdir), failed_dir, os_strerror(ret)); xfree(failed_dir); @@ -4909,10 +4920,27 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } rettv->vval.v_number = OK; - return; } } - rettv->vval.v_number = vim_mkdir_emsg(dir, prot); + if (rettv->vval.v_number == FAIL) { + rettv->vval.v_number = vim_mkdir_emsg(dir, prot); + } + + // Handle "D" and "R": deferred deletion of the created directory. + if (rettv->vval.v_number == OK + && created == NULL && (defer || defer_recurse)) { + created = FullName_save(dir, false); + } + if (created != NULL) { + typval_T tv[2]; + tv[0].v_type = VAR_STRING; + tv[0].v_lock = VAR_UNLOCKED; + tv[0].vval.v_string = created; + tv[1].v_type = VAR_STRING; + tv[1].v_lock = VAR_UNLOCKED; + tv[1].vval.v_string = xstrdup(defer_recurse ? "rf" : "d"); + add_defer("delete", 2, tv); + } } /// "mode()" function @@ -9332,8 +9360,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - if (defer && get_current_funccal() == NULL) { - semsg(_(e_str_not_inside_function), "defer"); + if (defer && !can_add_defer()) { return; } @@ -9351,7 +9378,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) typval_T tv = { .v_type = VAR_STRING, .v_lock = VAR_UNLOCKED, - .vval.v_string = xstrdup(fname), + .vval.v_string = FullName_save(fname, false), }; add_defer("delete", 1, &tv); } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 0a8e5c349a..808fb316fe 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3153,6 +3153,17 @@ static int ex_defer_inner(char *name, char **arg, const partial_T *const partial return OK; } +/// Return true if currently inside a function call. +/// Give an error message and return FALSE when not. +bool can_add_defer(void) +{ + if (get_current_funccal() == NULL) { + semsg(_(e_str_not_inside_function), "defer"); + return false; + } + return true; +} + /// Add a deferred call for "name" with arguments "argvars[argcount]". /// Consumes "argvars[]". /// Caller must check that current_funccal is not NULL. diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index d4725ccd86..fa2f72932f 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2536,7 +2536,7 @@ static int buf_write_make_backup(char *fname, bool append, FileInfo *file_info_o if (*dirp == NUL && !os_isdir(IObuff)) { int ret; char *failed_dir; - if ((ret = os_mkdir_recurse(IObuff, 0755, &failed_dir)) != 0) { + if ((ret = os_mkdir_recurse(IObuff, 0755, &failed_dir, NULL)) != 0) { semsg(_("E303: Unable to create directory \"%s\" for backup file: %s"), failed_dir, os_strerror(ret)); xfree(failed_dir); @@ -2679,7 +2679,7 @@ nobackup: if (*dirp == NUL && !os_isdir(IObuff)) { int ret; char *failed_dir; - if ((ret = os_mkdir_recurse(IObuff, 0755, &failed_dir)) != 0) { + if ((ret = os_mkdir_recurse(IObuff, 0755, &failed_dir, NULL)) != 0) { semsg(_("E303: Unable to create directory \"%s\" for backup file: %s"), failed_dir, os_strerror(ret)); xfree(failed_dir); diff --git a/src/nvim/log.c b/src/nvim/log.c index 77eeb09fec..4de0c4d88c 100644 --- a/src/nvim/log.c +++ b/src/nvim/log.c @@ -76,7 +76,7 @@ static void log_path_init(void) char *failed_dir = NULL; bool log_dir_failure = false; if (!os_isdir(loghome)) { - log_dir_failure = (os_mkdir_recurse(loghome, 0700, &failed_dir) != 0); + log_dir_failure = (os_mkdir_recurse(loghome, 0700, &failed_dir, NULL) != 0); } XFREE_CLEAR(loghome); // Invalid $NVIM_LOG_FILE or failed to expand; fall back to default. diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 18d5e75a53..0c38f18739 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -3442,7 +3442,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ } else if (!*found_existing_dir && **dirp == NUL) { int ret; char *failed_dir; - if ((ret = os_mkdir_recurse(dir_name, 0755, &failed_dir)) != 0) { + if ((ret = os_mkdir_recurse(dir_name, 0755, &failed_dir, NULL)) != 0) { semsg(_("E303: Unable to create directory \"%s\" for swap file, " "recovery impossible: %s"), failed_dir, os_strerror(ret)); diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index cb51e81005..872d9c9314 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -937,10 +937,13 @@ int os_mkdir(const char *path, int32_t mode) /// the name of the directory which os_mkdir_recurse /// failed to create. I.e. it will contain dir or any /// of the higher level directories. +/// @param[out] created Set to the full name of the first created directory. +/// It will be NULL until that happens. /// /// @return `0` for success, libuv error code for failure. -int os_mkdir_recurse(const char *const dir, int32_t mode, char **const failed_dir) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +int os_mkdir_recurse(const char *const dir, int32_t mode, char **const failed_dir, + char **const created) + FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT { // Get end of directory name in "dir". // We're done when it's "/" or "c:/". @@ -975,6 +978,8 @@ int os_mkdir_recurse(const char *const dir, int32_t mode, char **const failed_di if ((ret = os_mkdir(curdir, mode)) != 0) { *failed_dir = curdir; return ret; + } else if (created != NULL && *created == NULL) { + *created = FullName_save(curdir, false); } } xfree(curdir); @@ -1002,7 +1007,7 @@ int os_file_mkdir(char *fname, int32_t mode) *tail = NUL; int r; char *failed_dir; - if (((r = os_mkdir_recurse(fname, mode, &failed_dir)) < 0)) { + if (((r = os_mkdir_recurse(fname, mode, &failed_dir, NULL)) < 0)) { semsg(_(e_mkdir), failed_dir, os_strerror(r)); xfree(failed_dir); } diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 78499922bf..fcb8a15cde 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -3042,7 +3042,7 @@ shada_write_file_nomerge: {} if (!os_isdir(fname)) { int ret; char *failed_dir; - if ((ret = os_mkdir_recurse(fname, 0700, &failed_dir)) != 0) { + if ((ret = os_mkdir_recurse(fname, 0700, &failed_dir, NULL)) != 0) { semsg(_(SERR "Failed to create directory %s " "for writing ShaDa file: %s"), failed_dir, os_strerror(ret)); diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 132c84231f..7eb0d390fc 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -705,7 +705,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) // Last directory in the list does not exist, create it. int ret; char *failed_dir; - if ((ret = os_mkdir_recurse(dir_name, 0755, &failed_dir)) != 0) { + if ((ret = os_mkdir_recurse(dir_name, 0755, &failed_dir, NULL)) != 0) { semsg(_("E5003: Unable to create directory \"%s\" for undo file: %s"), failed_dir, os_strerror(ret)); xfree(failed_dir); |