fix: new oil buffers are nomodifiable during mutation processing

This commit is contained in:
Steven Arcangeli 2023-03-28 11:39:27 -07:00
parent 931453fc09
commit d631d9fc5a
3 changed files with 43 additions and 10 deletions

View file

@ -431,19 +431,24 @@ M.process_actions = function(actions, cb)
next_action() next_action()
end end
local mutation_in_progress = false
---@param confirm nil|boolean ---@param confirm nil|boolean
M.try_write_changes = function(confirm) M.try_write_changes = function(confirm)
if mutation_in_progress then
error("Cannot perform mutation when already in progress")
return
end
local current_buf = vim.api.nvim_get_current_buf() local current_buf = vim.api.nvim_get_current_buf()
local was_modified = vim.bo.modified local was_modified = vim.bo.modified
local buffers = view.get_all_buffers() local buffers = view.get_all_buffers()
local all_diffs = {} local all_diffs = {}
local all_errors = {} local all_errors = {}
local was_modifiable = {} mutation_in_progress = true
-- Lock the buffer to prevent race conditions from the user modifying them during parsing
view.lock_buffers()
for _, bufnr in ipairs(buffers) do for _, bufnr in ipairs(buffers) do
was_modifiable[bufnr] = vim.bo[bufnr].modifiable
-- Lock the buffer to prevent race conditions
vim.bo[bufnr].modifiable = false
if vim.bo[bufnr].modified then if vim.bo[bufnr].modified then
local diffs, errors = parser.parse(bufnr) local diffs, errors = parser.parse(bufnr)
all_diffs[bufnr] = diffs all_diffs[bufnr] = diffs
@ -453,13 +458,12 @@ M.try_write_changes = function(confirm)
end end
end end
local function unlock() local function unlock()
for _, bufnr in ipairs(buffers) do view.unlock_buffers()
pcall(vim.api.nvim_buf_set_option, bufnr, "modifiable", was_modifiable[bufnr])
end
-- The ":write" will set nomodified even if we cancel here, so we need to restore it -- The ":write" will set nomodified even if we cancel here, so we need to restore it
if was_modified then if was_modified then
vim.bo[current_buf].modified = true vim.bo[current_buf].modified = true
end end
mutation_in_progress = false
end end
local ns = vim.api.nvim_create_namespace("Oil") local ns = vim.api.nvim_create_namespace("Oil")
@ -500,8 +504,10 @@ M.try_write_changes = function(confirm)
M.process_actions( M.process_actions(
actions, actions,
vim.schedule_wrap(function(err) vim.schedule_wrap(function(err)
view.unlock_buffers()
if err then if err then
vim.notify(string.format("[oil] Error applying actions: %s", err), vim.log.levels.ERROR) vim.notify(string.format("[oil] Error applying actions: %s", err), vim.log.levels.ERROR)
view.rerender_all_oil_buffers({ preserve_undo = false })
else else
local current_entry = oil.get_cursor_entry() local current_entry = oil.get_cursor_entry()
if current_entry then if current_entry then
@ -513,6 +519,7 @@ M.try_write_changes = function(confirm)
end end
view.rerender_all_oil_buffers({ preserve_undo = M.trash }) view.rerender_all_oil_buffers({ preserve_undo = M.trash })
end end
mutation_in_progress = false
end) end)
) )
end) end)

View file

@ -69,7 +69,9 @@ function Progress:close()
self.timer = nil self.timer = nil
end end
if self.winid then if self.winid then
vim.api.nvim_win_close(self.winid, true) if vim.api.nvim_win_is_valid(self.winid) then
vim.api.nvim_win_close(self.winid, true)
end
self.winid = nil self.winid = nil
end end
end end

View file

@ -103,6 +103,30 @@ M.get_all_buffers = function()
return vim.tbl_filter(vim.api.nvim_buf_is_loaded, vim.tbl_keys(session)) return vim.tbl_filter(vim.api.nvim_buf_is_loaded, vim.tbl_keys(session))
end end
local buffers_locked = false
---Make all oil buffers nomodifiable
M.lock_buffers = function()
buffers_locked = true
for bufnr in pairs(session) do
if vim.api.nvim_buf_is_loaded(bufnr) then
vim.bo[bufnr].modifiable = false
end
end
end
---Restore normal modifiable settings for oil buffers
M.unlock_buffers = function()
buffers_locked = false
for bufnr in pairs(session) do
if vim.api.nvim_buf_is_loaded(bufnr) then
local adapter = util.get_adapter(bufnr)
if adapter then
vim.bo[bufnr].modifiable = adapter.is_modifiable(bufnr)
end
end
end
end
---@param opts table ---@param opts table
---@note ---@note
--- This DISCARDS ALL MODIFICATIONS a user has made to oil buffers --- This DISCARDS ALL MODIFICATIONS a user has made to oil buffers
@ -350,7 +374,7 @@ local function render_buffer(bufnr, opts)
}) })
local scheme = util.parse_url(bufname) local scheme = util.parse_url(bufname)
local adapter = util.get_adapter(bufnr) local adapter = util.get_adapter(bufnr)
if not adapter then if not scheme or not adapter then
return false return false
end end
local entries = cache.list_url(bufname) local entries = cache.list_url(bufname)
@ -539,7 +563,7 @@ M.render_buffer_async = function(bufnr, opts, callback)
if not preserve_undo then if not preserve_undo then
vim.bo[bufnr].undolevels = vim.api.nvim_get_option("undolevels") vim.bo[bufnr].undolevels = vim.api.nvim_get_option("undolevels")
end end
vim.bo[bufnr].modifiable = adapter.is_modifiable(bufnr) vim.bo[bufnr].modifiable = not buffers_locked and adapter.is_modifiable(bufnr)
if callback then if callback then
callback() callback()
end end