refactor(git): convert blocking subprocess calls to async
This commit is contained in:
+50
-50
@@ -1,7 +1,9 @@
|
||||
local log = require("log")
|
||||
local util = require("util")
|
||||
|
||||
local UNMERGED = {
|
||||
local M = {}
|
||||
|
||||
M.UNMERGED = {
|
||||
DD = true,
|
||||
AU = true,
|
||||
UD = true,
|
||||
@@ -14,7 +16,7 @@ local UNMERGED = {
|
||||
---@param code string porcelain v1 XY code
|
||||
---@return string? char
|
||||
---@return string? hl_group
|
||||
local function indicator(code)
|
||||
function M.indicator(code)
|
||||
if code == "" then
|
||||
return nil
|
||||
end
|
||||
@@ -24,7 +26,7 @@ local function indicator(code)
|
||||
if code == "!!" then
|
||||
return "!", "GitIgnored"
|
||||
end
|
||||
if UNMERGED[code] then
|
||||
if M.UNMERGED[code] then
|
||||
return "U", "GitUnmerged"
|
||||
end
|
||||
local x, y = code:sub(1, 1), code:sub(2, 2)
|
||||
@@ -43,7 +45,7 @@ end
|
||||
---@param code string
|
||||
---@return string?
|
||||
local function format(code)
|
||||
local char, hl = indicator(code)
|
||||
local char, hl = M.indicator(code)
|
||||
if not char then
|
||||
return nil
|
||||
end
|
||||
@@ -53,7 +55,7 @@ end
|
||||
---@param path string
|
||||
---@return string? gitdir
|
||||
---@return string? worktree
|
||||
local function resolve(path)
|
||||
function M.resolve(path)
|
||||
local found = vim.fs.find(".git", { upward = true, path = path })[1]
|
||||
if not found then
|
||||
return nil
|
||||
@@ -88,12 +90,12 @@ end
|
||||
---both when not inside a git repo.
|
||||
---@return string? gitdir
|
||||
---@return string? worktree
|
||||
local function resolve_cwd()
|
||||
function M.resolve_cwd()
|
||||
local path = vim.api.nvim_buf_get_name(0)
|
||||
if path == "" then
|
||||
path = vim.fn.getcwd()
|
||||
end
|
||||
return resolve(path)
|
||||
return M.resolve(path)
|
||||
end
|
||||
|
||||
---@class ow.Git.Repo
|
||||
@@ -152,15 +154,17 @@ local function do_refresh(repo)
|
||||
-- path lines, so it ignores `##` lines below. Running with `--branch`
|
||||
-- lets the sidebar reuse this single subprocess via the GitRefresh
|
||||
-- data payload instead of spawning its own.
|
||||
vim.system({
|
||||
"git",
|
||||
"-c",
|
||||
"core.quotePath=false",
|
||||
"status",
|
||||
"--porcelain=v1",
|
||||
"--branch",
|
||||
}, { cwd = repo.worktree, text = true }, function(obj)
|
||||
vim.schedule(function()
|
||||
vim.system(
|
||||
{
|
||||
"git",
|
||||
"-c",
|
||||
"core.quotePath=false",
|
||||
"status",
|
||||
"--porcelain=v1",
|
||||
"--branch",
|
||||
},
|
||||
{ cwd = repo.worktree, text = true },
|
||||
vim.schedule_wrap(function(obj)
|
||||
local statuses = {}
|
||||
if obj.code == 0 then
|
||||
for line in (obj.stdout or ""):gmatch("[^\r\n]+") do
|
||||
@@ -210,7 +214,7 @@ local function do_refresh(repo)
|
||||
},
|
||||
})
|
||||
end)
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
---@param gitdir string
|
||||
@@ -244,7 +248,7 @@ local function register(buf)
|
||||
if path == "" then
|
||||
return nil
|
||||
end
|
||||
local gitdir, worktree = resolve(path)
|
||||
local gitdir, worktree = M.resolve(path)
|
||||
if not gitdir or not worktree then
|
||||
return nil
|
||||
end
|
||||
@@ -259,7 +263,7 @@ local function register(buf)
|
||||
end
|
||||
|
||||
---@param buf integer
|
||||
local function unregister(buf)
|
||||
function M.unregister(buf)
|
||||
local repo = repo_by_buf[buf]
|
||||
if not repo then
|
||||
return
|
||||
@@ -273,7 +277,7 @@ local function unregister(buf)
|
||||
end
|
||||
|
||||
---@param buf integer
|
||||
local function refresh_buf(buf)
|
||||
function M.refresh_buf(buf)
|
||||
if not vim.api.nvim_buf_is_valid(buf) or vim.bo[buf].buftype ~= "" then
|
||||
return
|
||||
end
|
||||
@@ -285,7 +289,7 @@ local function refresh_buf(buf)
|
||||
repo:refresh()
|
||||
end
|
||||
|
||||
local function stop_all()
|
||||
function M.stop_all()
|
||||
for _, repo in pairs(repo_by_gitdir) do
|
||||
repo:stop_watcher()
|
||||
end
|
||||
@@ -293,8 +297,8 @@ end
|
||||
|
||||
---@param path string
|
||||
---@return string?
|
||||
local function head(path)
|
||||
local gitdir = resolve(path)
|
||||
function M.head(path)
|
||||
local gitdir = M.resolve(path)
|
||||
if not gitdir then
|
||||
return nil
|
||||
end
|
||||
@@ -318,39 +322,35 @@ local function head(path)
|
||||
return nil
|
||||
end
|
||||
|
||||
---Resolve a git revision to its object SHA. Returns nil if the ref can't be
|
||||
---resolved (root-commit's `^`, blob's `^`, malformed ref, etc.). When `short`
|
||||
---is true, the result is abbreviated via `core.abbrev` (auto-extended by git
|
||||
---to keep the prefix unique in the current repo).
|
||||
---Resolve a git revision to its object SHA. Calls `callback(sha?)` on the
|
||||
---main loop with nil if the ref can't be parsed (root-commit's `^`, blob's
|
||||
---`^`, malformed ref, etc.). When `short` is true, the result is abbreviated
|
||||
---via `core.abbrev` (auto-extended by git to keep the prefix unique in the
|
||||
---current repo).
|
||||
---@param worktree string
|
||||
---@param ref string
|
||||
---@param short? boolean
|
||||
---@return string?
|
||||
local function rev_parse(worktree, ref, short)
|
||||
---@param short boolean
|
||||
---@param callback fun(sha: string?)
|
||||
function M.rev_parse(worktree, ref, short, callback)
|
||||
local cmd = { "git", "rev-parse", "--verify", "--quiet" }
|
||||
if short then
|
||||
table.insert(cmd, "--short")
|
||||
end
|
||||
table.insert(cmd, ref)
|
||||
local result = vim.system(cmd, { cwd = worktree, text = true }):wait()
|
||||
if result.code ~= 0 then
|
||||
return nil
|
||||
end
|
||||
local sha = vim.trim(result.stdout or "")
|
||||
if sha == "" then
|
||||
return nil
|
||||
end
|
||||
return sha
|
||||
vim.system(
|
||||
cmd,
|
||||
{ cwd = worktree, text = true },
|
||||
vim.schedule_wrap(function(result)
|
||||
local sha
|
||||
if result.code == 0 then
|
||||
local trimmed = vim.trim(result.stdout or "")
|
||||
if trimmed ~= "" then
|
||||
sha = trimmed
|
||||
end
|
||||
end
|
||||
callback(sha)
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
return {
|
||||
UNMERGED = UNMERGED,
|
||||
head = head,
|
||||
indicator = indicator,
|
||||
refresh_buf = refresh_buf,
|
||||
resolve = resolve,
|
||||
resolve_cwd = resolve_cwd,
|
||||
rev_parse = rev_parse,
|
||||
stop_all = stop_all,
|
||||
unregister = unregister,
|
||||
}
|
||||
return M
|
||||
|
||||
Reference in New Issue
Block a user