To: vim_dev@googlegroups.com Subject: Patch 8.1.2126 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 -- Bram@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 ///