# HG changeset patch # User Christian Brabandt # Date 1523707206 -7200 # Node ID 4a1efd1a601846f322369d7ddeafd16afdf2657d # Parent c565c188dbaced541345e23e4fb4f2a9f3613b1e patch 8.0.1708: mkdir with 'p' flag fails on existing directory commit https://github.com/vim/vim/commit/78a16b0f2a142aae1fdc96c50ab0f25194d0e755 Author: Bram Moolenaar 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) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- 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 --- 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 diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim --- 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 --- 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,