refactor(git): introduce Revision class, normalize naming, slim docs

This commit is contained in:
2026-04-30 09:44:24 +02:00
parent 775add9b15
commit d95de4bc1d
10 changed files with 244 additions and 428 deletions
+14 -26
View File
@@ -7,9 +7,8 @@ local M = {}
---@class ow.Git.SplitHandler
---@field ft string
---@field needs_ref boolean?
---@field needs_rev boolean?
---Subcommands whose output goes to a buffer.
---@type table<string, ow.Git.SplitHandler>
local SPLIT_HANDLERS = {
log = { ft = "git" },
@@ -34,7 +33,6 @@ local function populate_cached_cmds(result)
table.sort(cached_cmds)
end
---Prime `cached_cmds` asynchronously so the first `:G <Tab>` doesn't block.
local function prefetch_cmds()
vim.system(
{ "git", "--list-cmds=main,others,alias" },
@@ -85,10 +83,6 @@ local function place_split(name)
return buf
end
---Run `git <args>` async. On success, drop the output into a named
---scratch split (creating or reusing as needed). On failure, `util.exec`
---notifies and the split is never opened, so a bad ref doesn't leave a
---stray buffer behind.
---@param worktree string
---@param args string[]
---@param conf ow.Git.SplitHandler
@@ -104,15 +98,15 @@ local function run_in_split(worktree, args, conf)
local name = "[git " .. table.concat(args, " ") .. "]"
local buf = place_split(name)
vim.b[buf].git_worktree = worktree
vim.b[buf].git_ref = nil
vim.b[buf].git_parent_ref = nil
if conf.needs_ref then
local user_ref = first_positional(args, 2) or "HEAD"
local sha = repo.rev_parse(worktree, user_ref, true)
vim.b[buf].git_sha = nil
vim.b[buf].git_parent_sha = nil
if conf.needs_rev then
local user_rev = first_positional(args, 2) or "HEAD"
local sha = repo.rev_parse(worktree, user_rev, true)
if sha then
vim.b[buf].git_ref = sha
vim.b[buf].git_parent_ref =
repo.rev_parse(worktree, user_ref .. "^", true)
vim.b[buf].git_sha = sha
vim.b[buf].git_parent_sha =
repo.rev_parse(worktree, user_rev .. "^", true)
end
end
vim.bo[buf].filetype = conf.ft
@@ -206,31 +200,25 @@ function M.run(args)
return
end
-- `:G show <ref>:<path>` opens the blob via the BufReadCmd loader
-- so the URI carries the path and filetype detection has something
-- to match against. Other show invocations dump output to a buffer.
if sub == "show" then
local arg = first_positional(args, 2)
if arg and arg:find(":", 1, true) then
object.open_object(worktree, arg)
return
end
run_in_split(worktree, args, { ft = "git", needs_ref = true })
run_in_split(worktree, args, { ft = "git", needs_rev = true })
return
end
-- `:G cat-file -p <sha>` routes to the gitobject viewer so commits
-- get the full message + diff view and other types render via
-- cat-file. Other modes (-t, -s, -e) dump to a buffer.
if sub == "cat-file" then
if vim.list_contains(args, "-p") then
local ref = first_positional(args, 2)
if ref then
object.open_object(worktree, ref)
local rev = first_positional(args, 2)
if rev then
object.open_object(worktree, rev)
return
end
end
run_in_split(worktree, args, { ft = "git", needs_ref = true })
run_in_split(worktree, args, { ft = "git", needs_rev = true })
return
end