perf(git): run git log sync with bounded count
This commit is contained in:
+37
-40
@@ -214,14 +214,13 @@ local function parse_porcelain(stdout)
|
||||
return branch, groups
|
||||
end
|
||||
|
||||
---Run the ahead/behind `git log` calls for any non-zero counters and call
|
||||
---`callback(branch, groups)` once they all finish (or immediately when
|
||||
---there's nothing to fetch).
|
||||
---Fill in the Unpushed/Unpulled groups from `git log` for any non-zero
|
||||
---ahead/behind counter. Capped at 200 commits per range so a wildly
|
||||
---divergent branch can't blow the sidebar's render budget.
|
||||
---@param worktree string
|
||||
---@param branch ow.Git.BranchInfo
|
||||
---@param groups table<string, ow.Git.SidebarEntry[]>
|
||||
---@param callback fun(branch: ow.Git.BranchInfo, groups: table<string, ow.Git.SidebarEntry[]>)
|
||||
local function enrich_with_log(worktree, branch, groups, callback)
|
||||
local function enrich_with_log(worktree, branch, groups)
|
||||
local fetches = {}
|
||||
if branch.upstream and branch.ahead > 0 then
|
||||
table.insert(
|
||||
@@ -235,45 +234,41 @@ local function enrich_with_log(worktree, branch, groups, callback)
|
||||
{ section = "Unpulled", range = "HEAD..@{upstream}" }
|
||||
)
|
||||
end
|
||||
if #fetches == 0 then
|
||||
callback(branch, groups)
|
||||
return
|
||||
end
|
||||
local pending = #fetches
|
||||
-- Submit both subprocesses before waiting so they run concurrently
|
||||
-- rather than sequentially. Total time = max, not sum.
|
||||
local pending = {}
|
||||
for _, f in ipairs(fetches) do
|
||||
vim.system(
|
||||
{
|
||||
table.insert(pending, {
|
||||
f = f,
|
||||
sys = vim.system({
|
||||
"git",
|
||||
"log",
|
||||
"--max-count=200",
|
||||
"--format=%h %s",
|
||||
f.range,
|
||||
},
|
||||
{ cwd = worktree, text = true },
|
||||
vim.schedule_wrap(function(log_obj)
|
||||
if log_obj.code == 0 then
|
||||
for line in (log_obj.stdout or ""):gmatch("[^\r\n]+") do
|
||||
local sha, subject = line:match("^(%S+)%s+(.+)$")
|
||||
if sha then
|
||||
table.insert(groups[f.section], {
|
||||
section = f.section,
|
||||
sha = sha,
|
||||
subject = subject,
|
||||
})
|
||||
end
|
||||
end
|
||||
else
|
||||
log.error(
|
||||
"git log %s failed: %s",
|
||||
f.range,
|
||||
vim.trim(log_obj.stderr or "")
|
||||
)
|
||||
}, { cwd = worktree, text = true }),
|
||||
})
|
||||
end
|
||||
for _, p in ipairs(pending) do
|
||||
local result = p.sys:wait()
|
||||
if result.code == 0 then
|
||||
for line in (result.stdout or ""):gmatch("[^\r\n]+") do
|
||||
local sha, subject = line:match("^(%S+)%s+(.+)$")
|
||||
if sha then
|
||||
table.insert(groups[p.f.section], {
|
||||
section = p.f.section,
|
||||
sha = sha,
|
||||
subject = subject,
|
||||
})
|
||||
end
|
||||
pending = pending - 1
|
||||
if pending == 0 then
|
||||
callback(branch, groups)
|
||||
end
|
||||
end)
|
||||
)
|
||||
end
|
||||
else
|
||||
log.error(
|
||||
"git log %s failed: %s",
|
||||
p.f.range,
|
||||
vim.trim(result.stderr or "")
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -287,7 +282,8 @@ end
|
||||
local function fetch_status(worktree, prefetched_stdout, callback)
|
||||
if prefetched_stdout then
|
||||
local branch, groups = parse_porcelain(prefetched_stdout)
|
||||
enrich_with_log(worktree, branch, groups, callback)
|
||||
enrich_with_log(worktree, branch, groups)
|
||||
callback(branch, groups)
|
||||
return
|
||||
end
|
||||
vim.system(
|
||||
@@ -316,7 +312,8 @@ local function fetch_status(worktree, prefetched_stdout, callback)
|
||||
return
|
||||
end
|
||||
local branch, groups = parse_porcelain(obj.stdout or "")
|
||||
enrich_with_log(worktree, branch, groups, callback)
|
||||
enrich_with_log(worktree, branch, groups)
|
||||
callback(branch, groups)
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user