diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 7829add2e5..73a433fd42 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -6695,7 +6695,7 @@ A jump table for the options with a short description can be found at |Q_op|. global Alias for 'term', see above. - *'undodir'* *'udir'* + *'undodir'* *'udir'* *E926* 'undodir' 'udir' string (default ".") global {only when compiled with the |+persistent_undo| feature} @@ -6705,8 +6705,10 @@ A jump table for the options with a short description can be found at |Q_op|. "file.txt" is ".file.txt.un~". For other directories the file name is the full path of the edited file, with path separators replaced with "%". - When writing: The first directory that exists is used. "." always - works, no directories after "." will be used for writing. + When writing: The first directory that exists is used. "." always + works, no directories after "." will be used for writing. If none of + the directories exist Neovim will attempt to create last directory in + the list. When reading all entries are tried to find an undo file. The first undo file that exists is used. When it cannot be read an error is given, no further entry is used. diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 90f02645da..d8158bf7cd 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -644,7 +644,9 @@ void u_compute_hash(char_u *hash) /// be found. /// @param[in] reading If true, find the file to read by traversing all of the /// directories in &undodir. If false use the first -/// existing directory. +/// existing directory. If none of the directories in +/// &undodir option exist then last directory in the list +/// will be automatically created. /// /// @return [allocated] File name to read from/write to or NULL. char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) @@ -690,7 +692,20 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) memmove(tail + tail_len + 1, ".un~", sizeof(".un~")); } else { dir_name[dir_len] = NUL; - if (os_isdir((char_u *)dir_name)) { + bool has_directory = os_isdir((char_u *)dir_name); + if (!has_directory && *dirp == NUL && !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) { + EMSG3(_("E926: Unable to create directory \"%s\" for undo file: %s"), + failed_dir, os_strerror(ret)); + xfree(failed_dir); + } else { + has_directory = true; + } + } + if (has_directory) { if (munged_name == NULL) { munged_name = xstrdup(ffname); for (char *p = munged_name; *p != NUL; mb_ptr_adv(p)) {