0
0
mirror of https://github.com/vim/vim.git synced 2025-09-29 04:34:16 -04:00

patch 8.1.0251: using full path is not supported for 'backupdir'

Problem:    Using a full path is supported for 'directory' but not for
            'backupdir'. (Mikolaj Machowski)
Solution:   Support 'backupdir' as well. (Christian Brabandt, closes #179)
This commit is contained in:
Bram Moolenaar
2018-08-07 21:39:28 +02:00
parent b1cf16113f
commit b782ba475a
8 changed files with 124 additions and 26 deletions

View File

@@ -1054,6 +1054,14 @@ A jump table for the options with a short description can be found at |Q_op|.
name, precede it with a backslash. name, precede it with a backslash.
- To include a comma in a directory 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 '/'. - 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|. - Environment variables are expanded |:set_env|.
- Careful with '\' characters, type one before a space, type two to - Careful with '\' characters, type one before a space, type two to
get one in the option (see |option-backslash|), for example: > get one in the option (see |option-backslash|), for example: >
@@ -2680,12 +2688,14 @@ A jump table for the options with a short description can be found at |Q_op|.
- A directory starting with "./" (or ".\" for MS-DOS et al.) means to - A directory starting with "./" (or ".\" for MS-DOS et al.) means to
put the swap file relative to where the edited file is. The leading put the swap file relative to where the edited file is. The leading
"." is replaced with the path name of the edited file. "." is replaced with the path name of the edited file.
- For Unix and Win32, if a directory ends in two path separators "//" - 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 swap file name will be built from the complete path to the file
the file with all path separators substituted to percent '%' signs. with all path separators substituted to percent '%' signs. This will
This will ensure file name uniqueness in the preserve directory. ensure file name uniqueness in the preserve directory.
On Win32, when a separating comma is following, you must use "//", On Win32, it is also possible to end with "\\". However, When a
since "\\" will include the comma in the file name. 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 - 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 of the directory name. To have a space at the start of a directory
name, precede it with a backslash. name, precede it with a backslash.

View File

@@ -12,6 +12,7 @@ NEW_TESTS = \
test_autocmd \ test_autocmd \
test_autoload \ test_autoload \
test_backspace_opt \ test_backspace_opt \
test_backup \
test_blockedit \ test_blockedit \
test_breakindent \ test_breakindent \
test_bufline \ test_bufline \

View File

@@ -3850,6 +3850,9 @@ buf_write(
stat_T st_new; stat_T st_new;
char_u *dirp; char_u *dirp;
char_u *rootname; char_u *rootname;
#if defined(UNIX) || defined(WIN3264)
char_u *p;
#endif
#if defined(UNIX) #if defined(UNIX)
int did_set_shortname; int did_set_shortname;
mode_t umask_save; mode_t umask_save;
@@ -3887,6 +3890,17 @@ buf_write(
* Isolate one directory name, using an entry in 'bdir'. * Isolate one directory name, using an entry in 'bdir'.
*/ */
(void)copy_option_part(&dirp, copybuf, BUFSIZE, ","); (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
#if defined(UNIX) || defined(WIN3264)
p = copybuf + STRLEN(copybuf);
if (after_pathsep(copybuf, p) && p[-1] == p[-2])
// Ends with '//', use full path
if ((p = make_percent_swname(copybuf, fname)) != NULL)
{
backup = modname(p, backup_ext, FALSE);
vim_free(p);
}
#endif
rootname = get_file_in_dir(fname, copybuf); rootname = get_file_in_dir(fname, copybuf);
if (rootname == NULL) if (rootname == NULL)
{ {
@@ -3904,9 +3918,10 @@ buf_write(
for (;;) for (;;)
{ {
/* /*
* Make backup file name. * Make the backup file name.
*/ */
backup = buf_modname((buf->b_p_sn || buf->b_shortname), if (backup == NULL)
backup = buf_modname((buf->b_p_sn || buf->b_shortname),
rootname, backup_ext, FALSE); rootname, backup_ext, FALSE);
if (backup == NULL) if (backup == NULL)
{ {
@@ -4108,14 +4123,29 @@ buf_write(
* Isolate one directory name and make the backup file name. * Isolate one directory name and make the backup file name.
*/ */
(void)copy_option_part(&dirp, IObuff, IOSIZE, ","); (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
rootname = get_file_in_dir(fname, IObuff);
if (rootname == NULL) #if defined(UNIX) || defined(WIN3264)
backup = NULL; p = IObuff + STRLEN(IObuff);
else if (after_pathsep(IObuff, p) && p[-1] == p[-2])
// path ends with '//', use full path
if ((p = make_percent_swname(IObuff, fname)) != NULL)
{
backup = modname(p, backup_ext, FALSE);
vim_free(p);
}
#endif
if (backup == NULL)
{ {
backup = buf_modname((buf->b_p_sn || buf->b_shortname), rootname = get_file_in_dir(fname, IObuff);
rootname, backup_ext, FALSE); if (rootname == NULL)
vim_free(rootname); backup = NULL;
else
{
backup = buf_modname(
(buf->b_p_sn || buf->b_shortname),
rootname, backup_ext, FALSE);
vim_free(rootname);
}
} }
if (backup != NULL) if (backup != NULL)
@@ -6252,7 +6282,7 @@ shorten_filenames(char_u **fnames, int count)
#endif #endif
/* /*
* add extension to file name - change path/fo.o.h to path/fo.o.h.ext or * Add extension to file name - change path/fo.o.h to path/fo.o.h.ext or
* fo_o_h.ext for MSDOS or when shortname option set. * fo_o_h.ext for MSDOS or when shortname option set.
* *
* Assumed that fname is a valid name found in the filesystem we assure that * Assumed that fname is a valid name found in the filesystem we assure that

View File

@@ -262,9 +262,6 @@ static int fnamecmp_ino(char_u *, char_u *, long);
#endif #endif
static void long_to_char(long, char_u *); static void long_to_char(long, char_u *);
static long char_to_long(char_u *); static long char_to_long(char_u *);
#if defined(UNIX) || defined(WIN3264)
static char_u *make_percent_swname(char_u *dir, char_u *name);
#endif
#ifdef FEAT_CRYPT #ifdef FEAT_CRYPT
static cryptstate_T *ml_crypt_prepare(memfile_T *mfp, off_T offset, int reading); static cryptstate_T *ml_crypt_prepare(memfile_T *mfp, off_T offset, int reading);
#endif #endif
@@ -2007,18 +2004,18 @@ recover_names(
return file_count; return file_count;
} }
#if defined(UNIX) || defined(WIN3264) /* Need _very_ long file names */ #if defined(UNIX) || defined(WIN3264) || defined(PROTO)
/* /*
* Need _very_ long file names.
* Append the full path to name with path separators made into percent * Append the full path to name with path separators made into percent
* signs, to dir. An unnamed buffer is handled as "" (<currentdir>/"") * signs, to dir. An unnamed buffer is handled as "" (<currentdir>/"")
*/ */
static char_u * char_u *
make_percent_swname(char_u *dir, char_u *name) make_percent_swname(char_u *dir, char_u *name)
{ {
char_u *d, *s, *f; char_u *d = NULL, *s, *f;
f = fix_fname(name != NULL ? name : (char_u *) ""); f = fix_fname(name != NULL ? name : (char_u *)"");
d = NULL;
if (f != NULL) if (f != NULL)
{ {
s = alloc((unsigned)(STRLEN(f) + 1)); s = alloc((unsigned)(STRLEN(f) + 1));
@@ -4070,8 +4067,6 @@ attention_message(
} }
#if defined(FEAT_EVAL) #if defined(FEAT_EVAL)
static int do_swapexists(buf_T *buf, char_u *fname);
/* /*
* Trigger the SwapExists autocommands. * Trigger the SwapExists autocommands.
* Returns a value for equivalent to do_dialog() (see below): * Returns a value for equivalent to do_dialog() (see below):

View File

@@ -34,4 +34,5 @@ char_u *ml_encrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned siz
void ml_decrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned size); void ml_decrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned size);
long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp); long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp);
void goto_byte(long cnt); void goto_byte(long cnt);
char_u *make_percent_swname (char_u *dir, char_u *name);
/* vim: set ft=c : */ /* vim: set ft=c : */

View File

@@ -2,6 +2,7 @@
" This makes testing go faster, since Vim doesn't need to restart. " This makes testing go faster, since Vim doesn't need to restart.
source test_assign.vim source test_assign.vim
source test_backup.vim
source test_bufline.vim source test_bufline.vim
source test_cd.vim source test_cd.vim
source test_changedtick.vim source test_changedtick.vim

View 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%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%testdir%Xbackup.txt\~', f)
bw!
bw!
call delete('Xbackup.txt')
call delete(f)
set backup&vim backupdir&vim backupcopy&vim
endfunc

View File

@@ -794,6 +794,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
251,
/**/ /**/
250, 250,
/**/ /**/