Skip to content

Commit

Permalink
feat: defaults: auto-create backup dir
Browse files Browse the repository at this point in the history
Copy the behavior of 'undodir' and create the last specified directory
in the 'backupdir' option if it doesn't exist.

Use trailing slashes for 'backupdir' as well as 'viewdir' and 'undodir'
by default. Note that 'undodir' always behaves as though it has the
trailing slashes, regardless of whether or not they are present. They
are added to the default option value to minimize surprise.

The '.' value in 'backupdir' is kept because the default behavior for
backups is solely to have a backup if the save of the main file to disk
fails. As soon as that save is completed the backup file is removed, so
generally there is no need to put them in a central location.

Co-authored by: murphy66 <murphy66@gmail.com>
  • Loading branch information
gpanders committed Aug 27, 2021
1 parent 3202478 commit 4600193
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 21 deletions.
6 changes: 3 additions & 3 deletions runtime/doc/options.txt
Expand Up @@ -824,7 +824,7 @@ 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
Expand Down Expand Up @@ -6533,7 +6533,7 @@ 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.
Expand Down Expand Up @@ -6692,7 +6692,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
Expand Down
4 changes: 2 additions & 2 deletions runtime/doc/vim_diff.txt
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions src/nvim/fileio.c
Expand Up @@ -2689,6 +2689,15 @@ buf_write(
* Isolate one directory name, using an entry in 'bdir'.
*/
(void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
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);
}
}
p = IObuff + STRLEN(IObuff);
if (after_pathsep((char *)IObuff, (char *)p) && p[-1] == p[-2]) {
// Ends with '//', Use Full path
Expand Down Expand Up @@ -2841,6 +2850,15 @@ buf_write(
* Isolate one directory name and make the backup file name.
*/
(void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
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);
}
}
p = IObuff + STRLEN(IObuff);
if (after_pathsep((char *)IObuff, (char *)p) && p[-1] == p[-2]) {
// path ends with '//', use full path
Expand Down
8 changes: 4 additions & 4 deletions src/nvim/option.c
Expand Up @@ -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.
Expand Down
24 changes: 12 additions & 12 deletions test/functional/options/defaults_spec.lua
Expand Up @@ -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)
Expand Down Expand Up @@ -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'
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 4600193

Please sign in to comment.