Skip to content

Commit b782ba4

Browse files
committed
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)
1 parent b1cf161 commit b782ba4

8 files changed

Lines changed: 124 additions & 26 deletions

File tree

runtime/doc/options.txt

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,14 @@ A jump table for the options with a short description can be found at |Q_op|.
10541054
name, precede it with a backslash.
10551055
- To include a comma in a directory name precede it with a backslash.
10561056
- A directory name may end in an '/'.
1057+
- For Unix and Win32, if a directory ends in two path separators "//",
1058+
the swap file name will be built from the complete path to the file
1059+
with all path separators changed to percent '%' signs. This will
1060+
ensure file name uniqueness in the backup directory.
1061+
On Win32, it is also possible to end with "\\". However, When a
1062+
separating comma is following, you must use "//", since "\\" will
1063+
include the comma in the file name. Therefore it is recommended to
1064+
use '//', instead of '\\'.
10571065
- Environment variables are expanded |:set_env|.
10581066
- Careful with '\' characters, type one before a space, type two to
10591067
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|.
26802688
- A directory starting with "./" (or ".\" for MS-DOS et al.) means to
26812689
put the swap file relative to where the edited file is. The leading
26822690
"." is replaced with the path name of the edited file.
2683-
- For Unix and Win32, if a directory ends in two path separators "//"
2684-
or "\\", the swap file name will be built from the complete path to
2685-
the file with all path separators substituted to percent '%' signs.
2686-
This will ensure file name uniqueness in the preserve directory.
2687-
On Win32, when a separating comma is following, you must use "//",
2688-
since "\\" will include the comma in the file name.
2691+
- For Unix and Win32, if a directory ends in two path separators "//",
2692+
the swap file name will be built from the complete path to the file
2693+
with all path separators substituted to percent '%' signs. This will
2694+
ensure file name uniqueness in the preserve directory.
2695+
On Win32, it is also possible to end with "\\". However, When a
2696+
separating comma is following, you must use "//", since "\\" will
2697+
include the comma in the file name. Therefore it is recommended to
2698+
use '//', instead of '\\'.
26892699
- Spaces after the comma are ignored, other spaces are considered part
26902700
of the directory name. To have a space at the start of a directory
26912701
name, precede it with a backslash.

src/Make_all.mak

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ NEW_TESTS = \
1212
test_autocmd \
1313
test_autoload \
1414
test_backspace_opt \
15+
test_backup \
1516
test_blockedit \
1617
test_breakindent \
1718
test_bufline \

src/fileio.c

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3850,6 +3850,9 @@ buf_write(
38503850
stat_T st_new;
38513851
char_u *dirp;
38523852
char_u *rootname;
3853+
#if defined(UNIX) || defined(WIN3264)
3854+
char_u *p;
3855+
#endif
38533856
#if defined(UNIX)
38543857
int did_set_shortname;
38553858
mode_t umask_save;
@@ -3887,6 +3890,17 @@ buf_write(
38873890
* Isolate one directory name, using an entry in 'bdir'.
38883891
*/
38893892
(void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
3893+
3894+
#if defined(UNIX) || defined(WIN3264)
3895+
p = copybuf + STRLEN(copybuf);
3896+
if (after_pathsep(copybuf, p) && p[-1] == p[-2])
3897+
// Ends with '//', use full path
3898+
if ((p = make_percent_swname(copybuf, fname)) != NULL)
3899+
{
3900+
backup = modname(p, backup_ext, FALSE);
3901+
vim_free(p);
3902+
}
3903+
#endif
38903904
rootname = get_file_in_dir(fname, copybuf);
38913905
if (rootname == NULL)
38923906
{
@@ -3904,9 +3918,10 @@ buf_write(
39043918
for (;;)
39053919
{
39063920
/*
3907-
* Make backup file name.
3921+
* Make the backup file name.
39083922
*/
3909-
backup = buf_modname((buf->b_p_sn || buf->b_shortname),
3923+
if (backup == NULL)
3924+
backup = buf_modname((buf->b_p_sn || buf->b_shortname),
39103925
rootname, backup_ext, FALSE);
39113926
if (backup == NULL)
39123927
{
@@ -4108,14 +4123,29 @@ buf_write(
41084123
* Isolate one directory name and make the backup file name.
41094124
*/
41104125
(void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
4111-
rootname = get_file_in_dir(fname, IObuff);
4112-
if (rootname == NULL)
4113-
backup = NULL;
4114-
else
4126+
4127+
#if defined(UNIX) || defined(WIN3264)
4128+
p = IObuff + STRLEN(IObuff);
4129+
if (after_pathsep(IObuff, p) && p[-1] == p[-2])
4130+
// path ends with '//', use full path
4131+
if ((p = make_percent_swname(IObuff, fname)) != NULL)
4132+
{
4133+
backup = modname(p, backup_ext, FALSE);
4134+
vim_free(p);
4135+
}
4136+
#endif
4137+
if (backup == NULL)
41154138
{
4116-
backup = buf_modname((buf->b_p_sn || buf->b_shortname),
4117-
rootname, backup_ext, FALSE);
4118-
vim_free(rootname);
4139+
rootname = get_file_in_dir(fname, IObuff);
4140+
if (rootname == NULL)
4141+
backup = NULL;
4142+
else
4143+
{
4144+
backup = buf_modname(
4145+
(buf->b_p_sn || buf->b_shortname),
4146+
rootname, backup_ext, FALSE);
4147+
vim_free(rootname);
4148+
}
41194149
}
41204150

41214151
if (backup != NULL)
@@ -6252,7 +6282,7 @@ shorten_filenames(char_u **fnames, int count)
62526282
#endif
62536283

62546284
/*
6255-
* add extension to file name - change path/fo.o.h to path/fo.o.h.ext or
6285+
* Add extension to file name - change path/fo.o.h to path/fo.o.h.ext or
62566286
* fo_o_h.ext for MSDOS or when shortname option set.
62576287
*
62586288
* Assumed that fname is a valid name found in the filesystem we assure that

src/memline.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,6 @@ static int fnamecmp_ino(char_u *, char_u *, long);
262262
#endif
263263
static void long_to_char(long, char_u *);
264264
static long char_to_long(char_u *);
265-
#if defined(UNIX) || defined(WIN3264)
266-
static char_u *make_percent_swname(char_u *dir, char_u *name);
267-
#endif
268265
#ifdef FEAT_CRYPT
269266
static cryptstate_T *ml_crypt_prepare(memfile_T *mfp, off_T offset, int reading);
270267
#endif
@@ -2007,18 +2004,18 @@ recover_names(
20072004
return file_count;
20082005
}
20092006

2010-
#if defined(UNIX) || defined(WIN3264) /* Need _very_ long file names */
2007+
#if defined(UNIX) || defined(WIN3264) || defined(PROTO)
20112008
/*
2009+
* Need _very_ long file names.
20122010
* Append the full path to name with path separators made into percent
20132011
* signs, to dir. An unnamed buffer is handled as "" (<currentdir>/"")
20142012
*/
2015-
static char_u *
2013+
char_u *
20162014
make_percent_swname(char_u *dir, char_u *name)
20172015
{
2018-
char_u *d, *s, *f;
2016+
char_u *d = NULL, *s, *f;
20192017

2020-
f = fix_fname(name != NULL ? name : (char_u *) "");
2021-
d = NULL;
2018+
f = fix_fname(name != NULL ? name : (char_u *)"");
20222019
if (f != NULL)
20232020
{
20242021
s = alloc((unsigned)(STRLEN(f) + 1));
@@ -4070,8 +4067,6 @@ attention_message(
40704067
}
40714068

40724069
#if defined(FEAT_EVAL)
4073-
static int do_swapexists(buf_T *buf, char_u *fname);
4074-
40754070
/*
40764071
* Trigger the SwapExists autocommands.
40774072
* Returns a value for equivalent to do_dialog() (see below):

src/proto/memline.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,5 @@ char_u *ml_encrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned siz
3434
void ml_decrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned size);
3535
long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp);
3636
void goto_byte(long cnt);
37+
char_u *make_percent_swname (char_u *dir, char_u *name);
3738
/* vim: set ft=c : */

src/testdir/test_alot.vim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
" This makes testing go faster, since Vim doesn't need to restart.
33

44
source test_assign.vim
5+
source test_backup.vim
56
source test_bufline.vim
67
source test_cd.vim
78
source test_changedtick.vim

src/testdir/test_backup.vim

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
" Tests for the backup function
2+
3+
func Test_backup()
4+
set backup backupdir=.
5+
new
6+
call setline(1, ['line1', 'line2'])
7+
:f Xbackup.txt
8+
:w! Xbackup.txt
9+
" backup file is only created after
10+
" writing a second time (before overwriting)
11+
:w! Xbackup.txt
12+
let l = readfile('Xbackup.txt~')
13+
call assert_equal(['line1', 'line2'], l)
14+
bw!
15+
set backup&vim backupdir&vim
16+
call delete('Xbackup.txt')
17+
call delete('Xbackup.txt~')
18+
endfunc
19+
20+
func Test_backup2()
21+
set backup backupdir=.//
22+
new
23+
call setline(1, ['line1', 'line2', 'line3'])
24+
:f Xbackup.txt
25+
:w! Xbackup.txt
26+
" backup file is only created after
27+
" writing a second time (before overwriting)
28+
:w! Xbackup.txt
29+
sp *Xbackup.txt~
30+
call assert_equal(['line1', 'line2', 'line3'], getline(1,'$'))
31+
let f=expand('%')
32+
call assert_match('src%testdir%Xbackup.txt\~', f)
33+
bw!
34+
bw!
35+
call delete('Xbackup.txt')
36+
call delete(f)
37+
set backup&vim backupdir&vim
38+
endfunc
39+
40+
func Test_backup2_backupcopy()
41+
set backup backupdir=.// backupcopy=yes
42+
new
43+
call setline(1, ['line1', 'line2', 'line3'])
44+
:f Xbackup.txt
45+
:w! Xbackup.txt
46+
" backup file is only created after
47+
" writing a second time (before overwriting)
48+
:w! Xbackup.txt
49+
sp *Xbackup.txt~
50+
call assert_equal(['line1', 'line2', 'line3'], getline(1,'$'))
51+
let f=expand('%')
52+
call assert_match('src%testdir%Xbackup.txt\~', f)
53+
bw!
54+
bw!
55+
call delete('Xbackup.txt')
56+
call delete(f)
57+
set backup&vim backupdir&vim backupcopy&vim
58+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,8 @@ static char *(features[]) =
794794

795795
static int included_patches[] =
796796
{ /* Add new patch number below this line */
797+
/**/
798+
251,
797799
/**/
798800
250,
799801
/**/

0 commit comments

Comments
 (0)