mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.2.0004: get E685 and E931 if buffer reload is interrupted
Problem: Get E685 and E931 if buffer reload is interrupted.
Solution: Do not abort deleting a dummy buffer. (closes vim/vim#5361)
a6e8f888e7
This commit is contained in:
parent
8f3245dbfa
commit
44b59d1a69
@ -174,7 +174,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags)
|
||||
if (ml_open(curbuf) == FAIL) {
|
||||
// There MUST be a memfile, otherwise we can't do anything
|
||||
// If we can't create one for the current buffer, take another buffer
|
||||
close_buffer(NULL, curbuf, 0, false);
|
||||
close_buffer(NULL, curbuf, 0, false, false);
|
||||
|
||||
curbuf = NULL;
|
||||
FOR_ALL_BUFFERS(buf) {
|
||||
@ -402,8 +402,10 @@ bool buf_valid(buf_T *buf)
|
||||
/// there to be only one window with this buffer. e.g. when
|
||||
/// ":quit" is supposed to close the window but autocommands
|
||||
/// close all other windows.
|
||||
/// @param ignore_abort
|
||||
/// If true, don't abort even when aborting() returns true.
|
||||
/// @return true when we got to the end and b_nwindows was decremented.
|
||||
bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
|
||||
bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool ignore_abort)
|
||||
{
|
||||
bool unload_buf = (action != 0);
|
||||
bool del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE);
|
||||
@ -494,7 +496,8 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (aborting()) { // autocmds may abort script processing
|
||||
// autocmds may abort script processing
|
||||
if (!ignore_abort && aborting()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -552,14 +555,16 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
|
||||
|
||||
buf->b_nwindows = nwindows;
|
||||
|
||||
buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0));
|
||||
buf_freeall(buf, ((del_buf ? BFA_DEL : 0)
|
||||
+ (wipe_buf ? BFA_WIPE : 0)
|
||||
+ (ignore_abort ? BFA_IGNORE_ABORT : 0)));
|
||||
|
||||
if (!bufref_valid(&bufref)) {
|
||||
// Autocommands may have deleted the buffer.
|
||||
return false;
|
||||
}
|
||||
if (aborting()) {
|
||||
// Autocmds may abort script processing.
|
||||
// autocmds may abort script processing.
|
||||
if (!ignore_abort && aborting()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -660,9 +665,10 @@ void buf_clear(void)
|
||||
/// buf_freeall() - free all things allocated for a buffer that are related to
|
||||
/// the file. Careful: get here with "curwin" NULL when exiting.
|
||||
///
|
||||
/// @param flags BFA_DEL buffer is going to be deleted
|
||||
/// BFA_WIPE buffer is going to be wiped out
|
||||
/// BFA_KEEP_UNDO do not free undo information
|
||||
/// @param flags BFA_DEL buffer is going to be deleted
|
||||
/// BFA_WIPE buffer is going to be wiped out
|
||||
/// BFA_KEEP_UNDO do not free undo information
|
||||
/// BFA_IGNORE_ABORT don't abort even when aborting() returns true
|
||||
void buf_freeall(buf_T *buf, int flags)
|
||||
{
|
||||
bool is_curbuf = (buf == curbuf);
|
||||
@ -706,7 +712,8 @@ void buf_freeall(buf_T *buf, int flags)
|
||||
goto_tabpage_win(the_curtab, the_curwin);
|
||||
unblock_autocmds();
|
||||
}
|
||||
if (aborting()) { // autocmds may abort script processing
|
||||
// autocmds may abort script processing
|
||||
if ((flags & BFA_IGNORE_ABORT) == 0 && aborting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -877,7 +884,7 @@ void handle_swap_exists(bufref_T *old_curbuf)
|
||||
// open a new, empty buffer.
|
||||
swap_exists_action = SEA_NONE; // don't want it again
|
||||
swap_exists_did_quit = true;
|
||||
close_buffer(curwin, curbuf, DOBUF_UNLOAD, false);
|
||||
close_buffer(curwin, curbuf, DOBUF_UNLOAD, false, false);
|
||||
if (old_curbuf == NULL
|
||||
|| !bufref_valid(old_curbuf)
|
||||
|| old_curbuf->br_buf == curbuf) {
|
||||
@ -1074,7 +1081,7 @@ static int empty_curbuf(int close_others, int forceit, int action)
|
||||
// the old one. But do_ecmd() may have done that already, check
|
||||
// if the buffer still exists.
|
||||
if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows == 0) {
|
||||
close_buffer(NULL, buf, action, false);
|
||||
close_buffer(NULL, buf, action, false, false);
|
||||
}
|
||||
|
||||
if (!close_others) {
|
||||
@ -1259,7 +1266,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
|
||||
if (buf != curbuf) {
|
||||
close_windows(buf, false);
|
||||
if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows <= 0) {
|
||||
close_buffer(NULL, buf, action, false);
|
||||
close_buffer(NULL, buf, action, false, false);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
@ -1485,7 +1492,7 @@ void set_curbuf(buf_T *buf, int action)
|
||||
? action
|
||||
: (action == DOBUF_GOTO && !buf_hide(prevbuf)
|
||||
&& !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0,
|
||||
false);
|
||||
false, false);
|
||||
if (curwin != previouswin && win_valid(previouswin)) {
|
||||
// autocommands changed curwin, Grr!
|
||||
curwin = previouswin;
|
||||
@ -2805,7 +2812,7 @@ int setfname(buf_T *buf, char_u *ffname_arg, char_u *sfname_arg, bool message)
|
||||
return FAIL;
|
||||
}
|
||||
// delete from the list
|
||||
close_buffer(NULL, obuf, DOBUF_WIPE, false);
|
||||
close_buffer(NULL, obuf, DOBUF_WIPE, false, false);
|
||||
}
|
||||
sfname = vim_strsave(sfname);
|
||||
#ifdef USE_FNAME_CASE
|
||||
@ -5650,7 +5657,7 @@ void wipe_buffer(buf_T *buf, bool aucmd)
|
||||
// Don't trigger BufDelete autocommands here.
|
||||
block_autocmds();
|
||||
}
|
||||
close_buffer(NULL, buf, DOBUF_WIPE, false);
|
||||
close_buffer(NULL, buf, DOBUF_WIPE, false, true);
|
||||
if (!aucmd) {
|
||||
unblock_autocmds();
|
||||
}
|
||||
|
@ -58,9 +58,10 @@ enum dobuf_start_values {
|
||||
|
||||
// flags for buf_freeall()
|
||||
enum bfa_values {
|
||||
BFA_DEL = 1, // buffer is going to be deleted
|
||||
BFA_WIPE = 2, // buffer is going to be wiped out
|
||||
BFA_KEEP_UNDO = 4, // do not free undo information
|
||||
BFA_DEL = 1, // buffer is going to be deleted
|
||||
BFA_WIPE = 2, // buffer is going to be wiped out
|
||||
BFA_KEEP_UNDO = 4, // do not free undo information
|
||||
BFA_IGNORE_ABORT = 8, // do not abort for aborting()
|
||||
};
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
|
@ -2527,9 +2527,9 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
|
||||
// Close the link to the current buffer. This will set
|
||||
// oldwin->w_buffer to NULL.
|
||||
u_sync(false);
|
||||
const bool did_decrement = close_buffer(oldwin, curbuf,
|
||||
(flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD,
|
||||
false);
|
||||
const bool did_decrement
|
||||
= close_buffer(oldwin, curbuf, (flags & ECMD_HIDE) || curbuf->terminal ? 0 : DOBUF_UNLOAD,
|
||||
false, false);
|
||||
|
||||
// Autocommands may have closed the window.
|
||||
if (win_valid(the_curwin)) {
|
||||
|
@ -6544,7 +6544,7 @@ static int open_cmdwin(void)
|
||||
// win_close() may have already wiped the buffer when 'bh' is
|
||||
// set to 'wipe', autocommands may have closed other windows
|
||||
if (bufref_valid(&bufref) && bufref.br_buf != curbuf) {
|
||||
close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, false);
|
||||
close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, false, false);
|
||||
}
|
||||
|
||||
// Restore window sizes.
|
||||
|
@ -691,7 +691,7 @@ void free_all_mem(void)
|
||||
bufref_T bufref;
|
||||
set_bufref(&bufref, buf);
|
||||
nextbuf = buf->b_next;
|
||||
close_buffer(NULL, buf, DOBUF_WIPE, false);
|
||||
close_buffer(NULL, buf, DOBUF_WIPE, false, false);
|
||||
// Didn't work, try next one.
|
||||
buf = bufref_valid(&bufref) ? nextbuf : firstbuf;
|
||||
}
|
||||
|
@ -1721,7 +1721,7 @@ static void wipe_qf_buffer(qf_info_T *qi)
|
||||
if (qfbuf != NULL && qfbuf->b_nwindows == 0) {
|
||||
// If the quickfix buffer is not loaded in any window, then
|
||||
// wipe the buffer.
|
||||
close_buffer(NULL, qfbuf, DOBUF_WIPE, false);
|
||||
close_buffer(NULL, qfbuf, DOBUF_WIPE, false, false);
|
||||
qi->qf_bufnr = INVALID_QFBUFNR;
|
||||
}
|
||||
}
|
||||
@ -5843,7 +5843,7 @@ static void wipe_dummy_buffer(buf_T *buf, char_u *dirname_start)
|
||||
static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start)
|
||||
{
|
||||
if (curbuf != buf) { // safety check
|
||||
close_buffer(NULL, buf, DOBUF_UNLOAD, false);
|
||||
close_buffer(NULL, buf, DOBUF_UNLOAD, false, true);
|
||||
|
||||
// When autocommands/'autochdir' option changed directory: go back.
|
||||
restore_start_dir(dirname_start);
|
||||
|
@ -1972,6 +1972,29 @@ func Test_builtin_func_error()
|
||||
call assert_equal('jlmnpqrtueghivyzACD', g:Xpath)
|
||||
endfunc
|
||||
|
||||
" Modelines {{{1
|
||||
func Test_reload_in_try_catch()
|
||||
call writefile(['x'], 'Xreload')
|
||||
set autoread
|
||||
edit Xreload
|
||||
tabnew
|
||||
call writefile(['xx'], 'Xreload')
|
||||
augroup ReLoad
|
||||
au FileReadPost Xreload let x = doesnotexist
|
||||
au BufReadPost Xreload let x = doesnotexist
|
||||
augroup END
|
||||
try
|
||||
edit Xreload
|
||||
catch
|
||||
endtry
|
||||
tabnew
|
||||
|
||||
tabclose
|
||||
tabclose
|
||||
autocmd! ReLoad
|
||||
set noautoread
|
||||
bwipe! Xreload
|
||||
call delete('Xreload')
|
||||
endfunc
|
||||
|
||||
" Modeline {{{1
|
||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||
"-------------------------------------------------------------------------------
|
||||
|
@ -2563,7 +2563,7 @@ static void win_close_buffer(win_T *win, bool free_buf, bool abort_if_last)
|
||||
bufref_T bufref;
|
||||
set_bufref(&bufref, curbuf);
|
||||
win->w_closing = true;
|
||||
close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, abort_if_last);
|
||||
close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, abort_if_last, false);
|
||||
if (win_valid_any_tab(win)) {
|
||||
win->w_closing = false;
|
||||
}
|
||||
@ -2885,7 +2885,7 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
|
||||
|
||||
if (win->w_buffer != NULL) {
|
||||
// Close the link to the buffer.
|
||||
close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, false);
|
||||
close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, false, false);
|
||||
}
|
||||
|
||||
// Careful: Autocommands may have closed the tab page or made it the
|
||||
|
@ -17,8 +17,8 @@ describe('buffer functions', function()
|
||||
return buffer.buflist_new(c_file, c_file, 1, flags)
|
||||
end
|
||||
|
||||
local close_buffer = function(win, buf, action, abort_if_last)
|
||||
return buffer.close_buffer(win, buf, action, abort_if_last)
|
||||
local close_buffer = function(win, buf, action, abort_if_last, ignore_abort)
|
||||
return buffer.close_buffer(win, buf, action, abort_if_last, ignore_abort)
|
||||
end
|
||||
|
||||
local path1 = 'test_file_path'
|
||||
@ -53,7 +53,7 @@ describe('buffer functions', function()
|
||||
itp('should view a closed and hidden buffer as valid', function()
|
||||
local buf = buflist_new(path1, buffer.BLN_LISTED)
|
||||
|
||||
close_buffer(NULL, buf, 0, 0)
|
||||
close_buffer(NULL, buf, 0, 0, 0)
|
||||
|
||||
eq(true, buffer.buf_valid(buf))
|
||||
end)
|
||||
@ -61,7 +61,7 @@ describe('buffer functions', function()
|
||||
itp('should view a closed and unloaded buffer as valid', function()
|
||||
local buf = buflist_new(path1, buffer.BLN_LISTED)
|
||||
|
||||
close_buffer(NULL, buf, buffer.DOBUF_UNLOAD, 0)
|
||||
close_buffer(NULL, buf, buffer.DOBUF_UNLOAD, 0, 0)
|
||||
|
||||
eq(true, buffer.buf_valid(buf))
|
||||
end)
|
||||
@ -69,7 +69,7 @@ describe('buffer functions', function()
|
||||
itp('should view a closed and wiped buffer as invalid', function()
|
||||
local buf = buflist_new(path1, buffer.BLN_LISTED)
|
||||
|
||||
close_buffer(NULL, buf, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf, buffer.DOBUF_WIPE, 0, 0)
|
||||
|
||||
eq(false, buffer.buf_valid(buf))
|
||||
end)
|
||||
@ -90,7 +90,7 @@ describe('buffer functions', function()
|
||||
|
||||
eq(buf.handle, buflist_findpat(path1, ONLY_LISTED))
|
||||
|
||||
close_buffer(NULL, buf, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf, buffer.DOBUF_WIPE, 0, 0)
|
||||
end)
|
||||
|
||||
itp('should prefer to match the start of a file path', function()
|
||||
@ -102,9 +102,9 @@ describe('buffer functions', function()
|
||||
eq(buf2.handle, buflist_findpat("file", ONLY_LISTED))
|
||||
eq(buf3.handle, buflist_findpat("path", ONLY_LISTED))
|
||||
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0, 0)
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0, 0)
|
||||
end)
|
||||
|
||||
itp('should prefer to match the end of a file over the middle', function()
|
||||
@ -118,7 +118,7 @@ describe('buffer functions', function()
|
||||
--}
|
||||
|
||||
--{ When: We close buf2
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0, 0)
|
||||
|
||||
-- And: Open buf1, which has 'file' in the middle of its name
|
||||
local buf1 = buflist_new(path1, buffer.BLN_LISTED)
|
||||
@ -127,8 +127,8 @@ describe('buffer functions', function()
|
||||
eq(buf3.handle, buflist_findpat("file", ONLY_LISTED))
|
||||
--}
|
||||
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0, 0)
|
||||
end)
|
||||
|
||||
itp('should match a unique fragment of a file path', function()
|
||||
@ -138,9 +138,9 @@ describe('buffer functions', function()
|
||||
|
||||
eq(buf3.handle, buflist_findpat("_test_", ONLY_LISTED))
|
||||
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0, 0)
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0, 0)
|
||||
end)
|
||||
|
||||
itp('should include / ignore unlisted buffers based on the flag.', function()
|
||||
@ -152,7 +152,7 @@ describe('buffer functions', function()
|
||||
--}
|
||||
|
||||
--{ When: We unlist the buffer
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_DEL, 0)
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_DEL, 0, 0)
|
||||
|
||||
-- Then: It should not find the buffer when searching only listed buffers
|
||||
eq(-1, buflist_findpat("_test_", ONLY_LISTED))
|
||||
@ -162,7 +162,7 @@ describe('buffer functions', function()
|
||||
--}
|
||||
|
||||
--{ When: We wipe the buffer
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0, 0)
|
||||
|
||||
-- Then: It should not find the buffer at all
|
||||
eq(-1, buflist_findpat("_test_", ONLY_LISTED))
|
||||
@ -180,7 +180,7 @@ describe('buffer functions', function()
|
||||
--}
|
||||
|
||||
--{ When: The first buffer is unlisted
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_DEL, 0)
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_DEL, 0, 0)
|
||||
|
||||
-- Then: The second buffer is preferred because
|
||||
-- unlisted buffers are not allowed
|
||||
@ -194,7 +194,7 @@ describe('buffer functions', function()
|
||||
--}
|
||||
|
||||
--{ When: We unlist the second buffer
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_DEL, 0)
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_DEL, 0, 0)
|
||||
|
||||
-- Then: The first buffer is preferred again
|
||||
-- because buf1 matches better which takes precedence
|
||||
@ -205,8 +205,8 @@ describe('buffer functions', function()
|
||||
eq(-1, buflist_findpat("test", ONLY_LISTED))
|
||||
--}
|
||||
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0)
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0, 0)
|
||||
end)
|
||||
end)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user