refactor(git): unify around the Repo abstraction
This commit is contained in:
+32
-45
@@ -32,14 +32,13 @@ local SIDEBAR_WIDTH = 50
|
||||
---@alias ow.Git.SidebarEntry ow.Git.FileEntry | ow.Git.CommitEntry
|
||||
|
||||
---@class ow.Git.SidebarState
|
||||
---@field gitdir string
|
||||
---@field worktree string
|
||||
---@field repo ow.Git.Repo
|
||||
---@field lines table<integer, ow.Git.SidebarEntry>
|
||||
---@field sidebar_win integer?
|
||||
---@field invocation_win integer?
|
||||
---@field diff_left_win integer?
|
||||
---@field diff_right_win integer?
|
||||
---@field user_aucmd integer?
|
||||
---@field unsubscribe fun()?
|
||||
---@field last_shown_key string?
|
||||
---@field last_render_key string?
|
||||
|
||||
@@ -407,7 +406,7 @@ local function refresh(bufnr, prefetched_stdout)
|
||||
end
|
||||
end
|
||||
|
||||
fetch_status(s.worktree, prefetched_stdout, function(branch, groups)
|
||||
fetch_status(s.repo.worktree, prefetched_stdout, function(branch, groups)
|
||||
if not vim.api.nvim_buf_is_valid(bufnr) then
|
||||
return
|
||||
end
|
||||
@@ -456,22 +455,22 @@ end
|
||||
---@field left ow.Git.DiffSide
|
||||
---@field right ow.Git.DiffSide
|
||||
|
||||
---@param worktree string
|
||||
---@param r ow.Git.Repo
|
||||
---@param path string
|
||||
---@return ow.Git.DiffSide
|
||||
local function head_pane(worktree, path)
|
||||
local function head_pane(r, path)
|
||||
local rev = Revision.new({ base = "HEAD", path = path })
|
||||
return {
|
||||
buf = object.buf_for(worktree, rev),
|
||||
name = rev:uri(),
|
||||
buf = object.buf_for(r, rev),
|
||||
name = object.format_uri(rev),
|
||||
}
|
||||
end
|
||||
|
||||
---@param worktree string
|
||||
---@param r ow.Git.Repo
|
||||
---@param path string
|
||||
---@return ow.Git.DiffSide
|
||||
local function worktree_pane(worktree, path)
|
||||
local buf = vim.fn.bufadd(vim.fs.joinpath(worktree, path))
|
||||
local function worktree_pane(r, path)
|
||||
local buf = vim.fn.bufadd(vim.fs.joinpath(r.worktree, path))
|
||||
vim.fn.bufload(buf)
|
||||
return { buf = buf, name = nil }
|
||||
end
|
||||
@@ -482,8 +481,8 @@ end
|
||||
local function index_pane(s, entry)
|
||||
local rev = Revision.new({ stage = 0, path = entry.path })
|
||||
return {
|
||||
buf = object.buf_for(s.worktree, rev),
|
||||
name = rev:uri(),
|
||||
buf = object.buf_for(s.repo, rev),
|
||||
name = object.format_uri(rev),
|
||||
}
|
||||
end
|
||||
|
||||
@@ -495,7 +494,7 @@ local function older_pane(s, entry)
|
||||
if entry.x == "A" then
|
||||
return nil
|
||||
end
|
||||
return head_pane(s.worktree, entry.orig or entry.path)
|
||||
return head_pane(s.repo, entry.orig or entry.path)
|
||||
end
|
||||
if entry.section == "Unstaged" then
|
||||
return index_pane(s, entry)
|
||||
@@ -517,10 +516,10 @@ local function newer_pane(s, entry)
|
||||
if entry.y == "D" then
|
||||
return nil
|
||||
end
|
||||
return worktree_pane(s.worktree, entry.path)
|
||||
return worktree_pane(s.repo, entry.path)
|
||||
end
|
||||
if entry.section == "Untracked" then
|
||||
return worktree_pane(s.worktree, entry.path)
|
||||
return worktree_pane(s.repo, entry.path)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
@@ -695,8 +694,9 @@ local function view_entry(s, entry, focus_left)
|
||||
+ vim.api.nvim_win_get_width(right_win)
|
||||
vim.api.nvim_win_set_width(left_win, math.floor(combined / 2))
|
||||
end
|
||||
---@cast left_win -nil
|
||||
---@cast right_win -nil
|
||||
|
||||
assert(left_win and right_win, "diff windows must be set")
|
||||
vim.w[left_win].git_diff_role = "left"
|
||||
vim.w[right_win].git_diff_role = "right"
|
||||
s.diff_left_win = left_win
|
||||
@@ -728,7 +728,7 @@ local function action_stage()
|
||||
end
|
||||
vim.system(
|
||||
{ "git", "add", "--", entry.path },
|
||||
{ cwd = s.worktree },
|
||||
{ cwd = s.repo.worktree },
|
||||
vim.schedule_wrap(function(obj)
|
||||
if obj.code ~= 0 then
|
||||
util.error("git add failed: %s", vim.trim(obj.stderr or ""))
|
||||
@@ -753,7 +753,7 @@ local function action_unstage()
|
||||
table.insert(cmd, entry.path)
|
||||
vim.system(
|
||||
cmd,
|
||||
{ cwd = s.worktree },
|
||||
{ cwd = s.repo.worktree },
|
||||
vim.schedule_wrap(function(obj)
|
||||
if obj.code ~= 0 then
|
||||
util.error(
|
||||
@@ -785,7 +785,7 @@ local function action_discard()
|
||||
entry.path
|
||||
)
|
||||
action = function()
|
||||
local target = vim.fs.joinpath(s.worktree, entry.path)
|
||||
local target = vim.fs.joinpath(s.repo.worktree, entry.path)
|
||||
local rc = vim.fn.delete(target, is_dir and "rf" or "")
|
||||
if rc ~= 0 then
|
||||
util.error("failed to delete %s", entry.path)
|
||||
@@ -797,7 +797,7 @@ local function action_discard()
|
||||
action = function()
|
||||
vim.system(
|
||||
{ "git", "checkout", "--", entry.path },
|
||||
{ cwd = s.worktree },
|
||||
{ cwd = s.repo.worktree },
|
||||
vim.schedule_wrap(function(obj)
|
||||
if obj.code ~= 0 then
|
||||
util.error(
|
||||
@@ -829,20 +829,14 @@ local function action_help()
|
||||
}, "\n"))
|
||||
end
|
||||
|
||||
---@param worktree string
|
||||
local function open(worktree)
|
||||
---@param r ow.Git.Repo
|
||||
local function open(r)
|
||||
local existing = find_sidebar()
|
||||
if existing then
|
||||
vim.api.nvim_set_current_win(existing)
|
||||
return
|
||||
end
|
||||
|
||||
local gitdir, worktree = repo.resolve(worktree)
|
||||
if not gitdir then
|
||||
return
|
||||
end
|
||||
---@cast worktree -nil
|
||||
|
||||
local previous_win = vim.api.nvim_get_current_win()
|
||||
local bufnr, win = util.new_scratch({ split = "left" })
|
||||
vim.bo[bufnr].filetype = "gitsidebar"
|
||||
@@ -856,8 +850,7 @@ local function open(worktree)
|
||||
vim.api.nvim_win_set_width(win, SIDEBAR_WIDTH)
|
||||
|
||||
state[bufnr] = {
|
||||
gitdir = gitdir,
|
||||
worktree = worktree,
|
||||
repo = r,
|
||||
lines = {},
|
||||
sidebar_win = win,
|
||||
invocation_win = previous_win,
|
||||
@@ -882,15 +875,9 @@ local function open(worktree)
|
||||
k("X", action_discard, "Discard worktree changes")
|
||||
k("g?", action_help, "Help")
|
||||
|
||||
state[bufnr].user_aucmd = vim.api.nvim_create_autocmd("User", {
|
||||
pattern = "GitRefresh",
|
||||
group = group,
|
||||
callback = function(args)
|
||||
if args.data and args.data.gitdir == gitdir then
|
||||
refresh(bufnr, args.data.porcelain_stdout)
|
||||
end
|
||||
end,
|
||||
})
|
||||
state[bufnr].unsubscribe = r:on_refresh(function(_, porcelain_stdout)
|
||||
refresh(bufnr, porcelain_stdout)
|
||||
end)
|
||||
vim.api.nvim_create_autocmd({ "BufWipeout", "BufDelete" }, {
|
||||
buffer = bufnr,
|
||||
group = group,
|
||||
@@ -899,8 +886,8 @@ local function open(worktree)
|
||||
if not s then
|
||||
return
|
||||
end
|
||||
if s.user_aucmd then
|
||||
pcall(vim.api.nvim_del_autocmd, s.user_aucmd)
|
||||
if s.unsubscribe then
|
||||
s.unsubscribe()
|
||||
end
|
||||
state[bufnr] = nil
|
||||
end,
|
||||
@@ -916,12 +903,12 @@ function M.toggle()
|
||||
vim.api.nvim_win_close(sidebar_win, false)
|
||||
return
|
||||
end
|
||||
local _, worktree = repo.current_repo()
|
||||
if not worktree then
|
||||
local r = repo.find()
|
||||
if not r then
|
||||
util.warning("not in a git repository")
|
||||
return
|
||||
end
|
||||
open(worktree)
|
||||
open(r)
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
Reference in New Issue
Block a user