fix(blame): don't run concurrent blames

Fixes: #783
This commit is contained in:
Lewis Russell 2023-07-04 11:50:36 +01:00 committed by Lewis Russell
parent a36bc3360d
commit dc2962f7fc
1 changed files with 83 additions and 46 deletions

View File

@ -116,10 +116,78 @@ local function flatten_virt_text(virt_text)
return table.concat(res) return table.concat(res)
end end
local running = false
--- @param bufnr integer
--- @param lnum integer
--- @param opts Gitsigns.CurrentLineBlameOpts
--- @return Gitsigns.BlameInfo?
local function run_blame(bufnr, lnum, opts)
local result = BlameCache:get(bufnr, lnum)
if result then
return result
end
if running then
return
end
running = true
local buftext = util.buf_lines(bufnr)
local bcache = cache[bufnr]
result = bcache.git_obj:run_blame(buftext, lnum, opts.ignore_whitespace)
BlameCache:add(bufnr, lnum, result)
running = false
return result
end
--- @param bufnr integer
--- @param lnum integer
--- @param blame_info Gitsigns.BlameInfo
--- @param opts Gitsigns.CurrentLineBlameOpts
local function handle_blame_info(bufnr, lnum, blame_info, opts)
local bcache = cache[bufnr]
local virt_text ---@type {[1]: string, [2]: string}[]
local clb_formatter = blame_info.author == 'Not Committed Yet'
and config.current_line_blame_formatter_nc
or config.current_line_blame_formatter
if type(clb_formatter) == 'string' then
virt_text = {
{
expand_blame_format(clb_formatter, bcache.git_obj.repo.username, blame_info),
'GitSignsCurrentLineBlame',
},
}
else -- function
virt_text = clb_formatter(
bcache.git_obj.repo.username,
blame_info,
config.current_line_blame_formatter_opts
)
end
vim.b[bufnr].gitsigns_blame_line = flatten_virt_text(virt_text)
if opts.virt_text then
set_extmark(bufnr, lnum, {
virt_text = virt_text,
virt_text_pos = opts.virt_text_pos,
priority = opts.virt_text_priority,
hl_mode = 'combine',
})
end
end
--- @return integer lnum
local function get_lnum()
return api.nvim_win_get_cursor(0)[1]
end
-- Update function, must be called in async context -- Update function, must be called in async context
local update = void(function() local function update0()
local bufnr = current_buf() local bufnr = current_buf()
local lnum = api.nvim_win_get_cursor(0)[1] local lnum = get_lnum()
local old_lnum = get_extmark(bufnr) local old_lnum = get_extmark(bufnr)
if old_lnum and lnum == old_lnum and BlameCache:get(bufnr, lnum) then if old_lnum and lnum == old_lnum and BlameCache:get(bufnr, lnum) then
@ -157,17 +225,14 @@ local update = void(function()
return return
end end
local result = BlameCache:get(bufnr, lnum) local blame_info = run_blame(bufnr, lnum, opts)
if not result then
local buftext = util.buf_lines(bufnr)
result = bcache.git_obj:run_blame(buftext, lnum, opts.ignore_whitespace)
BlameCache:add(bufnr, lnum, result)
scheduler() scheduler()
end
local lnum1 = api.nvim_win_get_cursor(0)[1] local lnum1 = get_lnum()
if bufnr == current_buf() and lnum ~= lnum1 then if bufnr == current_buf() and lnum ~= lnum1 then
-- Cursor has moved during events; abort -- Cursor has moved during events; abort and tr-trigger another update
-- since it's likely blame jobs where skipped
update0()
return return
end end
@ -176,40 +241,14 @@ local update = void(function()
return return
end end
vim.b[bufnr].gitsigns_blame_line_dict = result vim.b[bufnr].gitsigns_blame_line_dict = blame_info
if result then if blame_info then
local virt_text ---@type {[1]: string, [2]: string}[] handle_blame_info(bufnr, lnum, blame_info, opts)
local clb_formatter = result.author == 'Not Committed Yet'
and config.current_line_blame_formatter_nc
or config.current_line_blame_formatter
if type(clb_formatter) == 'string' then
virt_text = {
{
expand_blame_format(clb_formatter, bcache.git_obj.repo.username, result),
'GitSignsCurrentLineBlame',
},
}
else -- function
virt_text = clb_formatter(
bcache.git_obj.repo.username,
result,
config.current_line_blame_formatter_opts
)
end
vim.b[bufnr].gitsigns_blame_line = flatten_virt_text(virt_text)
if opts.virt_text then
set_extmark(bufnr, lnum, {
virt_text = virt_text,
virt_text_pos = opts.virt_text_pos,
priority = opts.virt_text_priority,
hl_mode = 'combine',
})
end end
end end
end)
local update = void(update0)
function M.setup() function M.setup()
local group = api.nvim_create_augroup('gitsigns_blame', {}) local group = api.nvim_create_augroup('gitsigns_blame', {})
@ -221,9 +260,7 @@ function M.setup()
if config.current_line_blame then if config.current_line_blame then
api.nvim_create_autocmd({ 'FocusGained', 'BufEnter', 'CursorMoved', 'CursorMovedI' }, { api.nvim_create_autocmd({ 'FocusGained', 'BufEnter', 'CursorMoved', 'CursorMovedI' }, {
group = group, group = group,
callback = function() callback = update,
update()
end,
}) })
api.nvim_create_autocmd({ 'InsertEnter', 'FocusLost', 'BufLeave' }, { api.nvim_create_autocmd({ 'InsertEnter', 'FocusLost', 'BufLeave' }, {