changeset 13672:4a1efd1a6018 v8.0.1708

patch 8.0.1708: mkdir with 'p' flag fails on existing directory commit https://github.com/vim/vim/commit/78a16b0f2a142aae1fdc96c50ab0f25194d0e755 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Apr 14 13:51:55 2018 +0200 patch 8.0.1708: mkdir with 'p' flag fails on existing directory 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)
author Christian Brabandt <cb@256bit.org>
date Sat, 14 Apr 2018 14:00:06 +0200
parents c565c188dbac
children 24336952ffcf
files runtime/doc/eval.txt src/evalfunc.c src/testdir/test_eval_stuff.vim src/version.c
diffstat 4 files changed, 47 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- 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")
 <
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -8057,22 +8057,32 @@ f_mkdir(typval_T *argvars, typval_T *ret
 
     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;
-
-	if (argvars[1].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);
-	}
-	rettv->vval.v_number = prot == -1 ? FAIL : vim_mkdir_emsg(dir, prot);
-    }
+	return;
+
+    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)
+	{
+	    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 = vim_mkdir_emsg(dir, prot);
 }
 #endif
 
--- 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
--- 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,