From 8624f825ebae18a7386a55c1bc2134dc10f391ca Mon Sep 17 00:00:00 2001 From: Oscar Wallberg Date: Sun, 10 May 2026 04:47:35 +0200 Subject: [PATCH] fix(git): validate placement, cache repo lookups, tighten lifecycle --- lua/git/repo.lua | 15 +++++++++++++++ lua/git/status_view.lua | 10 +++++++++- lua/git/statusline.lua | 8 +++++++- lua/git/util.lua | 4 ++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lua/git/repo.lua b/lua/git/repo.lua index 1061d9a..b9e0076 100644 --- a/lua/git/repo.lua +++ b/lua/git/repo.lua @@ -204,6 +204,7 @@ function Repo:close() end self._watchers = {} self._refresh_handle.close() + self._events:clear() end ---@param event ow.Git.Repo.Event @@ -344,6 +345,9 @@ end ---@type table keyed by worktree local repos = {} +---@type table +local no_repo_dirs = {} + ---@param event ow.Git.Repo.Event ---@param fn fun(...) ---@return fun() unsubscribe @@ -440,8 +444,13 @@ function M.resolve(arg) else path = path_for_buf(expand_buf(arg)) end + local dir = vim.fs.dirname(path) + if no_repo_dirs[dir] then + return nil + end local found = vim.fs.find(".git", { upward = true, path = path })[1] if not found then + no_repo_dirs[dir] = true return nil end local worktree = vim.fs.dirname(found) @@ -473,6 +482,11 @@ function M.resolve(arg) end local r = Repo.new(gitdir, worktree) repos[worktree] = r + for d in pairs(no_repo_dirs) do + if d == worktree or vim.startswith(d, worktree .. "/") then + no_repo_dirs[d] = nil + end + end return r end @@ -547,6 +561,7 @@ function M.refresh_all() end function M.update_cwd_repo() + no_repo_dirs = {} local tab = vim.api.nvim_get_current_tabpage() local new = M.resolve(vim.fn.getcwd()) local old diff --git a/lua/git/status_view.lua b/lua/git/status_view.lua index 783f388..e29eed8 100644 --- a/lua/git/status_view.lua +++ b/lua/git/status_view.lua @@ -49,7 +49,7 @@ end local state = {} local group = - vim.api.nvim_create_augroup("ow.git.status_win", { clear = false }) + vim.api.nvim_create_augroup("ow.git.status_win", { clear = true }) local ns = vim.api.nvim_create_namespace("ow.git.status_win") ---@return integer? win @@ -713,6 +713,14 @@ end function M.open(opts) opts = opts or {} local placement = opts.placement or "sidebar" + if not vim.tbl_contains(M.PLACEMENTS, placement) then + util.error( + "invalid placement: %s (expected one of %s)", + placement, + table.concat(M.PLACEMENTS, ", ") + ) + return + end local r = repo.resolve() if not r then util.error("not in a git repository") diff --git a/lua/git/statusline.lua b/lua/git/statusline.lua index d7265e6..2bc257a 100644 --- a/lua/git/statusline.lua +++ b/lua/git/statusline.lua @@ -58,12 +58,18 @@ local function update_buf(buf, r) end repo.on("refresh", function(r) + local any_visible = false for buf in pairs(r.buffers) do if vim.api.nvim_buf_is_loaded(buf) then update_buf(buf, r) + if not any_visible and #vim.fn.win_findbuf(buf) > 0 then + any_visible = true + end end end - vim.cmd.redrawstatus({ bang = true }) + if any_visible then + vim.cmd.redrawstatus({ bang = true }) + end end) vim.api.nvim_create_autocmd("BufWinEnter", { diff --git a/lua/git/util.lua b/lua/git/util.lua index e247d50..f75291a 100644 --- a/lua/git/util.lua +++ b/lua/git/util.lua @@ -278,6 +278,10 @@ function Emitter:emit(event, ...) end end +function Emitter:clear() + self._listeners = {} +end + M.Emitter = Emitter return M