Patch 8.1.2126
Problem:    Viminfo not sufficiently tested.
Solution:   Add more test cases.  Clean up comments. (Yegappan Lakshmanan,
            closes #5032)
Files:      src/search.c, src/structs.h, src/testdir/test_viminfo.vim,
            src/viminfo.c


*** ../vim-8.1.2125/src/search.c        2019-10-06 22:00:08.301244080 +0200
--- src/search.c        2019-10-09 21:55:06.286304147 +0200
***************
*** 5783,5794 ****
--- 5783,5800 ----
  #endif
  
  #ifdef FEAT_VIMINFO
+ /*
+  * Return the last used search pattern at "idx".
+  */
      spat_T *
  get_spat(int idx)
  {
      return &spats[idx];
  }
  
+ /*
+  * Return the last used search pattern index.
+  */
      int
  get_spat_last_idx(void)
  {
*** ../vim-8.1.2125/src/structs.h       2019-09-28 19:04:06.997029566 +0200
--- src/structs.h       2019-10-09 21:55:06.286304147 +0200
***************
*** 1134,1151 ****
  } vimconv_T;
  
  /*
-  * Structure used for reading from the viminfo file.
-  */
- typedef struct
- {
-     char_u    *vir_line;      // text of the current line
-     FILE      *vir_fd;        // file descriptor
-     vimconv_T vir_conv;       // encoding conversion
-     int               vir_version;    // viminfo version detected or -1
-     garray_T  vir_barlines;   // lines starting with |
- } vir_T;
- 
- /*
   * Structure used for the command line history.
   */
  typedef struct hist_entry
--- 1134,1139 ----
*** ../vim-8.1.2125/src/testdir/test_viminfo.vim        2019-10-04 
21:20:21.779342097 +0200
--- src/testdir/test_viminfo.vim        2019-10-09 21:55:06.286304147 +0200
***************
*** 1,5 ****
--- 1,7 ----
  " Test for reading and writing .viminfo
  
+ source check.vim
+ 
  function Test_viminfo_read_and_write()
    " First clear 'history', so that "hislen" is zero.  Then set it again,
    " simulating Vim starting up.
***************
*** 715,740 ****
    rviminfo! Xviminfo
    call assert_equal(join(repeat(["sun is rising"], 200), "\n"), @r)
    call delete('Xviminfo')
    let &viminfo = save_viminfo
  endfunc
  
  " Test for setting 'viminfofile' to NONE
  func Test_viminfofile_none()
    set viminfofile=NONE
    wviminfo Xviminfo
    call assert_false(filereadable('Xviminfo'))
    call writefile([''], 'Xviminfo')
    call assert_fails('rviminfo Xviminfo', 'E195:')
    call delete('Xviminfo')
  endfunc
  
! " Test for an unwritable 'viminfo' file
! func Test_viminfo_readonly()
!   if !has('unix')
!       return
!   endif
    call writefile([''], 'Xviminfo')
    call setfperm('Xviminfo', 'r-x------')
    call assert_fails('wviminfo Xviminfo', 'E137:')
    call delete('Xviminfo')
  endfunc
--- 717,794 ----
    rviminfo! Xviminfo
    call assert_equal(join(repeat(["sun is rising"], 200), "\n"), @r)
    call delete('Xviminfo')
+   let @r = ''
    let &viminfo = save_viminfo
  endfunc
  
  " Test for setting 'viminfofile' to NONE
  func Test_viminfofile_none()
+   let save_vif = &viminfofile
    set viminfofile=NONE
    wviminfo Xviminfo
    call assert_false(filereadable('Xviminfo'))
    call writefile([''], 'Xviminfo')
    call assert_fails('rviminfo Xviminfo', 'E195:')
    call delete('Xviminfo')
+   let &viminfofile = save_vif
  endfunc
  
! " Test for an unwritable and unreadble 'viminfo' file
! func Test_viminfo_perm()
!   CheckUnix
    call writefile([''], 'Xviminfo')
    call setfperm('Xviminfo', 'r-x------')
    call assert_fails('wviminfo Xviminfo', 'E137:')
+   call setfperm('Xviminfo', '--x------')
+   call assert_fails('rviminfo Xviminfo', 'E195:')
+   call delete('Xviminfo')
+ endfunc
+ 
+ " Test for writing to an existing viminfo file merges the file marks
+ func XTest_viminfo_marks_merge()
+   let save_viminfo = &viminfo
+   set viminfo&vim
+   set viminfo^=%
+   enew
+   %argdelete
+   %bwipe
+ 
+   call writefile(repeat(['editor'], 10), 'Xbufa')
+   call writefile(repeat(['Vim'], 10), 'Xbufb')
+ 
+   " set marks in buffers
+   call test_settime(10)
+   edit Xbufa
+   4mark a
+   wviminfo Xviminfo
+   edit Xbufb
+   4mark b
+   wviminfo Xviminfo
+   %bwipe
+ 
+   " set marks in buffers again
+   call test_settime(20)
+   edit Xbufb
+   6mark b
+   wviminfo Xviminfo
+   edit Xbufa
+   6mark a
+   wviminfo Xviminfo
+   %bwipe
+ 
+   " Load the buffer and check the marks
+   edit Xbufa
+   rviminfo! Xviminfo
+   call assert_equal(6, line("'a"))
+   edit Xbufb
+   rviminfo! Xviminfo
+   call assert_equal(6, line("'b"))
+ 
+   " cleanup
+   %bwipe
    call delete('Xviminfo')
+   call delete('Xbufa')
+   call delete('Xbufb')
+   call test_settime(0)
+   let &viminfo=save_viminfo
  endfunc
*** ../vim-8.1.2125/src/viminfo.c       2019-09-01 16:01:25.588754537 +0200
--- src/viminfo.c       2019-10-09 21:55:06.286304147 +0200
***************
*** 14,19 ****
--- 14,31 ----
  #include "vim.h"
  #include "version.h"
  
+ /*
+  * Structure used for reading from the viminfo file.
+  */
+ typedef struct
+ {
+     char_u    *vir_line;      // text of the current line
+     FILE      *vir_fd;        // file descriptor
+     vimconv_T vir_conv;       // encoding conversion
+     int               vir_version;    // viminfo version detected or -1
+     garray_T  vir_barlines;   // lines starting with |
+ } vir_T;
+ 
  #if defined(FEAT_VIMINFO) || defined(PROTO)
  
  static int  viminfo_errcnt;
***************
*** 822,832 ****
        if (num_saved > hislen)
            num_saved = hislen;
  
!       /*
!        * Merge typed and viminfo history:
!        * round 1: history of typed commands.
!        * round 2: history from recently read viminfo.
!        */
        for (round = 1; round <= 2; ++round)
        {
            if (round == 1)
--- 834,842 ----
        if (num_saved > hislen)
            num_saved = hislen;
  
!       // Merge typed and viminfo history:
!       // round 1: history of typed commands.
!       // round 2: history from recently read viminfo.
        for (round = 1; round <= 2; ++round)
        {
            if (round == 1)
***************
*** 2671,2686 ****
      int               i;
      int               read_next = TRUE;
  
!     /*
!      * The format is: |{bartype},{value},...
!      * For a very long string:
!      *     |{bartype},>{length of "{text}{text2}"}
!      *     |<{text1}
!      *     |<{text2},{value}
!      * For a long line not using a string
!      *     |{bartype},{lots of values},>
!      *     |<{value},{value}
!      */
      if (*p == '<')
      {
        // Continuation line of an unrecognized item.
--- 2681,2694 ----
      int               i;
      int               read_next = TRUE;
  
!     // The format is: |{bartype},{value},...
!     // For a very long string:
!     //     |{bartype},>{length of "{text}{text2}"}
!     //     |<{text1}
!     //     |<{text2},{value}
!     // For a long line not using a string
!     //     |{bartype},{lots of values},>
!     //     |<{value},{value}
      if (*p == '<')
      {
        // Continuation line of an unrecognized item.
***************
*** 3032,3049 ****
      }
      else
      {
!       /*
!        * There is an existing viminfo file.  Create a temporary file to
!        * write the new viminfo into, in the same directory as the
!        * existing viminfo file, which will be renamed once all writing is
!        * successful.
!        */
  #ifdef UNIX
!       /*
!        * For Unix we check the owner of the file.  It's not very nice to
!        * overwrite a user's viminfo file after a "su root", with a
!        * viminfo file that the user can't read.
!        */
        st_old.st_dev = (dev_t)0;
        st_old.st_ino = 0;
        st_old.st_mode = 0600;
--- 3040,3053 ----
      }
      else
      {
!       // There is an existing viminfo file.  Create a temporary file to
!       // write the new viminfo into, in the same directory as the
!       // existing viminfo file, which will be renamed once all writing is
!       // successful.
  #ifdef UNIX
!       // For Unix we check the owner of the file.  It's not very nice to
!       // overwrite a user's viminfo file after a "su root", with a
!       // viminfo file that the user can't read.
        st_old.st_dev = (dev_t)0;
        st_old.st_ino = 0;
        st_old.st_mode = 0600;
***************
*** 3069,3082 ****
        hidden = mch_ishidden(fname);
  #endif
  
!       /*
!        * Make tempname, find one that does not exist yet.
!        * Beware of a race condition: If someone logs out and all Vim
!        * instances exit at the same time a temp file might be created between
!        * stat() and open().  Use mch_open() with O_EXCL to avoid that.
!        * May try twice: Once normal and once with shortname set, just in
!        * case somebody puts his viminfo file in an 8.3 filesystem.
!        */
        for (;;)
        {
            int         next_char = 'z';
--- 3073,3084 ----
        hidden = mch_ishidden(fname);
  #endif
  
!       // Make tempname, find one that does not exist yet.
!       // Beware of a race condition: If someone logs out and all Vim
!       // instances exit at the same time a temp file might be created between
!       // stat() and open().  Use mch_open() with O_EXCL to avoid that.
!       // May try twice: Once normal and once with shortname set, just in
!       // case somebody puts his viminfo file in an 8.3 filesystem.
        for (;;)
        {
            int         next_char = 'z';
***************
*** 3098,3127 ****
            if (tempname == NULL)               // out of memory
                break;
  
!           /*
!            * Try a series of names.  Change one character, just before
!            * the extension.  This should also work for an 8.3
!            * file name, when after adding the extension it still is
!            * the same file as the original.
!            */
            wp = tempname + STRLEN(tempname) - 5;
            if (wp < gettail(tempname))     // empty file name?
                wp = gettail(tempname);
            for (;;)
            {
!               /*
!                * Check if tempfile already exists.  Never overwrite an
!                * existing file!
!                */
                if (mch_stat((char *)tempname, &st_new) == 0)
                {
  #ifdef UNIX
!                   /*
!                    * Check if tempfile is same as original file.  May happen
!                    * when modname() gave the same file back.  E.g.  silly
!                    * link, or file name-length reached.  Try again with
!                    * shortname set.
!                    */
                    if (!shortname && st_new.st_dev == st_old.st_dev
                                                && st_new.st_ino == 
st_old.st_ino)
                    {
--- 3100,3123 ----
            if (tempname == NULL)               // out of memory
                break;
  
!           // Try a series of names.  Change one character, just before
!           // the extension.  This should also work for an 8.3
!           // file name, when after adding the extension it still is
!           // the same file as the original.
            wp = tempname + STRLEN(tempname) - 5;
            if (wp < gettail(tempname))     // empty file name?
                wp = gettail(tempname);
            for (;;)
            {
!               // Check if tempfile already exists.  Never overwrite an
!               // existing file!
                if (mch_stat((char *)tempname, &st_new) == 0)
                {
  #ifdef UNIX
!                   // Check if tempfile is same as original file.  May happen
!                   // when modname() gave the same file back.  E.g.  silly
!                   // link, or file name-length reached.  Try again with
!                   // shortname set.
                    if (!shortname && st_new.st_dev == st_old.st_dev
                                                && st_new.st_ino == 
st_old.st_ino)
                    {
***************
*** 3199,3208 ****
        {
                stat_T  tmp_st;
  
!           /*
!            * Make sure the original owner can read/write the tempfile and
!            * otherwise preserve permissions, making sure the group matches.
!            */
            if (mch_stat((char *)tempname, &tmp_st) >= 0)
            {
                if (st_old.st_uid != tmp_st.st_uid)
--- 3195,3202 ----
        {
                stat_T  tmp_st;
  
!           // Make sure the original owner can read/write the tempfile and
!           // otherwise preserve permissions, making sure the group matches.
            if (mch_stat((char *)tempname, &tmp_st) >= 0)
            {
                if (st_old.st_uid != tmp_st.st_uid)
***************
*** 3222,3230 ****
  #endif
      }
  
!     /*
!      * Check if the new viminfo file can be written to.
!      */
      if (fp_out == NULL)
      {
        semsg(_("E138: Can't write viminfo file %s!"),
--- 3216,3222 ----
  #endif
      }
  
!     // Check if the new viminfo file can be written to.
      if (fp_out == NULL)
      {
        semsg(_("E138: Can't write viminfo file %s!"),
*** ../vim-8.1.2125/src/version.c       2019-10-08 23:26:46.746003980 +0200
--- src/version.c       2019-10-09 21:56:32.526017815 +0200
***************
*** 755,756 ****
--- 755,758 ----
  {   /* Add new patch number below this line */
+ /**/
+     2126,
  /**/

-- 
User:       I'm having problems with my text editor.
Help desk:  Which editor are you using?
User:       I don't know, but it's version VI (pronounced: 6).
Help desk:  Oh, then you should upgrade to version VIM (pronounced: 994).

 /// Bram Moolenaar -- b...@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    ///

-- 
-- 
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 vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/201910092002.x99K21iW022706%40masaka.moolenaar.net.

Raspunde prin e-mail lui