mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.1.0251: support full paths for 'backupdir' #11269
Problem: Using a full path is supported for 'directory' but not for
'backupdir'. (Mikolaj Machowski)
Solution: Support 'backupdir' as well. (Christian Brabandt, closes vim/vim#179)
b782ba475a
This commit is contained in:
parent
b1c4a8191e
commit
1ff5b60cb9
@ -843,6 +843,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
name, precede it with a backslash.
|
||||
- To include a comma in a directory name precede it with a backslash.
|
||||
- A directory name may end in an '/'.
|
||||
- For Unix and Win32, if a directory ends in two path separators "//",
|
||||
the swap file name will be built from the complete path to the file
|
||||
with all path separators changed to percent '%' signs. This will
|
||||
ensure file name uniqueness in the backup directory.
|
||||
On Win32, it is also possible to end with "\\". However, When a
|
||||
separating comma is following, you must use "//", since "\\" will
|
||||
include the comma in the file name. Therefore it is recommended to
|
||||
use '//', instead of '\\'.
|
||||
- Environment variables are expanded |:set_env|.
|
||||
- Careful with '\' characters, type one before a space, type two to
|
||||
get one in the option (see |option-backslash|), for example: >
|
||||
@ -1992,12 +2000,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
- A directory starting with "./" (or ".\" for Windows) means to
|
||||
put the swap file relative to where the edited file is. The leading
|
||||
"." is replaced with the path name of the edited file.
|
||||
- For Unix and Win32, if a directory ends in two path separators "//"
|
||||
or "\\", the swap file name will be built from the complete path to
|
||||
the file with all path separators substituted to percent '%' signs.
|
||||
This will ensure file name uniqueness in the preserve directory.
|
||||
On Win32, when a separating comma is following, you must use "//",
|
||||
since "\\" will include the comma in the file name.
|
||||
- For Unix and Win32, if a directory ends in two path separators "//",
|
||||
the swap file name will be built from the complete path to the file
|
||||
with all path separators substituted to percent '%' signs. This will
|
||||
ensure file name uniqueness in the preserve directory.
|
||||
On Win32, it is also possible to end with "\\". However, When a
|
||||
separating comma is following, you must use "//", since "\\" will
|
||||
include the comma in the file name. Therefore it is recommended to
|
||||
use '//', instead of '\\'.
|
||||
- Spaces after the comma are ignored, other spaces are considered part
|
||||
of the directory name. To have a space at the start of a directory
|
||||
name, precede it with a backslash.
|
||||
|
@ -2650,6 +2650,7 @@ buf_write(
|
||||
*/
|
||||
if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup) {
|
||||
FileInfo file_info;
|
||||
const bool no_prepend_dot = false;
|
||||
|
||||
if ((bkc & BKC_YES) || append) { /* "yes" */
|
||||
backup_copy = TRUE;
|
||||
@ -2737,6 +2738,7 @@ buf_write(
|
||||
int some_error = false;
|
||||
char_u *dirp;
|
||||
char_u *rootname;
|
||||
char_u *p;
|
||||
|
||||
/*
|
||||
* Try to make the backup in each directory in the 'bdir' option.
|
||||
@ -2756,6 +2758,17 @@ 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]) {
|
||||
// Ends with '//', Use Full path
|
||||
if ((p = (char_u *)make_percent_swname((char *)IObuff, (char *)fname))
|
||||
!= NULL) {
|
||||
backup = (char_u *)modname((char *)p, (char *)backup_ext,
|
||||
no_prepend_dot);
|
||||
xfree(p);
|
||||
}
|
||||
}
|
||||
|
||||
rootname = get_file_in_dir(fname, IObuff);
|
||||
if (rootname == NULL) {
|
||||
some_error = TRUE; /* out of memory */
|
||||
@ -2764,10 +2777,14 @@ buf_write(
|
||||
|
||||
FileInfo file_info_new;
|
||||
{
|
||||
/*
|
||||
* Make backup file name.
|
||||
*/
|
||||
backup = (char_u *)modname((char *)rootname, (char *)backup_ext, FALSE);
|
||||
//
|
||||
// Make the backup file name.
|
||||
//
|
||||
if (backup == NULL) {
|
||||
backup = (char_u *)modname((char *)rootname, (char *)backup_ext,
|
||||
no_prepend_dot);
|
||||
}
|
||||
|
||||
if (backup == NULL) {
|
||||
xfree(rootname);
|
||||
some_error = TRUE; /* out of memory */
|
||||
@ -2893,12 +2910,26 @@ nobackup:
|
||||
* Isolate one directory name and make the backup file name.
|
||||
*/
|
||||
(void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
|
||||
rootname = get_file_in_dir(fname, IObuff);
|
||||
if (rootname == NULL)
|
||||
backup = NULL;
|
||||
else {
|
||||
backup = (char_u *)modname((char *)rootname, (char *)backup_ext, FALSE);
|
||||
xfree(rootname);
|
||||
p = IObuff + STRLEN(IObuff);
|
||||
if (after_pathsep((char *)IObuff, (char *)p) && p[-1] == p[-2]) {
|
||||
// path ends with '//', use full path
|
||||
if ((p = (char_u *)make_percent_swname((char *)IObuff, (char *)fname))
|
||||
!= NULL) {
|
||||
backup = (char_u *)modname((char *)p, (char *)backup_ext,
|
||||
no_prepend_dot);
|
||||
xfree(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (backup == NULL) {
|
||||
rootname = get_file_in_dir(fname, IObuff);
|
||||
if (rootname == NULL) {
|
||||
backup = NULL;
|
||||
} else {
|
||||
backup = (char_u *)modname((char *)rootname, (char *)backup_ext,
|
||||
no_prepend_dot);
|
||||
xfree(rootname);
|
||||
}
|
||||
}
|
||||
|
||||
if (backup != NULL) {
|
||||
|
@ -1437,7 +1437,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>/"")
|
||||
*/
|
||||
static char *make_percent_swname(const char *dir, char *name)
|
||||
char *make_percent_swname(const char *dir, char *name)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
char *d = NULL;
|
||||
|
@ -2,6 +2,7 @@
|
||||
" This makes testing go faster, since Vim doesn't need to restart.
|
||||
|
||||
source test_assign.vim
|
||||
source test_backup.vim
|
||||
source test_behave.vim
|
||||
source test_cd.vim
|
||||
source test_changedtick.vim
|
||||
|
58
src/nvim/testdir/test_backup.vim
Normal file
58
src/nvim/testdir/test_backup.vim
Normal file
@ -0,0 +1,58 @@
|
||||
" Tests for the backup function
|
||||
|
||||
func Test_backup()
|
||||
set backup backupdir=.
|
||||
new
|
||||
call setline(1, ['line1', 'line2'])
|
||||
:f Xbackup.txt
|
||||
:w! Xbackup.txt
|
||||
" backup file is only created after
|
||||
" writing a second time (before overwriting)
|
||||
:w! Xbackup.txt
|
||||
let l = readfile('Xbackup.txt~')
|
||||
call assert_equal(['line1', 'line2'], l)
|
||||
bw!
|
||||
set backup&vim backupdir&vim
|
||||
call delete('Xbackup.txt')
|
||||
call delete('Xbackup.txt~')
|
||||
endfunc
|
||||
|
||||
func Test_backup2()
|
||||
set backup backupdir=.//
|
||||
new
|
||||
call setline(1, ['line1', 'line2', 'line3'])
|
||||
:f Xbackup.txt
|
||||
:w! Xbackup.txt
|
||||
" backup file is only created after
|
||||
" writing a second time (before overwriting)
|
||||
:w! Xbackup.txt
|
||||
sp *Xbackup.txt~
|
||||
call assert_equal(['line1', 'line2', 'line3'], getline(1,'$'))
|
||||
let f=expand('%')
|
||||
call assert_match('src%nvim%testdir%Xbackup.txt\~', f)
|
||||
bw!
|
||||
bw!
|
||||
call delete('Xbackup.txt')
|
||||
call delete(f)
|
||||
set backup&vim backupdir&vim
|
||||
endfunc
|
||||
|
||||
func Test_backup2_backupcopy()
|
||||
set backup backupdir=.// backupcopy=yes
|
||||
new
|
||||
call setline(1, ['line1', 'line2', 'line3'])
|
||||
:f Xbackup.txt
|
||||
:w! Xbackup.txt
|
||||
" backup file is only created after
|
||||
" writing a second time (before overwriting)
|
||||
:w! Xbackup.txt
|
||||
sp *Xbackup.txt~
|
||||
call assert_equal(['line1', 'line2', 'line3'], getline(1,'$'))
|
||||
let f=expand('%')
|
||||
call assert_match('src%nvim%testdir%Xbackup.txt\~', f)
|
||||
bw!
|
||||
bw!
|
||||
call delete('Xbackup.txt')
|
||||
call delete(f)
|
||||
set backup&vim backupdir&vim backupcopy&vim
|
||||
endfunc
|
@ -9,9 +9,12 @@ local nvim_prog = helpers.nvim_prog
|
||||
local request = helpers.request
|
||||
local retry = helpers.retry
|
||||
local rmdir = helpers.rmdir
|
||||
local mkdir = helpers.mkdir
|
||||
local sleep = helpers.sleep
|
||||
local read_file = helpers.read_file
|
||||
local trim = helpers.trim
|
||||
local currentdir = helpers.funcs.getcwd
|
||||
local iswin = helpers.iswin
|
||||
|
||||
describe('fileio', function()
|
||||
before_each(function()
|
||||
@ -24,6 +27,7 @@ describe('fileio', function()
|
||||
os.remove('Xtest_startup_file2')
|
||||
os.remove('Xtest_тест.md')
|
||||
rmdir('Xtest_startup_swapdir')
|
||||
rmdir('Xtest_backupdir')
|
||||
end)
|
||||
|
||||
it('fsync() codepaths #8304', function()
|
||||
@ -88,6 +92,27 @@ describe('fileio', function()
|
||||
eq('foo', bar_contents);
|
||||
end)
|
||||
|
||||
it('backup with full path #11214', function()
|
||||
clear()
|
||||
mkdir('Xtest_backupdir')
|
||||
command('set backup')
|
||||
command('set backupdir=Xtest_backupdir//')
|
||||
command('write Xtest_startup_file1')
|
||||
feed('ifoo<esc>')
|
||||
command('write')
|
||||
feed('Abar<esc>')
|
||||
command('write')
|
||||
|
||||
-- Backup filename = fullpath, separators replaced with "%".
|
||||
local backup_file_name = string.gsub(currentdir()..'/Xtest_startup_file1',
|
||||
iswin() and '[:/\\]' or '/', '%%') .. '~'
|
||||
local foo_contents = trim(read_file('Xtest_backupdir/'..backup_file_name))
|
||||
local foobar_contents = trim(read_file('Xtest_startup_file1'))
|
||||
|
||||
eq('foobar', foobar_contents);
|
||||
eq('foo', foo_contents);
|
||||
end)
|
||||
|
||||
it('readfile() on multibyte filename #10586', function()
|
||||
clear()
|
||||
local text = {
|
||||
|
Loading…
Reference in New Issue
Block a user