perf(git/repo): cache ref/file lookups, invalidate on status refresh
This commit is contained in:
+8
-3
@@ -317,22 +317,26 @@ end
|
|||||||
---@param dir string
|
---@param dir string
|
||||||
---@return string[]
|
---@return string[]
|
||||||
local function list_files(r, dir)
|
local function list_files(r, dir)
|
||||||
|
return r:get_cached("files:" .. dir, function(self)
|
||||||
local cmd = { "git", "ls-files" }
|
local cmd = { "git", "ls-files" }
|
||||||
if dir ~= "" then
|
if dir ~= "" then
|
||||||
table.insert(cmd, dir)
|
table.insert(cmd, dir)
|
||||||
end
|
end
|
||||||
local out = util.exec(cmd, { cwd = r.worktree, silent = true })
|
local out = util.exec(cmd, { cwd = self.worktree, silent = true })
|
||||||
return out and util.split_lines(out) or {}
|
return out and util.split_lines(out) or {}
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param r ow.Git.Repo
|
---@param r ow.Git.Repo
|
||||||
---@return string[]
|
---@return string[]
|
||||||
local function list_remotes(r)
|
local function list_remotes(r)
|
||||||
|
return r:get_cached("remotes", function(self)
|
||||||
local out = util.exec(
|
local out = util.exec(
|
||||||
{ "git", "remote" },
|
{ "git", "remote" },
|
||||||
{ cwd = r.worktree, silent = true }
|
{ cwd = self.worktree, silent = true }
|
||||||
)
|
)
|
||||||
return out and util.split_lines(out) or {}
|
return out and util.split_lines(out) or {}
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type table<string, string[]>
|
---@type table<string, string[]>
|
||||||
@@ -469,7 +473,8 @@ function M.complete_rev(arg_lead)
|
|||||||
|
|
||||||
local colon = arg_lead:find(":", 1, true)
|
local colon = arg_lead:find(":", 1, true)
|
||||||
if not colon then
|
if not colon then
|
||||||
local refs = r:list_refs()
|
local refs = {}
|
||||||
|
vim.list_extend(refs, r:list_refs())
|
||||||
vim.list_extend(refs, r:list_pseudo_refs())
|
vim.list_extend(refs, r:list_pseudo_refs())
|
||||||
vim.list_extend(refs, r:list_stash_refs())
|
vim.list_extend(refs, r:list_stash_refs())
|
||||||
return prefix_filter(refs, arg_lead)
|
return prefix_filter(refs, arg_lead)
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ local global = util.Emitter.new()
|
|||||||
---@field private _watcher? uv.uv_fs_event_t
|
---@field private _watcher? uv.uv_fs_event_t
|
||||||
---@field private _schedule_refresh fun(self: ow.Git.Repo)
|
---@field private _schedule_refresh fun(self: ow.Git.Repo)
|
||||||
---@field private _refresh_handle ow.Git.Util.DebounceHandle
|
---@field private _refresh_handle ow.Git.Util.DebounceHandle
|
||||||
|
---@field private _cache table<string, any>
|
||||||
local Repo = {}
|
local Repo = {}
|
||||||
Repo.__index = Repo
|
Repo.__index = Repo
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ function Repo:_fetch_status()
|
|||||||
STATUS_CMD,
|
STATUS_CMD,
|
||||||
{ cwd = self.worktree, text = true },
|
{ cwd = self.worktree, text = true },
|
||||||
vim.schedule_wrap(function(obj)
|
vim.schedule_wrap(function(obj)
|
||||||
|
self._cache = {}
|
||||||
if obj.code ~= 0 then
|
if obj.code ~= 0 then
|
||||||
util.error("git status failed: %s", vim.trim(obj.stderr or ""))
|
util.error("git status failed: %s", vim.trim(obj.stderr or ""))
|
||||||
return
|
return
|
||||||
@@ -82,6 +84,7 @@ function Repo.new(gitdir, worktree)
|
|||||||
tabs = {},
|
tabs = {},
|
||||||
status = status.parse(""),
|
status = status.parse(""),
|
||||||
_events = util.Emitter.new(),
|
_events = util.Emitter.new(),
|
||||||
|
_cache = {},
|
||||||
}, Repo)
|
}, Repo)
|
||||||
self._schedule_refresh, self._refresh_handle =
|
self._schedule_refresh, self._refresh_handle =
|
||||||
util.debounce(Repo._fetch_status, 50)
|
util.debounce(Repo._fetch_status, 50)
|
||||||
@@ -90,6 +93,20 @@ function Repo.new(gitdir, worktree)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@generic T
|
||||||
|
---@param key string
|
||||||
|
---@param compute fun(self: ow.Git.Repo): T
|
||||||
|
---@return T
|
||||||
|
function Repo:get_cached(key, compute)
|
||||||
|
local hit = self._cache[key]
|
||||||
|
if hit ~= nil then
|
||||||
|
return hit
|
||||||
|
end
|
||||||
|
local value = compute(self)
|
||||||
|
self._cache[key] = value
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
|
||||||
function Repo:start_watcher()
|
function Repo:start_watcher()
|
||||||
local watcher, err = vim.uv.new_fs_event()
|
local watcher, err = vim.uv.new_fs_event()
|
||||||
if not watcher then
|
if not watcher then
|
||||||
@@ -168,6 +185,7 @@ end
|
|||||||
|
|
||||||
---@return string[]
|
---@return string[]
|
||||||
function Repo:list_refs()
|
function Repo:list_refs()
|
||||||
|
return self:get_cached("refs", function(self)
|
||||||
local out = util.exec({
|
local out = util.exec({
|
||||||
"git",
|
"git",
|
||||||
"for-each-ref",
|
"for-each-ref",
|
||||||
@@ -180,6 +198,7 @@ function Repo:list_refs()
|
|||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
return util.split_lines(out)
|
return util.split_lines(out)
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local PSEUDO_REFS = {
|
local PSEUDO_REFS = {
|
||||||
@@ -194,6 +213,7 @@ local PSEUDO_REFS = {
|
|||||||
|
|
||||||
---@return string[]
|
---@return string[]
|
||||||
function Repo:list_pseudo_refs()
|
function Repo:list_pseudo_refs()
|
||||||
|
return self:get_cached("pseudo_refs", function(self)
|
||||||
local refs = {}
|
local refs = {}
|
||||||
for _, name in ipairs(PSEUDO_REFS) do
|
for _, name in ipairs(PSEUDO_REFS) do
|
||||||
if name == "HEAD" or vim.uv.fs_stat(self.gitdir .. "/" .. name) then
|
if name == "HEAD" or vim.uv.fs_stat(self.gitdir .. "/" .. name) then
|
||||||
@@ -201,10 +221,12 @@ function Repo:list_pseudo_refs()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
return refs
|
return refs
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return string[]
|
---@return string[]
|
||||||
function Repo:list_stash_refs()
|
function Repo:list_stash_refs()
|
||||||
|
return self:get_cached("stash_refs", function(self)
|
||||||
if not vim.uv.fs_stat(self.gitdir .. "/refs/stash") then
|
if not vim.uv.fs_stat(self.gitdir .. "/refs/stash") then
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
@@ -219,6 +241,7 @@ function Repo:list_stash_refs()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
return refs
|
return refs
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param rev string
|
---@param rev string
|
||||||
|
|||||||
Reference in New Issue
Block a user