Patch 8.2.1666
Problem: The initial value of 'backupskip' can have duplicate items.
Solution: Remove duplicates, like when it is set later. (Tom Ryder,
closes #6940)
Files: src/option.c, src/testdir/test_options.vim
*** ../vim-8.2.1665/src/option.c 2020-08-07 19:12:38.092576940 +0200
--- src/option.c 2020-09-12 14:51:03.675534570 +0200
***************
*** 37,42 ****
--- 37,43 ----
static void set_options_default(int opt_flags);
static void set_string_default_esc(char *name, char_u *val, int escape);
+ static char_u *find_dup_item(char_u *origval, char_u *newval, long_u flags);
static char_u *option_expand(int opt_idx, char_u *val);
static void didset_options(void);
static void didset_options2(void);
***************
*** 139,144 ****
--- 140,148 ----
int len;
garray_T ga;
int mustfree;
+ char_u *item;
+
+ opt_idx = findoption((char_u *)"backupskip");
ga_init2(&ga, 1, 100);
for (n = 0; n < (long)(sizeof(names) / sizeof(char *)); ++n)
***************
*** 158,172 ****
{
// First time count the NUL, otherwise count the ','.
len = (int)STRLEN(p) + 3;
! if (ga_grow(&ga, len) == OK)
{
if (ga.ga_len > 0)
STRCAT(ga.ga_data, ",");
! STRCAT(ga.ga_data, p);
! add_pathsep(ga.ga_data);
! STRCAT(ga.ga_data, "*");
ga.ga_len += len;
}
}
if (mustfree)
vim_free(p);
--- 162,181 ----
{
// First time count the NUL, otherwise count the ','.
len = (int)STRLEN(p) + 3;
! item = alloc(len);
! STRCPY(item, p);
! add_pathsep(item);
! STRCAT(item, "*");
! if (find_dup_item(ga.ga_data, item, options[opt_idx].flags)
! == NULL
! && ga_grow(&ga, len) == OK)
{
if (ga.ga_len > 0)
STRCAT(ga.ga_data, ",");
! STRCAT(ga.ga_data, item);
ga.ga_len += len;
}
+ vim_free(item);
}
if (mustfree)
vim_free(p);
***************
*** 668,673 ****
--- 677,722 ----
}
/*
+ * For an option value that contains comma separated items, find "newval" in
+ * "origval". Return NULL if not found.
+ */
+ static char_u *
+ find_dup_item(char_u *origval, char_u *newval, long_u flags)
+ {
+ int bs;
+ size_t newlen;
+ char_u *s;
+
+ if (origval == NULL)
+ return NULL;
+
+ newlen = STRLEN(newval);
+ for (s = origval; *s != NUL; ++s)
+ {
+ if ((!(flags & P_COMMA)
+ || s == origval
+ || (s[-1] == ',' && !(bs & 1)))
+ && STRNCMP(s, newval, newlen) == 0
+ && (!(flags & P_COMMA)
+ || s[newlen] == ','
+ || s[newlen] == NUL))
+ return s;
+ // Count backslashes. Only a comma with an even number of backslashes
+ // or a single backslash preceded by a comma before it is recognized as
+ // a separator.
+ if ((s > origval + 1
+ && s[-1] == '\\'
+ && s[-2] != ',')
+ || (s == origval + 1
+ && s[-1] == '\\'))
+ ++bs;
+ else
+ bs = 0;
+ }
+ return NULL;
+ }
+
+ /*
* Set the Vi-default value of a number option.
* Used for 'lines' and 'columns'.
*/
***************
*** 1572,1578 ****
#endif
unsigned newlen;
int comma;
- int bs;
int new_value_alloced; // new string option
// was allocated
--- 1621,1626 ----
***************
*** 1811,1849 ****
if (removing || (flags & P_NODUP))
{
i = (int)STRLEN(newval);
! bs = 0;
! for (s = origval; *s; ++s)
! {
! if ((!(flags & P_COMMA)
! || s == origval
! || (s[-1] == ',' && !(bs & 1)))
! && STRNCMP(s, newval, i) == 0
! && (!(flags & P_COMMA)
! || s[i] == ','
! || s[i] == NUL))
! break;
! // Count backslashes. Only a comma with an
! // even number of backslashes or a single
! // backslash preceded by a comma before it
! // is recognized as a separator
! if ((s > origval + 1
! && s[-1] == '\\'
! && s[-2] != ',')
! || (s == origval + 1
! && s[-1] == '\\'))
!
! ++bs;
! else
! bs = 0;
! }
// do not add if already there
! if ((adding || prepending) && *s)
{
prepending = FALSE;
adding = FALSE;
STRCPY(newval, origval);
}
}
// concatenate the two strings; add a ',' if
--- 1859,1878 ----
if (removing || (flags & P_NODUP))
{
i = (int)STRLEN(newval);
! s = find_dup_item(origval, newval, flags);
// do not add if already there
! if ((adding || prepending) && s != NULL)
{
prepending = FALSE;
adding = FALSE;
STRCPY(newval, origval);
}
+
+ // if no duplicate, move pointer to end of
+ // original value
+ if (s == NULL)
+ s = origval + (int)STRLEN(origval);
}
// concatenate the two strings; add a ',' if
*** ../vim-8.2.1665/src/testdir/test_options.vim 2020-08-13 18:57:56.562214742 +0200
--- src/testdir/test_options.vim 2020-09-12 14:40:30.105787221 +0200
***************
*** 1,5 ****
--- 1,6 ----
" Test for options
+ source shared.vim
source check.vim
source view_util.vim
***************
*** 587,592 ****
--- 588,622 ----
endif
endfor
+ " Duplicates from environment variables should be filtered out (option has
+ " P_NODUP). Run this in a separate instance and write v:errors in a file,
+ " so that we see what happens on startup.
+ let after =<< trim [CODE]
+ let bsklist = split(&backupskip, ',')
+ call assert_equal(uniq(copy(bsklist)), bsklist)
+ call writefile(['errors:'] + v:errors, 'Xtestout')
+ qall
+ [CODE]
+ call writefile(after, 'Xafter')
+ let cmd = GetVimProg() . ' --not-a-term -S Xafter --cmd "set enc=utf8"'
+
+ let saveenv = {}
+ for var in ['TMPDIR', 'TMP', 'TEMP']
+ let saveenv[var] = getenv(var)
+ call setenv(var, '/duplicate/path')
+ endfor
+
+ exe 'silent !' . cmd
+ call assert_equal(['errors:'], readfile('Xtestout'))
+
+ " restore environment variables
+ for var in ['TMPDIR', 'TMP', 'TEMP']
+ call setenv(var, saveenv[var])
+ endfor
+
+ call delete('Xtestout')
+ call delete('Xafter')
+
" Duplicates should be filtered out (option has P_NODUP)
let backupskip = &backupskip
set backupskip=
*** ../vim-8.2.1665/src/version.c 2020-09-11 22:25:11.298775020 +0200
--- src/version.c 2020-09-12 14:33:00.571400472 +0200
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 1666,
/**/
--
Every person is responsible for the choices he makes.
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language --
http://www.Zimbu.org ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///