aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-04-07 21:46:07 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-04-08 08:54:07 +0800
commit44b59d1a696b35d2520dbea2de3aab01e740a7ca (patch)
treeaaaf5fc54edfdb48fe0fbb3fed400a7d9864bc65
parent8f3245dbfa91d384215c78da32e4d1739c8a1f34 (diff)
downloadrneovim-44b59d1a696b35d2520dbea2de3aab01e740a7ca.tar.gz
rneovim-44b59d1a696b35d2520dbea2de3aab01e740a7ca.tar.bz2
rneovim-44b59d1a696b35d2520dbea2de3aab01e740a7ca.zip
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) https://github.com/vim/vim/commit/a6e8f888e7fc31b8ab7233509254fb2e2fe4089f
-rw-r--r--src/nvim/buffer.c39
-rw-r--r--src/nvim/buffer.h7
-rw-r--r--src/nvim/ex_cmds.c6
-rw-r--r--src/nvim/ex_getln.c2
-rw-r--r--src/nvim/memory.c2
-rw-r--r--src/nvim/quickfix.c4
-rw-r--r--src/nvim/testdir/test_trycatch.vim27
-rw-r--r--src/nvim/window.c4
-rw-r--r--test/unit/buffer_spec.lua42
9 files changed, 82 insertions, 51 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index bf592a626d..4ec23244cd 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -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();
}
diff --git a/src/nvim/buffer.h b/src/nvim/buffer.h
index 850ab175a5..7f4bbcc9e5 100644
--- a/src/nvim/buffer.h
+++ b/src/nvim/buffer.h
@@ -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
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 5d5b342c35..4e98319723 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -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)) {
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 9104a2dd5a..dd6e4630d2 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -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.
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index 6cdc4f1fde..c895cc1ec6 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -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;
}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 1d589e8ca0..4ad5e40fee 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -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);
diff --git a/src/nvim/testdir/test_trycatch.vim b/src/nvim/testdir/test_trycatch.vim
index 7e513180a3..adc1745b39 100644
--- a/src/nvim/testdir/test_trycatch.vim
+++ b/src/nvim/testdir/test_trycatch.vim
@@ -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
-"-------------------------------------------------------------------------------
diff --git a/src/nvim/window.c b/src/nvim/window.c
index e471c0b304..20f2447bbe 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -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
diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua
index 34c88248e6..833b21b00b 100644
--- a/test/unit/buffer_spec.lua
+++ b/test/unit/buffer_spec.lua
@@ -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)