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 -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202009121254.08CCsQsf1118659%40masaka.moolenaar.net.

Raspunde prin e-mail lui