Skip to content

Commit

Permalink
refacto: misc refactoring (#983)
Browse files Browse the repository at this point in the history
  • Loading branch information
lewis6991 committed Apr 16, 2024
1 parent d96ef3b commit c025161
Show file tree
Hide file tree
Showing 14 changed files with 182 additions and 178 deletions.
8 changes: 4 additions & 4 deletions doc/gitsigns.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,14 @@ attach({bufnr}, {ctx}, {callback?}) *gitsigns.attach()*
{file}: (string)
Path to the file represented by the buffer, relative to the
top-level.
{toplevel}: (string)
{toplevel}: (string?)
Path to the top-level of the parent git repository.
{gitdir}: (string)
{gitdir}: (string?)
Path to the git directory of the parent git repository
(typically the ".git/" directory).
{commit}: (string)
{commit}: (string?)
The git revision that the file belongs to.
{base}: (string|nil)
{base}: (string?)
The git revision that the file should be compared to.

detach({bufnr}) *gitsigns.detach()*
Expand Down
59 changes: 33 additions & 26 deletions lua/gitsigns.lua
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
local async = require('gitsigns.async')
local log = require('gitsigns.debug.log')

local gs_config = require('gitsigns.config')
local config = gs_config.config

local log = require('gitsigns.debug.log')
local dprintf = log.dprintf
local dprint = log.dprint

local api = vim.api
local uv = vim.uv or vim.loop

Expand Down Expand Up @@ -97,10 +94,10 @@ local function update_cwd_head()
async.create(function(err)
local __FUNC__ = 'cwd_watcher_cb'
if err then
dprintf('Git dir update error: %s', err)
log.dprintf('Git dir update error: %s', err)
return
end
dprint('Git cwd dir update')
log.dprint('Git cwd dir update')

update_head()
end)
Expand All @@ -127,12 +124,34 @@ end

--- @async
local function setup_attach()
if not config.auto_attach then
return
end

async.scheduler()

local attach_autocmd_disabled = false

api.nvim_create_autocmd({ 'BufRead', 'BufNewFile', 'BufWritePost' }, {
group = 'gitsigns',
callback = function(data)
require('gitsigns.attach').attach(data.buf, nil, data.event)
callback = function(args)
local bufnr = args.buf --[[@as integer]]
if attach_autocmd_disabled then
local __FUNC__ = 'attach_autocmd'
log.dprint('Attaching is disabled')
return
end
require('gitsigns.attach').attach(bufnr, nil, args.event)
end,
})

--- vimpgrep creates and deletes lots of buffers so attaching to each one will
--- waste lots of resource and even slow down vimgrep.
api.nvim_create_autocmd({ 'QuickFixCmdPre', 'QuickFixCmdPost' }, {
group = 'gitsigns',
pattern = '*vimgrep*',
callback = function(args)
attach_autocmd_disabled = args.event == 'QuickFixCmdPre'
end,
})

Expand All @@ -141,8 +160,7 @@ local function setup_attach()
if api.nvim_buf_is_loaded(buf) and api.nvim_buf_get_name(buf) ~= '' then
-- Make sure to run each attach in its on async context in case one of the
-- attaches is aborted.
local attach = require('gitsigns.attach')
attach.attach(buf, nil, 'setup')
require('gitsigns.attach').attach(buf, nil, 'setup')
end
end
end
Expand Down Expand Up @@ -180,28 +198,17 @@ M.setup = async.create(1, function(cfg)
return
end

if config.yadm.enable and vim.fn.executable('yadm') == 0 then
print("gitsigns: yadm not in path. Ignoring 'yadm.enable' in config")
config.yadm.enable = false
return
end

setup_debug()
setup_cli()

api.nvim_create_augroup('gitsigns', {})

if config._test_mode then
require('gitsigns.attach')._setup()
if vim.fn.has('nvim-0.9') == 0 then
require('gitsigns.git.version').check()
end

if config.auto_attach then
setup_attach()
end
setup_debug()
setup_cli()
require('gitsigns.highlight').setup()
setup_attach()
setup_cwd_head()

M._setup_done = true
end)

return setmetatable(M, {
Expand Down
165 changes: 69 additions & 96 deletions lua/gitsigns/attach.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ local uv = vim.loop

local M = {}

local attach_disabled = false

--- @param name string
--- @return string? buffer
--- @return string? commit
Expand Down Expand Up @@ -115,10 +113,7 @@ end
--- @param _ 'detach'
--- @param bufnr integer
local function on_detach(_, bufnr)
api.nvim_clear_autocmds({
group = 'gitsigns',
buffer = bufnr,
})
api.nvim_clear_autocmds({ group = 'gitsigns', buffer = bufnr })
M.detach(bufnr, true)
end

Expand Down Expand Up @@ -162,62 +157,63 @@ local function try_worktrees(_bufnr, file, encoding)
end
end

--- vimpgrep creates and deletes lots of buffers so attaching to each one will
--- waste lots of resource and even slow down vimgrep.
local function setup_vimgrep_autocmds()
api.nvim_create_autocmd('QuickFixCmdPre', {
group = 'gitsigns',
pattern = '*vimgrep*',
callback = function()
attach_disabled = true
end,
})

api.nvim_create_autocmd('QuickFixCmdPost', {
group = 'gitsigns',
pattern = '*vimgrep*',
callback = function()
attach_disabled = false
end,
})
end

local done_setup = false

function M._setup()
if done_setup then
return
end

done_setup = true

local setup = util.once(function()
manager.setup()
require('gitsigns.highlight').setup()

api.nvim_create_autocmd('OptionSet', {
group = 'gitsigns',
pattern = { 'fileformat', 'bomb', 'eol' },
callback = function()
require('gitsigns.actions').refresh()
local buf = vim.api.nvim_get_current_buf()
cache[buf]:invalidate(true)
manager.update(buf)
end,
})

setup_vimgrep_autocmds()

require('gitsigns.current_line_blame').setup()

api.nvim_create_autocmd('VimLeavePre', {
group = 'gitsigns',
callback = M.detach_all,
})
end
end)

--- @class Gitsigns.GitContext
--- @field toplevel string
--- @field gitdir string
--- @field file string
--- @field commit string
--- @field base string
--- @field toplevel? string
--- @field gitdir? string
--- @field commit? string
--- @field base? string

--- @param bufnr integer
--- @return Gitsigns.GitContext? ctx
--- @return string? err
local function get_buf_context(bufnr)
if api.nvim_buf_line_count(bufnr) > config.max_file_length then
return nil, 'Exceeds max_file_length'
end

local file, commit, force_attach = get_buf_path(bufnr)

if vim.bo[bufnr].buftype ~= '' and not force_attach then
return nil, 'Non-normal buffer'
end

local file_dir = util.dirname(file)

if not file_dir or not util.path_exists(file_dir) then
return nil, 'Not a path'
end

local gitdir, toplevel = on_attach_pre(bufnr)

return {
file = file,
gitdir = gitdir,
toplevel = toplevel,
commit = commit,
}
end

--- Ensure attaches cannot be interleaved for the same buffer.
--- Since attaches are asynchronous we need to make sure an attach isn't
Expand All @@ -227,13 +223,9 @@ end
--- @param aucmd? string
local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)
local __FUNC__ = 'attach'
local passed_ctx = ctx ~= nil

M._setup()

if attach_disabled then
dprint('attaching is disabled')
return
end
setup()

if cache[cbuf] then
dprint('Already attached')
Expand All @@ -251,47 +243,29 @@ local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)
return
end

if not ctx then
local err
ctx, err = get_buf_context(cbuf)
if err then
dprint(err)
return
end
assert(ctx)
end

local encoding = vim.bo[cbuf].fileencoding
if encoding == '' then
encoding = 'utf-8'
end
local file --- @type string
local commit --- @type string?
local gitdir_oap --- @type string?
local toplevel_oap --- @type string?

if ctx then
gitdir_oap = ctx.gitdir
toplevel_oap = ctx.toplevel
file = ctx.toplevel .. util.path_sep .. ctx.file
commit = ctx.commit
else
if api.nvim_buf_line_count(cbuf) > config.max_file_length then
dprint('Exceeds max_file_length')
return
end

local force_attach
file, commit, force_attach = get_buf_path(cbuf)

if vim.bo[cbuf].buftype ~= '' and not force_attach then
dprint('Non-normal buffer')
return
end

local file_dir = util.dirname(file)

if not file_dir or not util.path_exists(file_dir) then
dprint('Not a path')
return
end

gitdir_oap, toplevel_oap = on_attach_pre(cbuf)
local file = ctx.file
if not vim.startswith(file, '/') and ctx.toplevel then
file = ctx.toplevel .. util.path_sep .. file
end

local git_obj = git.Obj.new(file, encoding, gitdir_oap, toplevel_oap)
local git_obj = git.Obj.new(file, encoding, ctx.gitdir, ctx.toplevel)

if not git_obj and not ctx then
if not git_obj and not passed_ctx then
git_obj = try_worktrees(cbuf, file, encoding)
async.scheduler()
if not api.nvim_buf_is_valid(cbuf) then
Expand All @@ -303,25 +277,24 @@ local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)
dprint('Empty git obj')
return
end
local repo = git_obj.repo

