diff options
-rw-r--r-- | runtime/doc/options.txt | 20 | ||||
-rw-r--r-- | runtime/doc/vim_diff.txt | 4 | ||||
-rw-r--r-- | src/nvim/fileio.c | 38 | ||||
-rw-r--r-- | src/nvim/memline.c | 2 | ||||
-rw-r--r-- | src/nvim/option.c | 8 | ||||
-rw-r--r-- | src/nvim/undo.c | 10 | ||||
-rw-r--r-- | test/functional/options/defaults_spec.lua | 24 |
7 files changed, 72 insertions, 34 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 364d4c5167..475ccb66b3 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -824,12 +824,12 @@ A jump table for the options with a short description can be found at |Q_op|. again not rename the file. *'backupdir'* *'bdir'* -'backupdir' 'bdir' string (default ".,$XDG_DATA_HOME/nvim/backup") +'backupdir' 'bdir' string (default ".,$XDG_DATA_HOME/nvim/backup//") global List of directories for the backup file, separated with commas. - The backup file will be created in the first directory in the list - where this is possible. The directory must exist, Vim will not - create it for you. + where this is possible. If none of the directories exist Nvim will + attempt to create the last directory in the list. - Empty means that no backup file will be created ('patchmode' is impossible!). Writing may fail because of this. - A directory "." means to put the backup file in the same directory @@ -6533,17 +6533,17 @@ A jump table for the options with a short description can be found at |Q_op|. 'ttyfast' 'tf' Removed. |vim-differences| *'undodir'* *'udir'* *E5003* -'undodir' 'udir' string (default "$XDG_DATA_HOME/nvim/undo") +'undodir' 'udir' string (default "$XDG_DATA_HOME/nvim/undo//") global List of directory names for undo files, separated with commas. - See |'backupdir'| for details of the format. + See 'backupdir' for details of the format. "." means using the directory of the file. The undo file name for "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. If none of - the directories exist Neovim will attempt to create last directory in + works, no directories after "." will be used for writing. If none of + the directories exist Nvim will attempt to create the 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 @@ -6552,6 +6552,10 @@ A jump table for the options with a short description can be found at |Q_op|. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. + Note that unlike 'directory' and 'backupdir', 'undodir' always acts as + though the trailing slashes are present (see 'backupdir' for what this + means). + *'undofile'* *'noundofile'* *'udf'* *'noudf'* 'undofile' 'udf' boolean (default off) local to buffer @@ -6692,7 +6696,7 @@ A jump table for the options with a short description can be found at |Q_op|. displayed when 'verbosefile' is set. *'viewdir'* *'vdir'* -'viewdir' 'vdir' string (default: "$XDG_DATA_HOME/nvim/view") +'viewdir' 'vdir' string (default: "$XDG_DATA_HOME/nvim/view//") global Name of the directory where to store files for |:mkview|. This option cannot be set from a |modeline| or in the |sandbox|, for diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 166c0c17aa..918b35439d 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -30,7 +30,7 @@ the differences. - 'autoread' is enabled - 'background' defaults to "dark" (unless set automatically by the terminal/UI) - 'backspace' defaults to "indent,eol,start" -- 'backupdir' defaults to .,~/.local/share/nvim/backup (|xdg|) +- 'backupdir' defaults to .,~/.local/share/nvim/backup// (|xdg|), auto-created - 'belloff' defaults to "all" - 'compatible' is always disabled - 'complete' excludes "i" @@ -63,7 +63,7 @@ the differences. - 'tags' defaults to "./tags;,tags" - 'ttimeoutlen' defaults to 50 - 'ttyfast' is always set -- 'undodir' defaults to ~/.local/share/nvim/undo (|xdg|), auto-created +- 'undodir' defaults to ~/.local/share/nvim/undo// (|xdg|), auto-created - 'viewoptions' includes "unix,slash", excludes "options" - 'viminfo' includes "!" - 'wildmenu' is enabled diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 3d058e1d09..92b48c36cb 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2688,9 +2688,22 @@ buf_write( /* * Isolate one directory name, using an entry in 'bdir'. */ - (void)copy_option_part(&dirp, IObuff, IOSIZE, ","); - p = IObuff + STRLEN(IObuff); - if (after_pathsep((char *)IObuff, (char *)p) && p[-1] == p[-2]) { + size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ","); + p = IObuff + dir_len; + bool trailing_pathseps = after_pathsep((char *)IObuff, (char *)p) && p[-1] == p[-2]; + if (trailing_pathseps) { + IObuff[dir_len - 2] = NUL; + } + if (*dirp == NUL && !os_isdir(IObuff)) { + int ret; + char *failed_dir; + if ((ret = os_mkdir_recurse((char *)IObuff, 0755, &failed_dir)) != 0) { + EMSG3(_("E303: Unable to create directory \"%s\" for backup file: %s"), + failed_dir, os_strerror(ret)); + xfree(failed_dir); + } + } + if (trailing_pathseps) { // Ends with '//', Use Full path if ((p = (char_u *)make_percent_swname((char *)IObuff, (char *)fname)) != NULL) { @@ -2840,9 +2853,22 @@ nobackup: /* * Isolate one directory name and make the backup file name. */ - (void)copy_option_part(&dirp, IObuff, IOSIZE, ","); - p = IObuff + STRLEN(IObuff); - if (after_pathsep((char *)IObuff, (char *)p) && p[-1] == p[-2]) { + size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ","); + p = IObuff + dir_len; + bool trailing_pathseps = after_pathsep((char *)IObuff, (char *)p) && p[-1] == p[-2]; + if (trailing_pathseps) { + IObuff[dir_len - 2] = NUL; + } + if (*dirp == NUL && !os_isdir(IObuff)) { + int ret; + char *failed_dir; + if ((ret = os_mkdir_recurse((char *)IObuff, 0755, &failed_dir)) != 0) { + EMSG3(_("E303: Unable to create directory \"%s\" for backup file: %s"), + failed_dir, os_strerror(ret)); + xfree(failed_dir); + } + } + if (trailing_pathseps) { // path ends with '//', use full path if ((p = (char_u *)make_percent_swname((char *)IObuff, (char *)fname)) != NULL) { diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 4d435bc99f..230361b997 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -1442,7 +1442,7 @@ recover_names ( * Append the full path to name with path separators made into percent * signs, to dir. An unnamed buffer is handled as "" (<currentdir>/"") */ -char *make_percent_swname(const char *dir, char *name) +char *make_percent_swname(const char *dir, const char *name) FUNC_ATTR_NONNULL_ARG(1) { char *d = NULL; diff --git a/src/nvim/option.c b/src/nvim/option.c index f7635fe5ec..d11bbc8ecc 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -483,17 +483,17 @@ void set_init_1(bool clean_arg) #endif false); - char *backupdir = stdpaths_user_data_subpath("backup", 0, true); + char *backupdir = stdpaths_user_data_subpath("backup", 2, true); const size_t backupdir_len = strlen(backupdir); backupdir = xrealloc(backupdir, backupdir_len + 3); memmove(backupdir + 2, backupdir, backupdir_len + 1); memmove(backupdir, ".,", 2); - set_string_default("viewdir", stdpaths_user_data_subpath("view", 0, true), - true); set_string_default("backupdir", backupdir, true); + set_string_default("viewdir", stdpaths_user_data_subpath("view", 2, true), + true); set_string_default("directory", stdpaths_user_data_subpath("swap", 2, true), true); - set_string_default("undodir", stdpaths_user_data_subpath("undo", 0, true), + set_string_default("undodir", stdpaths_user_data_subpath("undo", 2, true), true); // Set default for &runtimepath. All necessary expansions are performed in // this function. diff --git a/src/nvim/undo.c b/src/nvim/undo.c index e1a7dbb2d3..fb96d7e6ff 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -672,6 +672,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) #ifdef HAVE_READLINK char fname_buf[MAXPATHL]; #endif + char *p; if (ffname == NULL) { return NULL; @@ -704,6 +705,13 @@ 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; + + // Remove trailing pathseps from directory name + p = &dir_name[dir_len - 1]; + while (vim_ispathsep(*p)) { + *p-- = NUL; + } + 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. @@ -720,7 +728,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) if (has_directory) { if (munged_name == NULL) { munged_name = xstrdup(ffname); - for (char *p = munged_name; *p != NUL; MB_PTR_ADV(p)) { + for (p = munged_name; *p != NUL; MB_PTR_ADV(p)) { if (vim_ispathsep(*p)) { *p = '%'; } diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua index eb5e284385..bd3553ec59 100644 --- a/test/functional/options/defaults_spec.lua +++ b/test/functional/options/defaults_spec.lua @@ -354,13 +354,13 @@ describe('XDG-based defaults', function() .. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim/after' .. ',' .. root_path .. ('/x'):rep(4096) .. '/nvim/after' ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/')) - eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. data_dir .. '/backup', + eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. data_dir .. '/backup//', (meths.get_option('backupdir'):gsub('\\', '/'))) eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/swap//', (meths.get_option('directory')):gsub('\\', '/')) - eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/undo', + eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/undo//', (meths.get_option('undodir')):gsub('\\', '/')) - eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/view', + eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/view//', (meths.get_option('viewdir')):gsub('\\', '/')) end) end) @@ -404,13 +404,13 @@ describe('XDG-based defaults', function() .. ',$XDG_DATA_DIRS/nvim/after' .. ',$XDG_DATA_HOME/nvim/after' ):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/')) - eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup'), + eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup//'), meths.get_option('backupdir'):gsub('\\', '/')) eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'), meths.get_option('directory'):gsub('\\', '/')) - eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo'), + eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo//'), meths.get_option('undodir'):gsub('\\', '/')) - eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view'), + eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view//'), meths.get_option('viewdir'):gsub('\\', '/')) meths.command('set all&') eq(('$XDG_DATA_HOME/nvim' @@ -424,13 +424,13 @@ describe('XDG-based defaults', function() .. ',$XDG_DATA_DIRS/nvim/after' .. ',$XDG_DATA_HOME/nvim/after' ):gsub('\\', '/'), (meths.get_option('runtimepath')):gsub('\\', '/')) - eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup'), + eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup//'), meths.get_option('backupdir'):gsub('\\', '/')) eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'), meths.get_option('directory'):gsub('\\', '/')) - eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo'), + eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo//'), meths.get_option('undodir'):gsub('\\', '/')) - eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view'), + eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view//'), meths.get_option('viewdir'):gsub('\\', '/')) end) end) @@ -483,13 +483,13 @@ describe('XDG-based defaults', function() .. ',\\,-\\,-\\,' .. path_sep ..'nvim' .. path_sep ..'after' .. ',\\, \\, \\,' .. path_sep ..'nvim' .. path_sep ..'after' ), meths.get_option('runtimepath')) - eq('.,\\,=\\,=\\,' .. path_sep .. data_dir .. '' .. path_sep ..'backup', + eq('.,\\,=\\,=\\,' .. path_sep .. data_dir .. '' .. path_sep ..'backup' .. (path_sep):rep(2), meths.get_option('backupdir')) eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'swap' .. (path_sep):rep(2), meths.get_option('directory')) - eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'undo', + eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'undo' .. (path_sep):rep(2), meths.get_option('undodir')) - eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'view', + eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'view' .. (path_sep):rep(2), meths.get_option('viewdir')) end) end) |