fix(git): preserve dispatch and content after jumping back

This commit is contained in:
2026-05-08 01:46:43 +02:00
parent 4649b803ab
commit 867b5c2a2e
4 changed files with 78 additions and 12 deletions
+5 -8
View File
@@ -47,14 +47,13 @@ local function fetch(worktree, max_count)
return util.exec(cmd, { cwd = worktree }) return util.exec(cmd, { cwd = worktree })
end end
---@type table<string, integer> -- worktree -> max_count
local max_counts = {}
---@param buf integer ---@param buf integer
---@param r ow.Git.Repo ---@param r ow.Git.Repo
local function populate(buf, r) local function populate(buf, r)
local state = r:state(buf) local stdout = fetch(r.worktree, max_counts[r.worktree])
if not state then
return
end
local stdout = fetch(r.worktree, state.log_max_count)
if not stdout then if not stdout then
return return
end end
@@ -123,10 +122,8 @@ function M.open(opts)
return return
end end
max_counts[r.worktree] = opts.max_count
local buf = vim.fn.bufadd(M.URI_PREFIX .. r.worktree) local buf = vim.fn.bufadd(M.URI_PREFIX .. r.worktree)
repo.bind(buf, r)
local state = r:state(buf) --[[@as -nil]]
state.log_max_count = opts.max_count
local was_loaded = vim.api.nvim_buf_is_loaded(buf) local was_loaded = vim.api.nvim_buf_is_loaded(buf)
local win = vim.fn.bufwinid(buf) local win = vim.fn.bufwinid(buf)
+2 -3
View File
@@ -375,13 +375,12 @@ end
---@return boolean dispatched ---@return boolean dispatched
function M.open_under_cursor() function M.open_under_cursor()
local s = repo.state() local r = repo.resolve()
if not s then if not r then
return false return false
end end
local line = vim.api.nvim_get_current_line() local line = vim.api.nvim_get_current_line()
local r = s.repo
local sha = line:match("^commit (%x+)$") local sha = line:match("^commit (%x+)$")
or line:match("^parent (%x+)$") or line:match("^parent (%x+)$")
-1
View File
@@ -19,7 +19,6 @@ end
---@field immutable boolean? ---@field immutable boolean?
---@field index_writer boolean? ---@field index_writer boolean?
---@field index_mode string? ---@field index_mode string?
---@field log_max_count integer?
---@alias ow.Git.Repo.Event "refresh" ---@alias ow.Git.Repo.Event "refresh"
+71
View File
@@ -316,6 +316,77 @@ t.test(":G show <CR> on + line opens the blob URI", function()
t.eq(vim.api.nvim_buf_get_name(0), "git://" .. blob) t.eq(vim.api.nvim_buf_get_name(0), "git://" .. blob)
end) end)
t.test("<leader>gl log buffer refills after jumping back", function()
local dir = make_repo({ a = "v1\n" })
t.write(dir, "a", "v2\n")
helpers.git(dir, "add", "a")
helpers.git(dir, "commit", "-q", "-m", "second")
require("git.log_view").open({ max_count = 1000 })
wait_buf_populated("^gitlog://")
local log_buf = vim.api.nvim_get_current_buf()
local log_win = vim.api.nvim_get_current_win()
t.truthy(
vim.api.nvim_buf_get_name(log_buf):match("^gitlog://")
)
local initial_lines =
#vim.api.nvim_buf_get_lines(log_buf, 0, -1, false)
t.truthy(initial_lines >= 2)
-- Step into a commit, then <C-o> back to the log.
vim.api.nvim_win_set_cursor(log_win, { 1, 0 })
local cr =
vim.api.nvim_replace_termcodes("<CR>", true, false, true)
vim.api.nvim_feedkeys(cr, "x", false)
t.truthy(vim.api.nvim_buf_get_name(0):match("^git://"))
local co =
vim.api.nvim_replace_termcodes("<C-o>", true, false, true)
vim.api.nvim_feedkeys(co, "x", false)
t.eq(vim.api.nvim_get_current_buf(), log_buf)
t.eq(
#vim.api.nvim_buf_get_lines(log_buf, 0, -1, false),
initial_lines,
"log buffer must repopulate on jump-back"
)
end)
t.test("<CR> still dispatches after navigating away and back", function()
local dir = make_repo({ a = "v1\n" })
t.write(dir, "a", "v2\n")
helpers.git(dir, "add", "a")
helpers.git(dir, "commit", "-q", "-m", "second")
-- Open the HEAD commit object buffer. Its cat-file output includes a
-- "parent <sha>" line we can navigate from.
local r = assert(require("git.repo").resolve(dir))
require("git.object").open(r, "HEAD", { split = false })
local first_obj_buf = vim.api.nvim_get_current_buf()
local first_obj_win = vim.api.nvim_get_current_win()
t.truthy(vim.api.nvim_buf_get_name(first_obj_buf):match("^git://"))
-- Step into the parent commit. This hides first_obj_buf which has
-- bufhidden=delete, so it gets unloaded.
local parent_lnum = assert(find_line(first_obj_buf, "parent "))
vim.api.nvim_win_set_cursor(first_obj_win, { parent_lnum, 0 })
t.truthy(require("git.object").open_under_cursor())
local parent_buf = vim.api.nvim_get_current_buf()
t.truthy(parent_buf ~= first_obj_buf)
-- <C-o> back to first_obj_buf. With bufhidden=delete, vim re-reads the
-- URI, which previously raced with BufDelete-driven unbind and left
-- state cleared, so open_under_cursor returned false.
local co = vim.api.nvim_replace_termcodes("<C-o>", true, false, true)
vim.api.nvim_feedkeys(co, "x", false)
t.eq(vim.api.nvim_get_current_buf(), first_obj_buf)
local tree_lnum = assert(find_line(first_obj_buf, "tree "))
vim.api.nvim_win_set_cursor(first_obj_win, { tree_lnum, 0 })
t.truthy(
require("git.object").open_under_cursor(),
"<CR> must work after returning to the buffer"
)
end)
t.test(":G diff <CR> on + line falls back to worktree file", function() t.test(":G diff <CR> on + line falls back to worktree file", function()
local dir = make_repo({ a = "v1\n" }) local dir = make_repo({ a = "v1\n" })
t.write(dir, "a", "v2\n") t.write(dir, "a", "v2\n")