]> granicus.if.org Git - vim/commitdiff
patch 8.1.0251: using full path is not supported for 'backupdir' v8.1.0251
authorBram Moolenaar <Bram@vim.org>
Tue, 7 Aug 2018 19:39:28 +0000 (21:39 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 7 Aug 2018 19:39:28 +0000 (21:39 +0200)
Problem:    Using a full path is supported for 'directory' but not for
            'backupdir'. (Mikolaj Machowski)
Solution:   Support 'backupdir' as well. (Christian Brabandt, closes #179)

runtime/doc/options.txt
src/Make_all.mak
src/fileio.c
src/memline.c
src/proto/memline.pro
src/testdir/test_alot.vim
src/testdir/test_backup.vim [new file with mode: 0644]
src/version.c

index 8645c47333e5bc67e8b3462368d6191ad415fd32..eb455fc09b611a26388a033206b46e0ea01deb4d 100644 (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.
        - 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: >
@@ -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
          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.
index 9831f7b04409374dcd7ee20a8da70116b2d60e20..49ad4f0af84826c4ceafd711568739c271216027 100644 (file)
@@ -12,6 +12,7 @@ NEW_TESTS = \
        test_autocmd \
        test_autoload \
        test_backspace_opt \
+       test_backup \
        test_blockedit \
        test_breakindent \
        test_bufline \
index 281191cfbf77c07226cf7c8a320361e19b7daddf..42f388a11ff63fe7e200fdcee4ac6fbec16237fd 100644 (file)
@@ -3850,6 +3850,9 @@ buf_write(
            stat_T      st_new;
            char_u      *dirp;
            char_u      *rootname;
+#if defined(UNIX) || defined(WIN3264)
+           char_u      *p;
+#endif
 #if defined(UNIX)
            int         did_set_shortname;
            mode_t      umask_save;
@@ -3887,6 +3890,17 @@ buf_write(
                 * Isolate one directory name, using an entry in 'bdir'.
                 */
                (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);
                if (rootname == NULL)
                {
@@ -3904,9 +3918,10 @@ buf_write(
                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);
                    if (backup == NULL)
                    {
@@ -4108,14 +4123,29 @@ buf_write(
                 * 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
+
+#if defined(UNIX) || defined(WIN3264)
+               p = IObuff + STRLEN(IObuff);
+               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, backup_ext, FALSE);
-                   vim_free(rootname);
+                   rootname = get_file_in_dir(fname, IObuff);
+                   if (rootname == NULL)
+                       backup = NULL;
+                   else
+                   {
+                       backup = buf_modname(
+                               (buf->b_p_sn || buf->b_shortname),
+                                               rootname, backup_ext, FALSE);
+                       vim_free(rootname);
+                   }
                }
 
                if (backup != NULL)
@@ -6252,7 +6282,7 @@ shorten_filenames(char_u **fnames, int count)
 #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.
  *
  * Assumed that fname is a valid name found in the filesystem we assure that
index be395fce6b86e2abf95c751f9060527ce6ba9b68..a2f0b4f6269b7242707fb988914bde4382a2286a 100644 (file)
@@ -262,9 +262,6 @@ static int fnamecmp_ino(char_u *, char_u *, long);
 #endif
 static void long_to_char(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
 static cryptstate_T *ml_crypt_prepare(memfile_T *mfp, off_T offset, int reading);
 #endif
@@ -2007,18 +2004,18 @@ recover_names(
     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
  * signs, to dir. An unnamed buffer is handled as "" (<currentdir>/"")
  */
-    static char_u *
+    char_u *
 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 *) "");
-    d = NULL;
+    f = fix_fname(name != NULL ? name : (char_u *)"");
     if (f != NULL)
     {
        s = alloc((unsigned)(STRLEN(f) + 1));
@@ -4070,8 +4067,6 @@ attention_message(
 }
 
 #if defined(FEAT_EVAL)
-static int do_swapexists(buf_T *buf, char_u *fname);
-
 /*
  * Trigger the SwapExists autocommands.
  * Returns a value for equivalent to do_dialog() (see below):
index bddb902f484a002a43308983ccfe3576026a83f5..727b24cc3077251d5771b461a65e16d2fa435c2d 100644 (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);
 long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp);
 void goto_byte(long cnt);
+char_u *make_percent_swname (char_u *dir, char_u *name);
 /* vim: set ft=c : */
index 1465a7abfc58d1ad12073b3470d5a660c49fec2a..16a3f7f8ac286e5da0f785ad00cba06d63264019 100644 (file)
@@ -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_bufline.vim
 source test_cd.vim
 source test_changedtick.vim
diff --git a/src/testdir/test_backup.vim b/src/testdir/test_backup.vim
new file mode 100644 (file)
index 0000000..3187b58
--- /dev/null
@@ -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
index c9b0ec4dcba60fa25f99dff0334ff33385b48cb7..432a7ab752ddc5a199770cdec012fcfebaefb05a 100644 (file)
@@ -794,6 +794,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    251,
 /**/
     250,
 /**/