mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.1.2126: viminfo not sufficiently tested
Problem: Viminfo not sufficiently tested. Solution: Add more test cases. Clean up comments. (Yegappan Lakshmanan, closes #5032)
This commit is contained in:
@@ -5783,12 +5783,18 @@ show_pat_in_path(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_VIMINFO
|
#ifdef FEAT_VIMINFO
|
||||||
|
/*
|
||||||
|
* Return the last used search pattern at "idx".
|
||||||
|
*/
|
||||||
spat_T *
|
spat_T *
|
||||||
get_spat(int idx)
|
get_spat(int idx)
|
||||||
{
|
{
|
||||||
return &spats[idx];
|
return &spats[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the last used search pattern index.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
get_spat_last_idx(void)
|
get_spat_last_idx(void)
|
||||||
{
|
{
|
||||||
|
@@ -1133,18 +1133,6 @@ typedef struct
|
|||||||
int vc_fail; // fail for invalid char, don't use '?'
|
int vc_fail; // fail for invalid char, don't use '?'
|
||||||
} vimconv_T;
|
} 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.
|
* Structure used for the command line history.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
" Test for reading and writing .viminfo
|
" Test for reading and writing .viminfo
|
||||||
|
|
||||||
|
source check.vim
|
||||||
|
|
||||||
function Test_viminfo_read_and_write()
|
function Test_viminfo_read_and_write()
|
||||||
" First clear 'history', so that "hislen" is zero. Then set it again,
|
" First clear 'history', so that "hislen" is zero. Then set it again,
|
||||||
" simulating Vim starting up.
|
" simulating Vim starting up.
|
||||||
@@ -715,26 +717,78 @@ func Test_viminfo_large_register()
|
|||||||
rviminfo! Xviminfo
|
rviminfo! Xviminfo
|
||||||
call assert_equal(join(repeat(["sun is rising"], 200), "\n"), @r)
|
call assert_equal(join(repeat(["sun is rising"], 200), "\n"), @r)
|
||||||
call delete('Xviminfo')
|
call delete('Xviminfo')
|
||||||
|
let @r = ''
|
||||||
let &viminfo = save_viminfo
|
let &viminfo = save_viminfo
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Test for setting 'viminfofile' to NONE
|
" Test for setting 'viminfofile' to NONE
|
||||||
func Test_viminfofile_none()
|
func Test_viminfofile_none()
|
||||||
|
let save_vif = &viminfofile
|
||||||
set viminfofile=NONE
|
set viminfofile=NONE
|
||||||
wviminfo Xviminfo
|
wviminfo Xviminfo
|
||||||
call assert_false(filereadable('Xviminfo'))
|
call assert_false(filereadable('Xviminfo'))
|
||||||
call writefile([''], 'Xviminfo')
|
call writefile([''], 'Xviminfo')
|
||||||
call assert_fails('rviminfo Xviminfo', 'E195:')
|
call assert_fails('rviminfo Xviminfo', 'E195:')
|
||||||
call delete('Xviminfo')
|
call delete('Xviminfo')
|
||||||
|
let &viminfofile = save_vif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Test for an unwritable 'viminfo' file
|
" Test for an unwritable and unreadble 'viminfo' file
|
||||||
func Test_viminfo_readonly()
|
func Test_viminfo_perm()
|
||||||
if !has('unix')
|
CheckUnix
|
||||||
return
|
|
||||||
endif
|
|
||||||
call writefile([''], 'Xviminfo')
|
call writefile([''], 'Xviminfo')
|
||||||
call setfperm('Xviminfo', 'r-x------')
|
call setfperm('Xviminfo', 'r-x------')
|
||||||
call assert_fails('wviminfo Xviminfo', 'E137:')
|
call assert_fails('wviminfo Xviminfo', 'E137:')
|
||||||
|
call setfperm('Xviminfo', '--x------')
|
||||||
|
call assert_fails('rviminfo Xviminfo', 'E195:')
|
||||||
call delete('Xviminfo')
|
call delete('Xviminfo')
|
||||||
endfunc
|
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
|
||||||
|
@@ -753,6 +753,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2126,
|
||||||
/**/
|
/**/
|
||||||
2125,
|
2125,
|
||||||
/**/
|
/**/
|
||||||
|
106
src/viminfo.c
106
src/viminfo.c
@@ -14,6 +14,18 @@
|
|||||||
#include "vim.h"
|
#include "vim.h"
|
||||||
#include "version.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)
|
#if defined(FEAT_VIMINFO) || defined(PROTO)
|
||||||
|
|
||||||
static int viminfo_errcnt;
|
static int viminfo_errcnt;
|
||||||
@@ -822,11 +834,9 @@ write_viminfo_history(FILE *fp, int merge)
|
|||||||
if (num_saved > hislen)
|
if (num_saved > hislen)
|
||||||
num_saved = hislen;
|
num_saved = hislen;
|
||||||
|
|
||||||
/*
|
// Merge typed and viminfo history:
|
||||||
* Merge typed and viminfo history:
|
// round 1: history of typed commands.
|
||||||
* round 1: history of typed commands.
|
// round 2: history from recently read viminfo.
|
||||||
* round 2: history from recently read viminfo.
|
|
||||||
*/
|
|
||||||
for (round = 1; round <= 2; ++round)
|
for (round = 1; round <= 2; ++round)
|
||||||
{
|
{
|
||||||
if (round == 1)
|
if (round == 1)
|
||||||
@@ -2671,16 +2681,14 @@ read_viminfo_barline(vir_T *virp, int got_encoding, int force, int writing)
|
|||||||
int i;
|
int i;
|
||||||
int read_next = TRUE;
|
int read_next = TRUE;
|
||||||
|
|
||||||
/*
|
// The format is: |{bartype},{value},...
|
||||||
* The format is: |{bartype},{value},...
|
// For a very long string:
|
||||||
* For a very long string:
|
// |{bartype},>{length of "{text}{text2}"}
|
||||||
* |{bartype},>{length of "{text}{text2}"}
|
// |<{text1}
|
||||||
* |<{text1}
|
// |<{text2},{value}
|
||||||
* |<{text2},{value}
|
// For a long line not using a string
|
||||||
* For a long line not using a string
|
// |{bartype},{lots of values},>
|
||||||
* |{bartype},{lots of values},>
|
// |<{value},{value}
|
||||||
* |<{value},{value}
|
|
||||||
*/
|
|
||||||
if (*p == '<')
|
if (*p == '<')
|
||||||
{
|
{
|
||||||
// Continuation line of an unrecognized item.
|
// Continuation line of an unrecognized item.
|
||||||
@@ -3032,18 +3040,14 @@ write_viminfo(char_u *file, int forceit)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
// There is an existing viminfo file. Create a temporary file to
|
||||||
* There is an existing viminfo file. Create a temporary file to
|
// write the new viminfo into, in the same directory as the
|
||||||
* write the new viminfo into, in the same directory as the
|
// existing viminfo file, which will be renamed once all writing is
|
||||||
* existing viminfo file, which will be renamed once all writing is
|
// successful.
|
||||||
* successful.
|
|
||||||
*/
|
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
/*
|
// For Unix we check the owner of the file. It's not very nice to
|
||||||
* 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
|
||||||
* overwrite a user's viminfo file after a "su root", with a
|
// viminfo file that the user can't read.
|
||||||
* viminfo file that the user can't read.
|
|
||||||
*/
|
|
||||||
st_old.st_dev = (dev_t)0;
|
st_old.st_dev = (dev_t)0;
|
||||||
st_old.st_ino = 0;
|
st_old.st_ino = 0;
|
||||||
st_old.st_mode = 0600;
|
st_old.st_mode = 0600;
|
||||||
@@ -3069,14 +3073,12 @@ write_viminfo(char_u *file, int forceit)
|
|||||||
hidden = mch_ishidden(fname);
|
hidden = mch_ishidden(fname);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
// Make tempname, find one that does not exist yet.
|
||||||
* Make tempname, find one that does not exist yet.
|
// Beware of a race condition: If someone logs out and all Vim
|
||||||
* 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
|
||||||
* 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.
|
||||||
* stat() and open(). Use mch_open() with O_EXCL to avoid that.
|
// May try twice: Once normal and once with shortname set, just in
|
||||||
* May try twice: Once normal and once with shortname set, just in
|
// case somebody puts his viminfo file in an 8.3 filesystem.
|
||||||
* case somebody puts his viminfo file in an 8.3 filesystem.
|
|
||||||
*/
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int next_char = 'z';
|
int next_char = 'z';
|
||||||
@@ -3098,30 +3100,24 @@ write_viminfo(char_u *file, int forceit)
|
|||||||
if (tempname == NULL) // out of memory
|
if (tempname == NULL) // out of memory
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
// Try a series of names. Change one character, just before
|
||||||
* Try a series of names. Change one character, just before
|
// the extension. This should also work for an 8.3
|
||||||
* the extension. This should also work for an 8.3
|
// file name, when after adding the extension it still is
|
||||||
* file name, when after adding the extension it still is
|
// the same file as the original.
|
||||||
* the same file as the original.
|
|
||||||
*/
|
|
||||||
wp = tempname + STRLEN(tempname) - 5;
|
wp = tempname + STRLEN(tempname) - 5;
|
||||||
if (wp < gettail(tempname)) // empty file name?
|
if (wp < gettail(tempname)) // empty file name?
|
||||||
wp = gettail(tempname);
|
wp = gettail(tempname);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
/*
|
// Check if tempfile already exists. Never overwrite an
|
||||||
* Check if tempfile already exists. Never overwrite an
|
// existing file!
|
||||||
* existing file!
|
|
||||||
*/
|
|
||||||
if (mch_stat((char *)tempname, &st_new) == 0)
|
if (mch_stat((char *)tempname, &st_new) == 0)
|
||||||
{
|
{
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
/*
|
// Check if tempfile is same as original file. May happen
|
||||||
* Check if tempfile is same as original file. May happen
|
// when modname() gave the same file back. E.g. silly
|
||||||
* when modname() gave the same file back. E.g. silly
|
// link, or file name-length reached. Try again with
|
||||||
* link, or file name-length reached. Try again with
|
// shortname set.
|
||||||
* shortname set.
|
|
||||||
*/
|
|
||||||
if (!shortname && st_new.st_dev == st_old.st_dev
|
if (!shortname && st_new.st_dev == st_old.st_dev
|
||||||
&& st_new.st_ino == st_old.st_ino)
|
&& st_new.st_ino == st_old.st_ino)
|
||||||
{
|
{
|
||||||
@@ -3199,10 +3195,8 @@ write_viminfo(char_u *file, int forceit)
|
|||||||
{
|
{
|
||||||
stat_T tmp_st;
|
stat_T tmp_st;
|
||||||
|
|
||||||
/*
|
// Make sure the original owner can read/write the tempfile and
|
||||||
* Make sure the original owner can read/write the tempfile and
|
// otherwise preserve permissions, making sure the group matches.
|
||||||
* otherwise preserve permissions, making sure the group matches.
|
|
||||||
*/
|
|
||||||
if (mch_stat((char *)tempname, &tmp_st) >= 0)
|
if (mch_stat((char *)tempname, &tmp_st) >= 0)
|
||||||
{
|
{
|
||||||
if (st_old.st_uid != tmp_st.st_uid)
|
if (st_old.st_uid != tmp_st.st_uid)
|
||||||
@@ -3222,9 +3216,7 @@ write_viminfo(char_u *file, int forceit)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Check if the new viminfo file can be written to.
|
||||||
* Check if the new viminfo file can be written to.
|
|
||||||
*/
|
|
||||||
if (fp_out == NULL)
|
if (fp_out == NULL)
|
||||||
{
|
{
|
||||||
semsg(_("E138: Can't write viminfo file %s!"),
|
semsg(_("E138: Can't write viminfo file %s!"),
|
||||||
|
Reference in New Issue
Block a user