summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-09-12 14:53:53 +0200
committerBram Moolenaar <Bram@vim.org>2020-09-12 14:53:53 +0200
commitb00ef0508b22905379953a164bdb4300015d3705 (patch)
treeba2fc4de9e8d4febac6475338c7bc8509fb3ffde
parent635414dd2f3ae7d4d972d79b806348a6516cb91a (diff)
downloadvim-git-b00ef0508b22905379953a164bdb4300015d3705.tar.gz
patch 8.2.1666: the initial value of 'backupskip' can have duplicate itemsv8.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)
-rw-r--r--src/option.c91
-rw-r--r--src/testdir/test_options.vim30
-rw-r--r--src/version.c2
3 files changed, 92 insertions, 31 deletions
diff --git a/src/option.c b/src/option.c
index 648f22db3..6ebc2bd9b 100644
--- a/src/option.c
+++ b/src/option.c
@@ -37,6 +37,7 @@
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,6 +140,9 @@ set_init_1(int clean_arg)
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,15 +162,20 @@ set_init_1(int clean_arg)
{
// First time count the NUL, otherwise count the ','.
len = (int)STRLEN(p) + 3;
- if (ga_grow(&ga, len) == OK)
+ 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, p);
- add_pathsep(ga.ga_data);
- STRCAT(ga.ga_data, "*");
+ STRCAT(ga.ga_data, item);
ga.ga_len += len;
}
+ vim_free(item);
}
if (mustfree)
vim_free(p);
@@ -668,6 +677,46 @@ set_string_default(char *name, char_u *val)
}
/*
+ * 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,7 +1621,6 @@ do_set(
#endif
unsigned newlen;
int comma;
- int bs;
int new_value_alloced; // new string option
// was allocated
@@ -1811,39 +1859,20 @@ do_set(
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;
- }
+ s = find_dup_item(origval, newval, flags);
// do not add if already there
- if ((adding || prepending) && *s)
+ 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
diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim
index c5e5ab47c..ec40ccc5f 100644
--- a/src/testdir/test_options.vim
+++ b/src/testdir/test_options.vim
@@ -1,5 +1,6 @@
" Test for options
+source shared.vim
source check.vim
source view_util.vim
@@ -587,6 +588,35 @@ func Test_backupskip()
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=
diff --git a/src/version.c b/src/version.c
index e0afdf835..596f38d7e 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1666,
+/**/
1665,
/**/
1664,