refactor(git): convert blocking subprocess calls to async
This commit is contained in:
+62
-62
@@ -1,4 +1,5 @@
|
||||
local diff = require("git.diff")
|
||||
local git = require("git")
|
||||
local log = require("log")
|
||||
local repo = require("git.repo")
|
||||
|
||||
@@ -240,13 +241,15 @@ local function enrich_with_log(worktree, branch, groups, callback)
|
||||
end
|
||||
local pending = #fetches
|
||||
for _, f in ipairs(fetches) do
|
||||
vim.system({
|
||||
"git",
|
||||
"log",
|
||||
"--format=%h %s",
|
||||
f.range,
|
||||
}, { cwd = worktree, text = true }, function(log_obj)
|
||||
vim.schedule(function()
|
||||
vim.system(
|
||||
{
|
||||
"git",
|
||||
"log",
|
||||
"--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+(.+)$")
|
||||
@@ -270,7 +273,7 @@ local function enrich_with_log(worktree, branch, groups, callback)
|
||||
callback(branch, groups)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -287,15 +290,17 @@ local function fetch_status(worktree, prefetched_stdout, callback)
|
||||
enrich_with_log(worktree, branch, groups, callback)
|
||||
return
|
||||
end
|
||||
vim.system({
|
||||
"git",
|
||||
"-c",
|
||||
"core.quotePath=false",
|
||||
"status",
|
||||
"--porcelain=v1",
|
||||
"--branch",
|
||||
}, { cwd = worktree, text = true }, function(obj)
|
||||
vim.schedule(function()
|
||||
vim.system(
|
||||
{
|
||||
"git",
|
||||
"-c",
|
||||
"core.quotePath=false",
|
||||
"status",
|
||||
"--porcelain=v1",
|
||||
"--branch",
|
||||
},
|
||||
{ cwd = worktree, text = true },
|
||||
vim.schedule_wrap(function(obj)
|
||||
if obj.code ~= 0 then
|
||||
log.error("git status failed: %s", vim.trim(obj.stderr or ""))
|
||||
local branch = { ahead = 0, behind = 0 }
|
||||
@@ -313,7 +318,7 @@ local function fetch_status(worktree, prefetched_stdout, callback)
|
||||
local branch, groups = parse_porcelain(obj.stdout or "")
|
||||
enrich_with_log(worktree, branch, groups, callback)
|
||||
end)
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
@@ -598,9 +603,7 @@ end
|
||||
---@param win integer
|
||||
---@param enabled boolean
|
||||
local function set_diff(win, enabled)
|
||||
vim.api.nvim_win_call(win, function()
|
||||
vim.cmd(enabled and "diffthis" or "diffoff")
|
||||
end)
|
||||
vim.wo[win].diff = enabled
|
||||
if enabled then
|
||||
vim.wo[win].foldenable = true
|
||||
vim.wo[win].foldlevel = 0
|
||||
@@ -642,6 +645,21 @@ local function entry_key(entry)
|
||||
return entry.section .. "|" .. entry.path .. "|" .. (entry.orig or "")
|
||||
end
|
||||
|
||||
---Split `target_win` and put its buffer into the new window. Matches the
|
||||
---semantics of `:set_current_win(target); :rightbelow/leftabove vertical
|
||||
---split` (the new window inherits the target's buffer; caller swaps it
|
||||
---afterwards via `nvim_win_set_buf`).
|
||||
---@param target_win integer
|
||||
---@param dir "left"|"right"
|
||||
---@return integer
|
||||
local function vsplit_at(target_win, dir)
|
||||
return vim.api.nvim_open_win(
|
||||
vim.api.nvim_win_get_buf(target_win),
|
||||
true,
|
||||
{ split = dir, win = target_win }
|
||||
)
|
||||
end
|
||||
|
||||
---@param s ow.Git.StatusState
|
||||
---@param entry ow.Git.StatusEntry
|
||||
---@param focus_left boolean
|
||||
@@ -673,23 +691,17 @@ local function show_diff(s, entry, focus_left)
|
||||
end
|
||||
|
||||
if left_win and not right_win then
|
||||
vim.api.nvim_set_current_win(left_win)
|
||||
vim.cmd("rightbelow vertical split")
|
||||
right_win = vim.api.nvim_get_current_win()
|
||||
right_win = vsplit_at(left_win, "right")
|
||||
reset_diff_win(right_win)
|
||||
elseif right_win and not left_win then
|
||||
vim.api.nvim_set_current_win(right_win)
|
||||
vim.cmd("leftabove vertical split")
|
||||
left_win = vim.api.nvim_get_current_win()
|
||||
left_win = vsplit_at(right_win, "left")
|
||||
reset_diff_win(left_win)
|
||||
elseif not (left_win or right_win) then
|
||||
local default_main = find_default_main_win(sidebar_win)
|
||||
if default_main then
|
||||
right_win = default_main
|
||||
reset_diff_win(right_win)
|
||||
vim.api.nvim_set_current_win(default_main)
|
||||
vim.cmd("leftabove vertical split")
|
||||
left_win = vim.api.nvim_get_current_win()
|
||||
left_win = vsplit_at(right_win, "left")
|
||||
reset_diff_win(left_win)
|
||||
else
|
||||
-- No reusable default-empty window. Open the diff pair by
|
||||
@@ -697,12 +709,9 @@ local function show_diff(s, entry, focus_left)
|
||||
-- when there are other windows to absorb the split; if the
|
||||
-- sidebar is the only window in the tab, the split has to take
|
||||
-- from the sidebar itself, so restore the width explicitly.
|
||||
vim.api.nvim_set_current_win(sidebar_win)
|
||||
vim.cmd("rightbelow vertical split")
|
||||
right_win = vim.api.nvim_get_current_win()
|
||||
right_win = vsplit_at(sidebar_win, "right")
|
||||
reset_diff_win(right_win)
|
||||
vim.cmd("leftabove vertical split")
|
||||
left_win = vim.api.nvim_get_current_win()
|
||||
left_win = vsplit_at(right_win, "left")
|
||||
reset_diff_win(left_win)
|
||||
vim.api.nvim_win_set_width(sidebar_win, SIDEBAR_WIDTH)
|
||||
end
|
||||
@@ -756,13 +765,11 @@ local function action_stage()
|
||||
vim.system(
|
||||
{ "git", "add", "--", entry.path },
|
||||
{ cwd = s.worktree },
|
||||
function(obj)
|
||||
vim.schedule_wrap(function(obj)
|
||||
if obj.code ~= 0 then
|
||||
vim.schedule(function()
|
||||
log.error("git add failed: %s", vim.trim(obj.stderr or ""))
|
||||
end)
|
||||
log.error("git add failed: %s", vim.trim(obj.stderr or ""))
|
||||
end
|
||||
end
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -780,16 +787,18 @@ local function action_unstage()
|
||||
table.insert(cmd, entry.orig)
|
||||
end
|
||||
table.insert(cmd, entry.path)
|
||||
vim.system(cmd, { cwd = s.worktree }, function(obj)
|
||||
if obj.code ~= 0 then
|
||||
vim.schedule(function()
|
||||
vim.system(
|
||||
cmd,
|
||||
{ cwd = s.worktree },
|
||||
vim.schedule_wrap(function(obj)
|
||||
if obj.code ~= 0 then
|
||||
log.error(
|
||||
"git restore --staged failed: %s",
|
||||
vim.trim(obj.stderr or "")
|
||||
)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
local function action_discard()
|
||||
@@ -828,16 +837,14 @@ local function action_discard()
|
||||
vim.system(
|
||||
{ "git", "checkout", "--", entry.path },
|
||||
{ cwd = s.worktree },
|
||||
function(obj)
|
||||
vim.schedule_wrap(function(obj)
|
||||
if obj.code ~= 0 then
|
||||
vim.schedule(function()
|
||||
log.error(
|
||||
"git checkout failed: %s",
|
||||
vim.trim(obj.stderr or "")
|
||||
)
|
||||
end)
|
||||
log.error(
|
||||
"git checkout failed: %s",
|
||||
vim.trim(obj.stderr or "")
|
||||
)
|
||||
end
|
||||
end
|
||||
end)
|
||||
)
|
||||
end
|
||||
else
|
||||
@@ -875,15 +882,8 @@ local function open(worktree)
|
||||
end
|
||||
|
||||
local previous_win = vim.api.nvim_get_current_win()
|
||||
vim.cmd("leftabove vertical new")
|
||||
local win = vim.api.nvim_get_current_win()
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
|
||||
vim.bo[bufnr].buftype = "nofile"
|
||||
vim.bo[bufnr].bufhidden = "wipe"
|
||||
vim.bo[bufnr].swapfile = false
|
||||
local bufnr, win = git.new_scratch({ split = "left", bufhidden = "wipe" })
|
||||
vim.bo[bufnr].filetype = "gitstatus"
|
||||
vim.bo[bufnr].modifiable = false
|
||||
|
||||
vim.wo[win].number = false
|
||||
vim.wo[win].relativenumber = false
|
||||
|
||||
Reference in New Issue
Block a user