Skip to content

Commit c915504

Browse files
committed
fix(file): Race condition during buffer creation (fixes sindrets#380)
Problem: If there are two or more file instances for the same rev, and one of them get destroyed while another is still waiting for the VCS adapter to provide the file content, we get an error once the waiting instance tries to use the now deleted buffer. Solution: Revalidate buffer after data is resolved.
1 parent 0ad3e4f commit c915504

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

lua/diffview/vcs/file.lua

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -237,16 +237,21 @@ File.create_buffer = async.wrap(function(self, callback)
237237
return
238238
end
239239

240+
-- Create buffer and set name *before* calling `produce_data()` to ensure
241+
-- that multiple file instances won't ever try to create the same file.
240242
self.bufnr = api.nvim_create_buf(false, false)
241-
local bufopts = vim.deepcopy(File.bufopts)
242-
243243
api.nvim_buf_set_name(self.bufnr, fullname)
244244

245245
local err, lines = await(self:produce_data())
246246
if err then error(table.concat(err, "\n")) end
247247

248248
await(async.scheduler())
249249

250+
-- Revalidate buffer in case the file was destroyed before `produce_data()`
251+
-- returned.
252+
if not api.nvim_buf_is_valid(self.bufnr) then return end
253+
local bufopts = vim.deepcopy(File.bufopts)
254+
250255
if self.rev.type == RevType.STAGE and self.rev.stage == 0 then
251256
self.blob_hash = self.adapter:file_blob_hash(self.path)
252257
bufopts.modifiable = true
@@ -267,21 +272,19 @@ File.create_buffer = async.wrap(function(self, callback)
267272
api.nvim_buf_set_option(self.bufnr, option, value)
268273
end
269274

270-
if api.nvim_buf_is_valid(self.bufnr) then
271-
local last_modifiable = vim.bo[self.bufnr].modifiable
272-
local last_modified = vim.bo[self.bufnr].modified
273-
vim.bo[self.bufnr].modifiable = true
274-
api.nvim_buf_set_lines(self.bufnr, 0, -1, false, lines)
275+
local last_modifiable = vim.bo[self.bufnr].modifiable
276+
local last_modified = vim.bo[self.bufnr].modified
277+
vim.bo[self.bufnr].modifiable = true
278+
api.nvim_buf_set_lines(self.bufnr, 0, -1, false, lines)
275279

276-
api.nvim_buf_call(self.bufnr, function()
277-
vim.cmd("filetype detect")
278-
end)
280+
api.nvim_buf_call(self.bufnr, function()
281+
vim.cmd("filetype detect")
282+
end)
279283

280-
vim.bo[self.bufnr].modifiable = last_modifiable
281-
vim.bo[self.bufnr].modified = last_modified
282-
self:post_buf_created()
283-
callback(self.bufnr)
284-
end
284+
vim.bo[self.bufnr].modifiable = last_modifiable
285+
vim.bo[self.bufnr].modified = last_modified
286+
self:post_buf_created()
287+
callback(self.bufnr)
285288
---@diagnostic enable: invisible
286289
end)
287290

0 commit comments

Comments
 (0)