summaryrefslogtreecommitdiffstats
path: root/src/filepath.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-09-04 15:40:36 +0100
committerBram Moolenaar <Bram@vim.org>2022-09-04 15:40:36 +0100
commit806a273f3c84ecd475913d901890bb1929be9a0a (patch)
tree7970b531379736fd2497f3a1acea0c400028db81 /src/filepath.c
parentc1eb131c9eb38e00e08109f50e3e5337c072b71e (diff)
patch 9.0.0379: cleaning up after writefile() is a hasslev9.0.0379
Problem: Cleaning up after writefile() is a hassle. Solution: Add the 'D' flag to defer deleting the written file. Very useful in tests.
Diffstat (limited to 'src/filepath.c')
-rw-r--r--src/filepath.c65
1 files changed, 45 insertions, 20 deletions
diff --git a/src/filepath.c b/src/filepath.c
index b824529fbc..c72e4285f3 100644
--- a/src/filepath.c
+++ b/src/filepath.c
@@ -2232,6 +2232,7 @@ f_writefile(typval_T *argvars, typval_T *rettv)
{
int binary = FALSE;
int append = FALSE;
+ int defer = FALSE;
#ifdef HAVE_FSYNC
int do_fsync = p_fs;
#endif
@@ -2285,6 +2286,8 @@ f_writefile(typval_T *argvars, typval_T *rettv)
binary = TRUE;
if (vim_strchr(arg2, 'a') != NULL)
append = TRUE;
+ if (vim_strchr(arg2, 'D') != NULL)
+ defer = TRUE;
#ifdef HAVE_FSYNC
if (vim_strchr(arg2, 's') != NULL)
do_fsync = TRUE;
@@ -2297,37 +2300,59 @@ f_writefile(typval_T *argvars, typval_T *rettv)
if (fname == NULL)
return;
+ if (defer && !in_def_function() && get_current_funccal() == NULL)
+ {
+ semsg(_(e_str_not_inside_function), "defer");
+ return;
+ }
+
// Always open the file in binary mode, library functions have a mind of
// their own about CR-LF conversion.
if (*fname == NUL || (fd = mch_fopen((char *)fname,
append ? APPENDBIN : WRITEBIN)) == NULL)
{
- semsg(_(e_cant_create_file_str), *fname == NUL ? (char_u *)_("<empty>") : fname);
+ semsg(_(e_cant_create_file_str),
+ *fname == NUL ? (char_u *)_("<empty>") : fname);
ret = -1;
}
- else if (blob)
- {
- if (write_blob(fd, blob) == FAIL)
- ret = -1;
-#ifdef HAVE_FSYNC
- else if (do_fsync)
- // Ignore the error, the user wouldn't know what to do about it.
- // May happen for a device.
- vim_ignored = vim_fsync(fileno(fd));
-#endif
- fclose(fd);
- }
else
{
- if (write_list(fd, list, binary) == FAIL)
- ret = -1;
+ if (defer)
+ {
+ typval_T tv;
+
+ tv.v_type = VAR_STRING;
+ tv.v_lock = 0;
+ tv.vval.v_string = vim_strsave(fname);
+ if (tv.vval.v_string == NULL
+ || add_defer((char_u *)"delete", 1, &tv) == FAIL)
+ {
+ ret = -1;
+ fclose(fd);
+ (void)mch_remove(fname);
+ }
+ }
+
+ if (ret == 0)
+ {
+ if (blob)
+ {
+ if (write_blob(fd, blob) == FAIL)
+ ret = -1;
+ }
+ else
+ {
+ if (write_list(fd, list, binary) == FAIL)
+ ret = -1;
+ }
#ifdef HAVE_FSYNC
- else if (do_fsync)
- // Ignore the error, the user wouldn't know what to do about it.
- // May happen for a device.
- vim_ignored = vim_fsync(fileno(fd));
+ if (ret == 0 && do_fsync)
+ // Ignore the error, the user wouldn't know what to do about
+ // it. May happen for a device.
+ vim_ignored = vim_fsync(fileno(fd));
#endif
- fclose(fd);
+ fclose(fd);
+ }
}
rettv->vval.v_number = ret;