perf(git): run rev-parse and git show <commit> sync
This commit is contained in:
+16
-27
@@ -74,13 +74,11 @@ end
|
|||||||
---@param user_ref string
|
---@param user_ref string
|
||||||
---@param path string
|
---@param path string
|
||||||
local function show_file_in_split(worktree, user_ref, path)
|
local function show_file_in_split(worktree, user_ref, path)
|
||||||
repo.rev_parse(worktree, user_ref, true, function(sha)
|
local label = repo.rev_parse(worktree, user_ref, true) or user_ref
|
||||||
local label = sha or user_ref
|
local uri = "git://" .. label .. "//" .. path
|
||||||
local uri = "git://" .. label .. "//" .. path
|
local buf = vim.fn.bufadd(uri)
|
||||||
local buf = vim.fn.bufadd(uri)
|
vim.b[buf].git_worktree = worktree
|
||||||
vim.b[buf].git_worktree = worktree
|
vim.cmd("split " .. vim.fn.fnameescape(uri))
|
||||||
vim.cmd("split " .. vim.fn.fnameescape(uri))
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param worktree string
|
---@param worktree string
|
||||||
@@ -105,27 +103,18 @@ local function run_in_split(worktree, args, conf)
|
|||||||
vim.b[buf].git_worktree = worktree
|
vim.b[buf].git_worktree = worktree
|
||||||
if conf.needs_ref then
|
if conf.needs_ref then
|
||||||
local user_ref = first_positional(args, 2) or "HEAD"
|
local user_ref = first_positional(args, 2) or "HEAD"
|
||||||
local function apply_name(label)
|
local sha = repo.rev_parse(worktree, user_ref, true)
|
||||||
if not vim.api.nvim_buf_is_valid(buf) then
|
if sha then
|
||||||
return
|
vim.b[buf].git_ref = sha
|
||||||
end
|
vim.b[buf].git_parent_ref =
|
||||||
pcall(vim.api.nvim_buf_set_name, buf, "git://" .. label .. "//")
|
repo.rev_parse(worktree, user_ref .. "^", true)
|
||||||
vim.bo[buf].filetype = conf.ft
|
|
||||||
end
|
end
|
||||||
repo.rev_parse(worktree, user_ref, true, function(sha)
|
pcall(
|
||||||
if not sha then
|
vim.api.nvim_buf_set_name,
|
||||||
apply_name(user_ref)
|
buf,
|
||||||
return
|
"git://" .. (sha or user_ref) .. "//"
|
||||||
end
|
)
|
||||||
repo.rev_parse(worktree, user_ref .. "^", true, function(parent)
|
vim.bo[buf].filetype = conf.ft
|
||||||
if not vim.api.nvim_buf_is_valid(buf) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
vim.b[buf].git_ref = sha
|
|
||||||
vim.b[buf].git_parent_ref = parent
|
|
||||||
apply_name(sha)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
else
|
else
|
||||||
vim.bo[buf].filetype = conf.ft
|
vim.bo[buf].filetype = conf.ft
|
||||||
end
|
end
|
||||||
|
|||||||
+12
-21
@@ -322,35 +322,26 @@ function M.head(path)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
---Resolve a git revision to its object SHA. Calls `callback(sha?)` on the
|
---Resolve a git revision to its object SHA. Returns nil if the ref can't
|
||||||
---main loop with nil if the ref can't be parsed (root-commit's `^`, blob's
|
---be parsed (root-commit's `^`, blob's `^`, malformed ref, etc.). When
|
||||||
---`^`, malformed ref, etc.). When `short` is true, the result is abbreviated
|
---`short` is true, the result is abbreviated via `core.abbrev`
|
||||||
---via `core.abbrev` (auto-extended by git to keep the prefix unique in the
|
---(auto-extended by git to keep the prefix unique in the current repo).
|
||||||
---current repo).
|
|
||||||
---@param worktree string
|
---@param worktree string
|
||||||
---@param ref string
|
---@param ref string
|
||||||
---@param short boolean
|
---@param short boolean
|
||||||
---@param callback fun(sha: string?)
|
---@return string?
|
||||||
function M.rev_parse(worktree, ref, short, callback)
|
function M.rev_parse(worktree, ref, short)
|
||||||
local cmd = { "git", "rev-parse", "--verify", "--quiet" }
|
local cmd = { "git", "rev-parse", "--verify", "--quiet" }
|
||||||
if short then
|
if short then
|
||||||
table.insert(cmd, "--short")
|
table.insert(cmd, "--short")
|
||||||
end
|
end
|
||||||
table.insert(cmd, ref)
|
table.insert(cmd, ref)
|
||||||
vim.system(
|
local result = vim.system(cmd, { cwd = worktree, text = true }):wait()
|
||||||
cmd,
|
if result.code ~= 0 then
|
||||||
{ cwd = worktree, text = true },
|
return nil
|
||||||
vim.schedule_wrap(function(result)
|
end
|
||||||
local sha
|
local trimmed = vim.trim(result.stdout or "")
|
||||||
if result.code == 0 then
|
return trimmed ~= "" and trimmed or nil
|
||||||
local trimmed = vim.trim(result.stdout or "")
|
|
||||||
if trimmed ~= "" then
|
|
||||||
sha = trimmed
|
|
||||||
end
|
|
||||||
end
|
|
||||||
callback(sha)
|
|
||||||
end)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
+40
-59
@@ -135,68 +135,49 @@ end
|
|||||||
---@param opts ow.Git.OpenCommitOpts?
|
---@param opts ow.Git.OpenCommitOpts?
|
||||||
function M.open_commit(worktree, ref, opts)
|
function M.open_commit(worktree, ref, opts)
|
||||||
local split = opts and opts.split
|
local split = opts and opts.split
|
||||||
repo.rev_parse(worktree, ref, true, function(resolved)
|
local sha = repo.rev_parse(worktree, ref, true) or ref
|
||||||
local sha = resolved or ref
|
local name = "git://" .. sha .. "//"
|
||||||
local name = "git://" .. sha .. "//"
|
-- Commit SHAs are immutable so a previously-opened buffer is still
|
||||||
-- Reuse a previously-opened buffer for the same commit; commit SHAs
|
-- valid. Reuse it instead of refetching.
|
||||||
-- are immutable so the content is stable.
|
local existing = vim.fn.bufnr(name)
|
||||||
local existing = vim.fn.bufnr(name)
|
if existing ~= -1 and vim.api.nvim_buf_is_loaded(existing) then
|
||||||
if existing ~= -1 and vim.api.nvim_buf_is_loaded(existing) then
|
if split == false then
|
||||||
if split == false then
|
vim.cmd.normal({ "m'", bang = true })
|
||||||
vim.cmd.normal({ "m'", bang = true })
|
vim.api.nvim_set_current_buf(existing)
|
||||||
vim.api.nvim_set_current_buf(existing)
|
else
|
||||||
else
|
vim.api.nvim_open_win(existing, true, {
|
||||||
vim.api.nvim_open_win(existing, true, {
|
split = split or (vim.o.splitbelow and "below" or "above"),
|
||||||
split = split or (vim.o.splitbelow and "below" or "above"),
|
})
|
||||||
})
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local buf, win = git.new_scratch({ name = name, split = split })
|
local result = vim.system(
|
||||||
vim.b[buf].git_worktree = worktree
|
{ "git", "show", ref },
|
||||||
vim.b[buf].git_ref = sha
|
{ cwd = worktree, text = true }
|
||||||
|
)
|
||||||
|
:wait()
|
||||||
|
if result.code ~= 0 then
|
||||||
|
log.error("git show %s failed: %s", ref, vim.trim(result.stderr or ""))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
vim.system(
|
local parent = repo.rev_parse(worktree, ref .. "^", true)
|
||||||
{ "git", "show", ref },
|
local buf, _ = git.new_scratch({ name = name, split = split })
|
||||||
{ cwd = worktree, text = true },
|
vim.b[buf].git_worktree = worktree
|
||||||
vim.schedule_wrap(function(result)
|
vim.b[buf].git_ref = sha
|
||||||
if result.code ~= 0 then
|
vim.b[buf].git_parent_ref = parent
|
||||||
log.error(
|
vim.bo[buf].modifiable = true
|
||||||
"git show %s failed: %s",
|
vim.api.nvim_buf_set_lines(
|
||||||
ref,
|
buf,
|
||||||
vim.trim(result.stderr or "")
|
0,
|
||||||
)
|
-1,
|
||||||
-- Drop the empty placeholder so a retry runs a fresh
|
false,
|
||||||
-- fetch. With `split = false` the window falls back to
|
util.split_lines(result.stdout or "")
|
||||||
-- its alternate buffer (the gitlog); for a real split
|
)
|
||||||
-- we close the dedicated window to keep the layout tidy.
|
vim.bo[buf].modifiable = false
|
||||||
if split ~= false and vim.api.nvim_win_is_valid(win) then
|
vim.bo[buf].modified = false
|
||||||
pcall(vim.api.nvim_win_close, win, true)
|
vim.bo[buf].filetype = "git"
|
||||||
end
|
|
||||||
if vim.api.nvim_buf_is_valid(buf) then
|
|
||||||
vim.api.nvim_buf_delete(buf, { force = true })
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if not vim.api.nvim_buf_is_valid(buf) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local lines = util.split_lines(result.stdout or "")
|
|
||||||
repo.rev_parse(worktree, ref .. "^", true, function(parent)
|
|
||||||
if not vim.api.nvim_buf_is_valid(buf) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
vim.b[buf].git_parent_ref = parent
|
|
||||||
vim.bo[buf].modifiable = true
|
|
||||||
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
|
|
||||||
vim.bo[buf].modifiable = false
|
|
||||||
vim.bo[buf].modified = false
|
|
||||||
vim.bo[buf].filetype = "git"
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
)
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return boolean dispatched true if the cursor was on an actionable line
|
---@return boolean dispatched true if the cursor was on an actionable line
|
||||||
|
|||||||
Reference in New Issue
Block a user