Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: check valid buffer when scheduling #854

Merged
merged 1 commit into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 17 additions & 19 deletions lua/gitsigns/actions.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
local void = require('gitsigns.async').void
local scheduler = require('gitsigns.async').scheduler

local async = require('gitsigns.async')
local config = require('gitsigns.config').config
local mk_repeatable = require('gitsigns.repeat').mk_repeatable
local popup = require('gitsigns.popup')
Expand Down Expand Up @@ -167,7 +165,7 @@ end
--- @param bufnr integer
local function update(bufnr)
manager.update(bufnr)
scheduler()
async.scheduler_if_buf_valid(bufnr)
if vim.wo.diff then
require('gitsigns.diffthis').update(bufnr)
end
Expand Down Expand Up @@ -202,7 +200,7 @@ local function get_hunks(bufnr, bcache, greedy, staged)
return
end
hunks = run_diff(text, buftext, false)
scheduler()
async.scheduler()
return hunks
end

Expand Down Expand Up @@ -255,7 +253,7 @@ end
--- • {greedy}: (boolean)
--- Stage all contiguous hunks. Only useful if 'diff_opts'
--- contains `linematch`. Defaults to `true`.
M.stage_hunk = mk_repeatable(void(function(range, opts)
M.stage_hunk = mk_repeatable(async.void(function(range, opts)
opts = opts or {}
local bufnr = current_buf()
local bcache = cache[bufnr]
Expand Down Expand Up @@ -306,7 +304,7 @@ end
--- • {greedy}: (boolean)
--- Stage all contiguous hunks. Only useful if 'diff_opts'
--- contains `linematch`. Defaults to `true`.
M.reset_hunk = mk_repeatable(void(function(range, opts)
M.reset_hunk = mk_repeatable(async.void(function(range, opts)
opts = opts or {}
local bufnr = current_buf()
local bcache = cache[bufnr]
Expand Down Expand Up @@ -353,7 +351,7 @@ end
---
--- Attributes: ~
--- {async}
M.undo_stage_hunk = void(function()
M.undo_stage_hunk = async.void(function()
local bufnr = current_buf()
local bcache = cache[bufnr]
if not bcache then
Expand All @@ -375,7 +373,7 @@ end)
---
--- Attributes: ~
--- {async}
M.stage_buffer = void(function()
M.stage_buffer = async.void(function()
local bufnr = current_buf()

local bcache = cache[bufnr]
Expand Down Expand Up @@ -411,7 +409,7 @@ end)
---
--- Attributes: ~
--- {async}
M.reset_buffer_index = void(function()
M.reset_buffer_index = async.void(function()
local bufnr = current_buf()
local bcache = cache[bufnr]
if not bcache then
Expand Down Expand Up @@ -490,7 +488,7 @@ end

--- @param opts? Gitsigns.NavOpts
--- @param forwards boolean
local nav_hunk = void(function(opts, forwards)
local nav_hunk = async.void(function(opts, forwards)
opts = process_nav_opts(opts)
local bufnr = current_buf()
local bcache = cache[bufnr]
Expand Down Expand Up @@ -859,7 +857,7 @@ end
--- Display full commit message with hunk.
--- • {ignore_whitespace}: (boolean)
--- Ignore whitespace when running blame.
M.blame_line = void(function(opts)
M.blame_line = async.void(function(opts)
if popup.focus_open('blame') then
return
end
Expand All @@ -876,7 +874,7 @@ M.blame_line = void(function(opts)
popup.create({ { { 'Loading...', 'Title' } } }, config.preview_config)
end, 1000)

scheduler()
async.scheduler_if_buf_valid()
local buftext = util.buf_lines(bufnr)
local fileformat = vim.bo[bufnr].fileformat
local lnum = api.nvim_win_get_cursor(0)[1]
Expand Down Expand Up @@ -905,7 +903,7 @@ M.blame_line = void(function(opts)
insert_hunk_hlmarks(blame_fmt, hunk)
end

scheduler()
async.scheduler_if_buf_valid(bufnr)

popup.create(lines_format(blame_fmt, result), config.preview_config, 'blame')
end)
Expand Down Expand Up @@ -948,7 +946,7 @@ end
---
--- @param base string|nil The object/revision to diff against.
--- @param global boolean|nil Change the base of all buffers.
M.change_base = void(function(base, global)
M.change_base = async.void(function(base, global)
base = util.calc_base(base)

if global then
Expand Down Expand Up @@ -1134,7 +1132,7 @@ local function buildqflist(target)
local stat = vim.loop.fs_stat(f_abs)
if stat and stat.type == 'file' then
local a = r:get_show_text(':0:' .. f)
scheduler()
async.scheduler()
local hunks = run_diff(a, util.file_lines(f_abs))
hunks_to_qflist(f_abs, hunks, qflist)
end
Expand Down Expand Up @@ -1170,7 +1168,7 @@ end
--- • {open}: (boolean)
--- Open the quickfix/location list viewer.
--- Defaults to `true`.
M.setqflist = void(function(target, opts)
M.setqflist = async.void(function(target, opts)
opts = opts or {}
if opts.open == nil then
opts.open = true
Expand All @@ -1179,7 +1177,7 @@ M.setqflist = void(function(target, opts)
items = buildqflist(target),
title = 'Hunks',
}
scheduler()
async.scheduler()
if opts.use_location_list then
local nr = opts.nr or 0
vim.fn.setloclist(nr, {}, ' ', qfopts)
Expand Down Expand Up @@ -1263,7 +1261,7 @@ end
---
--- Attributes: ~
--- {async}
M.refresh = void(function()
M.refresh = async.void(function()
manager.reset_signs()
require('gitsigns.highlight').setup_highlights()
require('gitsigns.current_line_blame').setup()
Expand Down
9 changes: 9 additions & 0 deletions lua/gitsigns/async.lua
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,13 @@ end
---able to call the API.
M.scheduler = M.wrap(vim.schedule, 1)

--- @param buf? integer
M.scheduler_if_buf_valid = M.wrap(function(buf, cb)
vim.schedule(function()
if not buf or vim.api.nvim_buf_is_valid(buf) then
cb()
end
end)
end, 2)

return M
6 changes: 3 additions & 3 deletions lua/gitsigns/attach.lua
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)

if not git_obj and not ctx then
git_obj = try_worktrees(cbuf, file, encoding)
async.scheduler()
async.scheduler_if_buf_valid(cbuf)
end

if not git_obj then
Expand All @@ -300,7 +300,7 @@ local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)
end
local repo = git_obj.repo

async.scheduler()
async.scheduler_if_buf_valid(cbuf)
Status:update(cbuf, {
head = repo.abbrev_head,
root = repo.toplevel,
Expand Down Expand Up @@ -329,7 +329,7 @@ local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)

-- On windows os.tmpname() crashes in callback threads so initialise this
-- variable on the main thread.
async.scheduler()
async.scheduler_if_buf_valid(cbuf)

if config.on_attach and config.on_attach(cbuf) == false then
dprint('User on_attach() returned false')
Expand Down
19 changes: 5 additions & 14 deletions lua/gitsigns/current_line_blame.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
local a = require('gitsigns.async')
local wrap = a.wrap
local void = a.void
local scheduler = a.scheduler

local async = require('gitsigns.async')
local cache = require('gitsigns.cache').cache
local config = require('gitsigns.config').config
local util = require('gitsigns.util')
Expand All @@ -18,7 +14,7 @@ local timer = assert(uv.new_timer())

local M = {}

local wait_timer = wrap(uv.timer_start, 4)
local wait_timer = async.wrap(uv.timer_start, 4)

--- @param bufnr integer
--- @param row integer
Expand Down Expand Up @@ -218,15 +214,15 @@ local function update0()

-- Note because the same timer is re-used, this call has a debouncing effect.
wait_timer(timer, opts.delay, 0)
scheduler()
async.scheduler()

local bcache = cache[bufnr]
if not bcache or not bcache.git_obj.object_name then
return
end

local blame_info = run_blame(bufnr, lnum, opts)
scheduler()
async.scheduler_if_buf_valid(bufnr)

local lnum1 = get_lnum()
if bufnr == current_buf() and lnum ~= lnum1 then
Expand All @@ -236,19 +232,14 @@ local function update0()
return
end

if not api.nvim_buf_is_loaded(bufnr) then
-- Buffer is no longer loaded; abort
return
end

vim.b[bufnr].gitsigns_blame_line_dict = blame_info

if blame_info then
handle_blame_info(bufnr, lnum, blame_info, opts)
end
end

local update = void(update0)
local update = async.void(update0)

function M.setup()
local group = api.nvim_create_augroup('gitsigns_blame', {})
Expand Down
27 changes: 11 additions & 16 deletions lua/gitsigns/diffthis.lua
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
local api = vim.api

local void = require('gitsigns.async').void
local scheduler = require('gitsigns.async').scheduler
local awrap = require('gitsigns.async').wrap

local gs_cache = require('gitsigns.cache')
local cache = gs_cache.cache

local async = require('gitsigns.async')
local cache = require('gitsigns.cache').cache
local util = require('gitsigns.util')
local manager = require('gitsigns.manager')
local message = require('gitsigns.message')

local throttle_by_id = require('gitsigns.debounce').throttle_by_id

--- @type fun(opts: table): string
local input = awrap(vim.ui.input, 2)
local input = async.awrap(vim.ui.input, 2)

local M = {}

--- @param bufnr integer
--- @param dbufnr integer
--- @param base string
local bufread = void(function(bufnr, dbufnr, base)
local bufread = async.void(function(bufnr, dbufnr, base)
local bcache = cache[bufnr]
local comp_rev = bcache:get_compare_rev(util.calc_base(base))
local text --- @type string[]
Expand All @@ -33,7 +28,7 @@ local bufread = void(function(bufnr, dbufnr, base)
if err then
error(err, 2)
end
scheduler()
async.scheduler_if_buf_valid(bufnr)
if vim.bo[bufnr].fileformat == 'dos' then
text = util.strip_cr(text)
end
Expand All @@ -52,11 +47,11 @@ end)
--- @param bufnr integer
--- @param dbufnr integer
--- @param base string
local bufwrite = void(function(bufnr, dbufnr, base)
local bufwrite = async.void(function(bufnr, dbufnr, base)
local bcache = cache[bufnr]
local buftext = util.buf_lines(dbufnr)
bcache.git_obj:stage_lines(buftext)
scheduler()
async.scheduler_if_buf_valid(bufnr)
vim.bo[dbufnr].modified = false
-- If diff buffer base matches the bcache base then also update the
-- signs.
Expand Down Expand Up @@ -86,7 +81,7 @@ local function create_show_buf(bufnr, base)
local ok, err = pcall(bufread, bufnr, dbuf, base)
if not ok then
message.error(err --[[@as string]])
scheduler()
async.scheduler()
api.nvim_buf_delete(dbuf, { force = true })
return
end
Expand Down Expand Up @@ -145,7 +140,7 @@ end

--- @param base string
--- @param opts Gitsigns.DiffthisOpts
M.diffthis = void(function(base, opts)
M.diffthis = async.void(function(base, opts)
if vim.wo.diff then
return
end
Expand All @@ -169,7 +164,7 @@ M.diffthis = void(function(base, opts)
end)

--- @param base string
M.show = void(function(base)
M.show = async.void(function(base)
local bufnr = api.nvim_get_current_buf()
local bufname = create_show_buf(bufnr, base)
if not bufname then
Expand All @@ -196,7 +191,7 @@ end

-- This function needs to be throttled as there is a call to vim.ui.input
--- @param bufnr integer
M.update = throttle_by_id(void(function(bufnr)
M.update = throttle_by_id(async.void(function(bufnr)
if not vim.wo.diff then
return
end
Expand Down
19 changes: 5 additions & 14 deletions lua/gitsigns/manager.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
local void = require('gitsigns.async').void
local awrap = require('gitsigns.async').wrap
local async = require('gitsigns.async')

local gs_cache = require('gitsigns.cache')
local cache = gs_cache.cache
Expand Down Expand Up @@ -30,14 +29,6 @@ local signs_staged --- @type Gitsigns.Signs

local M = {}

local scheduler_if_buf_valid = awrap(function(buf, cb)
vim.schedule(function()
if vim.api.nvim_buf_is_valid(buf) then
cb()
end
end)
end, 2)

--- @param bufnr integer
--- @param signs Gitsigns.Signs
--- @param hunks Gitsigns.Hunk.Hunk[]
Expand Down Expand Up @@ -421,13 +412,13 @@ M.update = throttle_by_id(function(bufnr, bcache)
local old_hunks, old_hunks_staged = bcache.hunks, bcache.hunks_staged
bcache.hunks, bcache.hunks_staged = nil, nil

scheduler_if_buf_valid(bufnr)
async.scheduler_if_buf_valid(bufnr)
local buftext = util.buf_lines(bufnr)
local git_obj = bcache.git_obj

if not bcache.compare_text or config._refresh_staged_on_update then
bcache.compare_text = git_obj:get_show_text(bcache:get_compare_rev())
scheduler_if_buf_valid(bufnr)
async.scheduler_if_buf_valid(bufnr)
end

bcache.hunks = run_diff(bcache.compare_text, buftext)
Expand All @@ -440,7 +431,7 @@ M.update = throttle_by_id(function(bufnr, bcache)
bcache.hunks_staged = gs_hunks.filter_common(hunks_head, bcache.hunks)
end

scheduler_if_buf_valid(bufnr)
async.scheduler_if_buf_valid(bufnr)

-- Note the decoration provider may have invalidated bcache.hunks at this
-- point
Expand Down Expand Up @@ -536,7 +527,7 @@ function M.setup()
signs_staged = Signs.new(config._signs_staged, 'staged')
end

M.update_debounced = debounce_trailing(config.update_debounce, void(M.update))
M.update_debounced = debounce_trailing(config.update_debounce, async.void(M.update))
end

return M
Loading
Loading