summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2018-04-14 13:51:55 +0200
committerBram Moolenaar <Bram@vim.org>2018-04-14 13:51:55 +0200
commit78a16b0f2a142aae1fdc96c50ab0f25194d0e755 (patch)
tree2980fc918579aba91215787b3ce7f535708d4ad4
parent98da6ecab905df48a67da36ce60233f45726c979 (diff)
patch 8.0.1708: mkdir with 'p' flag fails on existing directoryv8.0.1708
Problem: Mkdir with 'p' flag fails on existing directory, which is different from the mkdir shell command. Solution: Don't fail if the directory already exists. (James McCoy, closes #2775)
-rw-r--r--runtime/doc/eval.txt2
-rw-r--r--src/evalfunc.c34
-rw-r--r--src/testdir/test_eval_stuff.vim17
-rw-r--r--src/version.c2
4 files changed, 43 insertions, 12 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index b0170b847b..1868f4ee73 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -6138,6 +6138,8 @@ mkdir({name} [, {path} [, {prot}]])
Example: >
:call mkdir($HOME . "/tmp/foo/bar", "p", 0700)
< This function is not available in the |sandbox|.
+ There is no error if the directory already exists and the "p"
+ flag is passed (since patch 8.0.1708).
Not available on all systems. To check use: >
:if exists("*mkdir")
<
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 65279a52f8..4b09951852 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -8057,22 +8057,32 @@ f_mkdir(typval_T *argvars, typval_T *rettv)
dir = get_tv_string_buf(&argvars[0], buf);
if (*dir == NUL)
- rettv->vval.v_number = FAIL;
- else
- {
- if (*gettail(dir) == NUL)
- /* remove trailing slashes */
- *gettail_sep(dir) = NUL;
+ return;
- if (argvars[1].v_type != VAR_UNKNOWN)
+ if (*gettail(dir) == NUL)
+ /* remove trailing slashes */
+ *gettail_sep(dir) = NUL;
+
+ if (argvars[1].v_type != VAR_UNKNOWN)
+ {
+ if (argvars[2].v_type != VAR_UNKNOWN)
{
- if (argvars[2].v_type != VAR_UNKNOWN)
- prot = (int)get_tv_number_chk(&argvars[2], NULL);
- if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0)
- mkdir_recurse(dir, prot);
+ prot = (int)get_tv_number_chk(&argvars[2], NULL);
+ if (prot == -1)
+ return;
+ }
+ if (STRCMP(get_tv_string(&argvars[1]), "p") == 0)
+ {
+ if (mch_isdir(dir))
+ {
+ /* With the "p" flag it's OK if the dir already exists. */
+ rettv->vval.v_number = OK;
+ return;
+ }
+ mkdir_recurse(dir, prot);
}
- rettv->vval.v_number = prot == -1 ? FAIL : vim_mkdir_emsg(dir, prot);
}
+ rettv->vval.v_number = vim_mkdir_emsg(dir, prot);
}
#endif
diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim
index 12222303d3..41ba1374d8 100644
--- a/src/testdir/test_eval_stuff.vim
+++ b/src/testdir/test_eval_stuff.vim
@@ -25,3 +25,20 @@ func Test_nocatch_restore_silent_emsg()
let c5 = nr2char(screenchar(&lines, 5))
call assert_equal('wrong', c1 . c2 . c3 . c4 . c5)
endfunc
+
+func Test_mkdir_p()
+ call mkdir('Xmkdir/nested', 'p')
+ call assert_true(isdirectory('Xmkdir/nested'))
+ try
+ " Trying to make existing directories doesn't error
+ call mkdir('Xmkdir', 'p')
+ call mkdir('Xmkdir/nested', 'p')
+ catch /E739:/
+ call assert_report('mkdir(..., "p") failed for an existing directory')
+ endtry
+ " 'p' doesn't suppress real errors
+ call writefile([], 'Xfile')
+ call assert_fails('call mkdir("Xfile", "p")', 'E739')
+ call delete('Xfile')
+ call delete('Xmkdir', 'rf')
+endfunc
diff --git a/src/version.c b/src/version.c
index 5facbc5811..6bebac2913 100644
--- a/src/version.c
+++ b/src/version.c
@@ -763,6 +763,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1708,
+/**/
1707,
/**/
1706,