mirror of
https://github.com/neovim/neovim.git
synced 2026-09-03 21:00:34 +00:00
fix(cwd): E812 when a message opens a window during a file read #41458
Problem:
When ui2 is enabled, opening an already-open file in another Neovim
instance results in the error `E812: Autocommands changed buffer…`.
Analysis:
On E812 the file is not loaded. The default SwapExists handler notifies
`W325: Ignoring swapfile…`, and ui2 shows that message by opening
a window, which is a temp context switch. `ctx_dirs_restore()`
re-shortens every buffer name on the way out, and `shorten_buf_fname()`
always frees and reallocates `b_sfname`. `readfile()` aliases `b_fname`
across `check_need_swap()` and compares the pointer to detect a rename.
Regression by b296666e41, which replaced the `cs_save_sfname` restore
(that kept curbuf's pointer) with `shorten_fnames(true)`.
Solution:
Keep the allocation in `shorten_buf_fname()` when the short name is
unchanged. Pointer stability is what the E200/E201/E812 guards actually
assert.
This commit is contained in:
@@ -2366,22 +2366,28 @@ static char *check_for_bom(const char *p_in, int size, int *lenp, int flags)
|
||||
/// name.
|
||||
void shorten_buf_fname(buf_T *buf, char *dirname, int force)
|
||||
{
|
||||
if (buf->b_fname != NULL
|
||||
&& !bt_nofilename(buf)
|
||||
&& !path_with_url(buf->b_fname)
|
||||
&& (force
|
||||
|| buf->b_sfname == NULL
|
||||
|| path_is_absolute(buf->b_sfname))) {
|
||||
if (buf->b_sfname != buf->b_ffname) {
|
||||
XFREE_CLEAR(buf->b_sfname);
|
||||
}
|
||||
char *p = path_shorten_fname(buf->b_ffname, dirname);
|
||||
if (p != NULL && *p != NUL) {
|
||||
buf->b_sfname = xstrdup(p);
|
||||
buf->b_fname = buf->b_sfname;
|
||||
} else {
|
||||
buf->b_fname = buf->b_ffname;
|
||||
}
|
||||
if (buf->b_fname == NULL
|
||||
|| bt_nofilename(buf)
|
||||
|| path_with_url(buf->b_fname)
|
||||
|| !(force || buf->b_sfname == NULL || path_is_absolute(buf->b_sfname))) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *p = path_shorten_fname(buf->b_ffname, dirname);
|
||||
if (p != NULL && *p != NUL && buf->b_sfname != NULL && strcmp(p, buf->b_sfname) == 0) {
|
||||
// Same name: keep the allocation. Callers (readfile()) alias `b_fname` across autocommands and
|
||||
// check the pointer to detect a rename. Very cool... #41454
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf->b_sfname != buf->b_ffname) {
|
||||
XFREE_CLEAR(buf->b_sfname);
|
||||
}
|
||||
if (p != NULL && *p != NUL) {
|
||||
buf->b_sfname = xstrdup(p);
|
||||
buf->b_fname = buf->b_sfname;
|
||||
} else {
|
||||
buf->b_fname = buf->b_ffname;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user