diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/buffer.c | 8 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 8 | ||||
-rw-r--r-- | src/nvim/fileio.c | 24 | ||||
-rw-r--r-- | src/nvim/testdir/check.vim | 24 | ||||
-rw-r--r-- | src/nvim/testdir/test_edit.vim | 27 | ||||
-rw-r--r-- | src/nvim/testdir/test_undo.vim | 39 | ||||
-rw-r--r-- | src/nvim/undo.c | 7 |
7 files changed, 124 insertions, 13 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 174f6e94a9..2811a2da12 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1531,10 +1531,10 @@ Integer nvim_buf_add_highlight(Buffer buffer, end_line++; } - ns_id = extmark_set(buf, ns_id, 0, - (int)line, (colnr_T)col_start, - end_line, (colnr_T)col_end, - decoration_hl(hl_id), kExtmarkNoUndo); + extmark_set(buf, ns_id, 0, + (int)line, (colnr_T)col_start, + end_line, (colnr_T)col_end, + decoration_hl(hl_id), kExtmarkNoUndo); return src_id; } diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 9be6adcd61..bb4e92efc0 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2497,8 +2497,12 @@ int do_ecmd( new_name = NULL; } set_bufref(&bufref, buf); - if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) { - // Save all the text, so that the reload can be undone. + + // If the buffer was used before, store the current contents so that + // the reload can be undone. Do not do this if the (empty) buffer is + // being re-used for another file. + if (!(curbuf->b_flags & BF_NEVERLOADED) + && (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur)) { // Sync first so that this is a separate undo-able action. u_sync(false); if (u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, true) diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index ed8b72e2be..521d5c9deb 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -350,6 +350,7 @@ readfile( char_u *old_b_fname; int using_b_ffname; int using_b_fname; + static char *msg_is_a_directory = N_("is a directory"); au_did_filetype = false; // reset before triggering any autocommands @@ -444,16 +445,27 @@ readfile( else msg_scroll = TRUE; /* don't overwrite previous file message */ - /* - * If the name is too long we might crash further on, quit here. - */ + // If the name is too long we might crash further on, quit here. if (fname != NULL && *fname != NUL) { - if (STRLEN(fname) >= MAXPATHL) { + size_t namelen = STRLEN(fname); + + // If the name is too long we might crash further on, quit here. + if (namelen >= MAXPATHL) { filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0); msg_end(); msg_scroll = msg_save; return FAIL; } + + // If the name ends in a path separator, we can't open it. Check here, + // because reading the file may actually work, but then creating the + // swap file may destroy it! Reported on MS-DOS and Win 95. + if (after_pathsep((const char *)fname, (const char *)(fname + namelen))) { + filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0); + msg_end(); + msg_scroll = msg_save; + return FAIL; + } } if (!read_buffer && !read_stdin && !read_fifo) { @@ -474,7 +486,7 @@ readfile( # endif ) { if (S_ISDIR(perm)) { - filemess(curbuf, fname, (char_u *)_("is a directory"), 0); + filemess(curbuf, fname, (char_u *)_(msg_is_a_directory), 0); } else { filemess(curbuf, fname, (char_u *)_("is not a file"), 0); } @@ -544,7 +556,7 @@ readfile( #ifndef UNIX // On non-unix systems we can't open a directory, check here. if (os_isdir(fname)) { - filemess(curbuf, sfname, (char_u *)_("is a directory"), 0); + filemess(curbuf, sfname, (char_u *)_(msg_is_a_directory), 0); curbuf->b_p_ro = true; // must use "w!" now } else { #endif diff --git a/src/nvim/testdir/check.vim b/src/nvim/testdir/check.vim index e0ebe8fd49..7f6b7dcfec 100644 --- a/src/nvim/testdir/check.vim +++ b/src/nvim/testdir/check.vim @@ -25,6 +25,14 @@ func CheckFunction(name) endif endfunc +" Command to check for the presence of python. Argument should have been +" obtained with PythonProg() +func CheckPython(name) + if a:name == '' + throw 'Skipped: python command not available' + endif +endfunc + " Command to check for running on MS-Windows command CheckMSWindows call CheckMSWindows() func CheckMSWindows() @@ -73,3 +81,19 @@ func CheckNotGui() throw 'Skipped: only works in the terminal' endif endfunc + +" Command to check that the current language is English +command CheckEnglish call CheckEnglish() +func CheckEnglish() + if v:lang != "C" && v:lang !~ '^[Ee]n' + throw 'Skipped: only works in English language environment' + endif +endfunc + +" Command to check for NOT running on MS-Windows +command CheckNotMSWindows call CheckNotMSWindows() +func CheckNotMSWindows() + if has('win32') + throw 'Skipped: does not work on MS-Windows' + endif +endfunc diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim index 7f456ffbce..97a8ad25a3 100644 --- a/src/nvim/testdir/test_edit.vim +++ b/src/nvim/testdir/test_edit.vim @@ -1534,3 +1534,30 @@ func Test_edit_noesckeys() bwipe! " set esckeys endfunc + +" Test for editing a directory +" Todo: "is a directory" message is not displayed in Windows. +func Test_edit_is_a_directory() + CheckEnglish + CheckNotMSWindows + let dirname = getcwd() . "/Xdir" + call mkdir(dirname, 'p') + + new + redir => msg + exe 'edit' dirname + redir END + call assert_match("is a directory$", split(msg, "\n")[0]) + bwipe! + + let dirname .= '/' + + new + redir => msg + exe 'edit' dirname + redir END + call assert_match("is a directory$", split(msg, "\n")[0]) + bwipe! + + call delete(dirname, 'rf') +endfunc diff --git a/src/nvim/testdir/test_undo.vim b/src/nvim/testdir/test_undo.vim index adcdcb1cd9..3b66071d6d 100644 --- a/src/nvim/testdir/test_undo.vim +++ b/src/nvim/testdir/test_undo.vim @@ -364,6 +364,25 @@ func Test_wundo_errors() bwipe! endfunc +" Check that reading a truncted undo file doesn't hang. +func Test_undofile_truncated() + throw 'skipped: TODO: ' + new + call setline(1, 'hello') + set ul=100 + wundo Xundofile + let contents = readfile('Xundofile', 'B') + + " try several sizes + for size in range(20, 500, 33) + call writefile(contents[0:size], 'Xundofile') + call assert_fails('rundo Xundofile', 'E825:') + endfor + + bwipe! + call delete('Xundofile') +endfunc + func Test_rundo_errors() call assert_fails('rundo XfileDoesNotExist', 'E822:') @@ -373,6 +392,26 @@ func Test_rundo_errors() call delete('Xundofile') endfunc +func Test_undofile_next() + set undofile + new Xfoo.txt + execute "norm ix\<c-g>uy\<c-g>uz\<Esc>" + write + bwipe + + next Xfoo.txt + call assert_equal('xyz', getline(1)) + silent undo + call assert_equal('xy', getline(1)) + silent undo + call assert_equal('x', getline(1)) + bwipe! + + call delete('Xfoo.txt') + call delete('.Xfoo.txt.un~') + set undofile& +endfunc + " Test for undo working properly when executing commands from a register. " Also test this in an empty buffer. func Test_cmd_in_reg_undo() diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 903e57732f..6c5a6cdb46 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -878,7 +878,12 @@ static u_header_T *unserialize_uhp(bufinfo_T *bi, for (;; ) { int len = undo_read_byte(bi); - if (len == 0 || len == EOF) { + if (len == EOF) { + corruption_error("truncated", file_name); + u_free_uhp(uhp); + return NULL; + } + if (len == 0) { break; } int what = undo_read_byte(bi); |