async.scheduler()
if not api.nvim_buf_is_valid(cbuf) then
return
end

Status:update(cbuf, {
head = repo.abbrev_head,
root = repo.toplevel,
gitdir = repo.gitdir,
head = git_obj.repo.abbrev_head,
root = git_obj.repo.toplevel,
gitdir = git_obj.repo.gitdir,
})

if vim.startswith(file, repo.gitdir .. util.path_sep) then
if vim.startswith(file, git_obj.repo.gitdir .. util.path_sep) then
dprint('In non-standard git dir')
return
end

if not ctx and (not util.path_exists(file) or uv.fs_stat(file).type == 'directory') then
if not passed_ctx and (not util.path_exists(file) or uv.fs_stat(file).type == 'directory') then
dprint('Not a file')
return
end
Expand Down Expand Up @@ -350,15 +323,15 @@ local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)

cache[cbuf] = gs_cache.new({
bufnr = cbuf,
base = ctx and ctx.base or config.base,
base = ctx.base or config.base,
file = file,
commit = commit,
commit = ctx.commit,
git_obj = git_obj,
})

if config.watch_gitdir.enable then
local watcher = require('gitsigns.watcher')
cache[cbuf].gitdir_watcher = watcher.watch_gitdir(cbuf, repo.gitdir)
cache[cbuf].gitdir_watcher = watcher.watch_gitdir(cbuf, git_obj.repo.gitdir)
end

if not api.nvim_buf_is_loaded(cbuf) then
Expand Down Expand Up @@ -433,14 +406,14 @@ end
--- • {file}: (string)
--- Path to the file represented by the buffer, relative to the
--- top-level.
--- • {toplevel}: (string)
--- • {toplevel}: (string?)
--- Path to the top-level of the parent git repository.
--- • {gitdir}: (string)
--- • {gitdir}: (string?)
--- Path to the git directory of the parent git repository
--- (typically the ".git/" directory).
--- • {commit}: (string)
--- • {commit}: (string?)
--- The git revision that the file belongs to.
--- • {base}: (string|nil)
--- • {base}: (string?)
--- The git revision that the file should be compared to.
--- @param _trigger? string
M.attach = async.create(3, function(bufnr, ctx, _trigger)
Expand Down
Loading

0 comments on commit c025161

Please sign in to comment.