commit fcf752476a33a26058b3342ac09108f76801bd4b
parent 03032d1f73d8f1d26e6fd846354646cc68fa27a6
Author: glepnir <glephunter@gmail.com>
Date: Sun, 28 Sep 2025 11:28:05 +0800
fix(cmd): :update writes new file buffers only for real files #35939
Problem: :update should write new file buffers, but previous fix
affected special buffer types (acwrite, nofile, etc.).
Solution: Add bt_nofilename() check to only write new files for
buffers representing real filesystem paths.
Diffstat:
4 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt
@@ -989,7 +989,8 @@ slower (but safer).
*:up* *:update*
:[range]up[date][!] [++opt] [>>] [file]
Like ":write", but only write when the buffer has been
- modified.
+ modified, or when the buffer represents a new file
+ that doesn't exist on disk.
WRITING WITH MULTIPLE BUFFERS *buffer-write*
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
@@ -308,6 +308,7 @@ Commands:
- |:trust|
- User commands can support |:command-preview| to show results as you type
- |:write| with "++p" flag creates parent directories.
+- |:update| command writes new file buffers even when unmodified.
Editor:
- |prompt-buffer| supports multiline input/paste, undo/redo, and o/O normal
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
@@ -1772,7 +1772,9 @@ void ex_file(exarg_T *eap)
/// ":update".
void ex_update(exarg_T *eap)
{
- if (curbufIsChanged() || (curbuf->b_ffname != NULL && !os_path_exists(curbuf->b_ffname))) {
+ if (curbufIsChanged()
+ || (!bt_nofilename(curbuf) && curbuf->b_ffname != NULL
+ && !os_path_exists(curbuf->b_ffname))) {
do_write(eap);
}
}
diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua
@@ -258,4 +258,15 @@ describe(':update', function()
eq(1, eval('g:write_pre'))
eq(1, eval('g:write_post'))
end)
+
+ it('does not write acwrite buffer when unchanged', function()
+ command('file remote://test')
+ command('setlocal buftype=acwrite')
+ command('let g:triggered = 0 | autocmd BufWriteCmd remote://* let g:triggered = 1')
+ command('update')
+ eq(0, eval('g:triggered'))
+ command('call setline(1, ["hello"])')
+ command('update')
+ eq(1, eval('g:triggered'))
+ end)
end)