chore: apply formatting

This commit is contained in:
2026-05-26 17:30:18 +02:00
parent 914aa493ff
commit 428ded2c4c
12 changed files with 305 additions and 280 deletions
+2 -6
View File
@@ -169,8 +169,7 @@ local function read_git_config(path)
section = s section = s
out[section] = out[section] or {} out[section] = out[section] or {}
elseif section then elseif section then
local key, value = local key, value = trimmed:match("^(%S+)%s*=%s*(.-)$")
trimmed:match("^(%S+)%s*=%s*(.-)$")
if key then if key then
out[section][key] = value out[section][key] = value
end end
@@ -225,10 +224,7 @@ function Repo:_fetch_status()
end end
self.status = status.parse(result.stdout or "") self.status = status.parse(result.stdout or "")
local change = { local change = {
paths = status.diff_entries( paths = status.diff_entries(prior_entries, self.status.entries),
prior_entries,
self.status.entries
),
branch_changed = not vim.deep_equal( branch_changed = not vim.deep_equal(
prior_branch, prior_branch,
self.status.branch self.status.branch
+5 -3
View File
@@ -489,8 +489,7 @@ local function recompute(buf)
state.head_sha = sha state.head_sha = sha
end, end,
function() function()
local new = local new = vim.api.nvim_buf_get_lines(buf, 0, -1, false)
vim.api.nvim_buf_get_lines(buf, 0, -1, false)
state.hunks = state.index state.hunks = state.index
and compute_hunks(state.index, new) and compute_hunks(state.index, new)
or {} or {}
@@ -524,7 +523,10 @@ function M.attach(buf)
if not r then if not r then
return return
end end
local rel = vim.fs.relpath(r.worktree, vim.fn.resolve(vim.api.nvim_buf_get_name(buf))) local rel = vim.fs.relpath(
r.worktree,
vim.fn.resolve(vim.api.nvim_buf_get_name(buf))
)
if not rel then if not rel then
return return
end end
+3 -1
View File
@@ -14,7 +14,9 @@ local function open_under_cursor(buf)
-- Anchor past the leading graph chars (matches the leading sha column, -- Anchor past the leading graph chars (matches the leading sha column,
-- not any hex word that happens to appear later in the subject). -- not any hex word that happens to appear later in the subject).
local sha = r local sha = r
and vim.api.nvim_get_current_line():match("^[*|/\\_ ]*(%x%x%x%x%x%x%x+)") and vim.api
.nvim_get_current_line()
:match("^[*|/\\_ ]*(%x%x%x%x%x%x%x+)")
if not sha then if not sha then
return false return false
end end
+2 -7
View File
@@ -38,8 +38,7 @@ end
---@type table<integer, ow.Git.StatusView.State> ---@type table<integer, ow.Git.StatusView.State>
local state = {} local state = {}
local group = local group = vim.api.nvim_create_augroup("ow.git.status_win", { clear = true })
vim.api.nvim_create_augroup("ow.git.status_win", { clear = true })
local ns = vim.api.nvim_create_namespace("ow.git.status_win") local ns = vim.api.nvim_create_namespace("ow.git.status_win")
---@return integer? win ---@return integer? win
@@ -349,11 +348,7 @@ local function view_row(s, row, focus_left)
local left = older_pane(s, row) local left = older_pane(s, row)
local right = newer_pane(s, row) local right = newer_pane(s, row)
if not left and not right then if not left and not right then
util.warning( util.warning("no content for %s row: %s", row.section, row.entry.path)
"no content for %s row: %s",
row.section,
row.entry.path
)
return return
end end
+2 -8
View File
@@ -20,10 +20,7 @@ local function render(entry)
end end
local parts = {} local parts = {}
for _, mark in ipairs(marks) do for _, mark in ipairs(marks) do
table.insert( table.insert(parts, string.format("%%#%s#%s%%*", mark.hl, mark.char))
parts,
string.format("%%#%s#%s%%*", mark.hl, mark.char)
)
end end
return table.concat(parts, " ") return table.concat(parts, " ")
end end
@@ -73,10 +70,7 @@ repo.on("change", function(r)
local rel = vim.fs.relpath(r.worktree, vim.fn.resolve(name)) local rel = vim.fs.relpath(r.worktree, vim.fn.resolve(name))
if rel then if rel then
set_status(buf, r, rel) set_status(buf, r, rel)
if if not any_visible and #vim.fn.win_findbuf(buf) > 0 then
not any_visible
and #vim.fn.win_findbuf(buf) > 0
then
any_visible = true any_visible = true
end end
end end
-1
View File
@@ -336,4 +336,3 @@ end, {
silent = true, silent = true,
desc = "Open this file at the parent of the line's commit", desc = "Open this file at the parent of the line's commit",
}) })
+1 -2
View File
@@ -548,8 +548,7 @@ t.test("streaming :G fetch (no bang) does not open a window", function()
local before = #vim.api.nvim_tabpage_list_wins(0) local before = #vim.api.nvim_tabpage_list_wins(0)
cmd.run({ "fetch" }) cmd.run({ "fetch" })
t.wait_for(function() t.wait_for(function()
return has_status(calls, "failed") return has_status(calls, "failed") or has_status(calls, "success")
or has_status(calls, "success")
end, "streaming job to terminate", 5000) end, "streaming job to terminate", 5000)
t.eq(#vim.api.nvim_tabpage_list_wins(0), before, "no new window") t.eq(#vim.api.nvim_tabpage_list_wins(0), before, "no new window")
t.falsy(find_preview_win(), "no preview window") t.falsy(find_preview_win(), "no preview window")
+55 -47
View File
@@ -29,9 +29,11 @@ end
local function sign_marks(buf) local function sign_marks(buf)
local ns = vim.api.nvim_get_namespaces()["ow.git.hunks"] local ns = vim.api.nvim_get_namespaces()["ow.git.hunks"]
local out = {} local out = {}
for _, m in ipairs(vim.api.nvim_buf_get_extmarks(buf, ns, 0, -1, { for _, m in
details = true, ipairs(vim.api.nvim_buf_get_extmarks(buf, ns, 0, -1, {
})) do details = true,
}))
do
local d = assert(m[4]) local d = assert(m[4])
table.insert(out, { table.insert(out, {
row = m[2], row = m[2],
@@ -167,7 +169,10 @@ t.test("overlay: change hunk shows deletion and addition", function()
t.eq(add_d.line_hl_group, "GitHunkAddLine") t.eq(add_d.line_hl_group, "GitHunkAddLine")
virt_d = assert(virt_d, "the deletion should render as virtual lines") virt_d = assert(virt_d, "the deletion should render as virtual lines")
local piece = assert(assert(assert(virt_d.virt_lines)[1])[1]) local piece = assert(assert(assert(virt_d.virt_lines)[1])[1])
t.truthy(vim.startswith(piece[1], "b"), "deleted line shows the old content") t.truthy(
vim.startswith(piece[1], "b"),
"deleted line shows the old content"
)
t.eq(piece[2], "GitHunkDeleteLine") t.eq(piece[2], "GitHunkDeleteLine")
end) end)
@@ -197,11 +202,8 @@ t.test("overlay: add hunk highlights the added lines", function()
end) end)
t.test("overlay: deleted lines are treesitter-highlighted", function() t.test("overlay: deleted lines are treesitter-highlighted", function()
local _, buf = setup( local _, buf =
"-- a note\nlocal x = 1\nlocal y = 2\n", setup("-- a note\nlocal x = 1\nlocal y = 2\n", "local y = 2\n", "a.lua")
"local y = 2\n",
"a.lua"
)
t.truthy( t.truthy(
pcall(vim.treesitter.start, buf, "lua"), pcall(vim.treesitter.start, buf, "lua"),
"the lua parser should be available" "the lua parser should be available"
@@ -437,22 +439,25 @@ t.test("toggle_stage unstages one of two adjacent staged hunks", function()
) )
end) end)
t.test("toggle_stage refreshes the gutter when status stays modified", function() t.test(
local _, buf = setup("a\nb\nc\nd\ne\n", "A\nb\nC\nd\nE\n") "toggle_stage refreshes the gutter when status stays modified",
t.eq(#assert(hunks.state(buf)).hunks, 3) function()
local _, buf = setup("a\nb\nc\nd\ne\n", "A\nb\nC\nd\nE\n")
t.eq(#assert(hunks.state(buf)).hunks, 3)
vim.api.nvim_win_set_cursor(0, { 1, 0 }) vim.api.nvim_win_set_cursor(0, { 1, 0 })
hunks.toggle_stage(buf) hunks.toggle_stage(buf)
t.wait_for(function() t.wait_for(function()
return #assert(hunks.state(buf)).hunks == 2 return #assert(hunks.state(buf)).hunks == 2
end, "gutter to drop the first staged hunk") end, "gutter to drop the first staged hunk")
vim.api.nvim_win_set_cursor(0, { 3, 0 }) vim.api.nvim_win_set_cursor(0, { 3, 0 })
hunks.toggle_stage(buf) hunks.toggle_stage(buf)
t.wait_for(function() t.wait_for(function()
return #assert(hunks.state(buf)).hunks == 1 return #assert(hunks.state(buf)).hunks == 1
end, "gutter to drop the middle staged hunk") end, "gutter to drop the middle staged hunk")
end) end
)
t.test("staged hunks show with the staged highlight", function() t.test("staged hunks show with the staged highlight", function()
local _, buf = setup("a\nb\nc\n", "a\nB\nc\n") local _, buf = setup("a\nb\nc\n", "a\nB\nc\n")
@@ -499,32 +504,35 @@ t.test("toggle_stage toggles a staged hunk back to unstaged", function()
}) })
end) end)
t.test("toggle_stage unstages correctly when buffer lines are shifted", function() t.test(
local dir, buf = setup("a\nb\nc\n", "a\nb\nC\n") "toggle_stage unstages correctly when buffer lines are shifted",
vim.api.nvim_win_set_cursor(0, { 3, 0 }) function()
hunks.toggle_stage(buf) local dir, buf = setup("a\nb\nc\n", "a\nb\nC\n")
t.wait_for(function() vim.api.nvim_win_set_cursor(0, { 3, 0 })
return #assert(hunks.state(buf)).staged == 1 hunks.toggle_stage(buf)
end, "the line-3 change to be staged") t.wait_for(function()
return #assert(hunks.state(buf)).staged == 1
end, "the line-3 change to be staged")
vim.api.nvim_buf_set_lines(buf, 0, 0, false, { "NEW" }) vim.api.nvim_buf_set_lines(buf, 0, 0, false, { "NEW" })
vim.api.nvim_exec_autocmds("TextChanged", { buffer = buf }) vim.api.nvim_exec_autocmds("TextChanged", { buffer = buf })
hunks._flush(buf) hunks._flush(buf)
t.wait_for(function() t.wait_for(function()
return #assert(hunks.state(buf)).hunks == 1 return #assert(hunks.state(buf)).hunks == 1
end, "the unstaged add at the top to register") end, "the unstaged add at the top to register")
vim.api.nvim_win_set_cursor(0, { 4, 0 }) vim.api.nvim_win_set_cursor(0, { 4, 0 })
hunks.toggle_stage(buf) hunks.toggle_stage(buf)
t.wait_for(function() t.wait_for(function()
return #assert(hunks.state(buf)).staged == 0 return #assert(hunks.state(buf)).staged == 0
end, "the shifted staged hunk to be unstaged") end, "the shifted staged hunk to be unstaged")
t.eq( t.eq(
h.git(dir, "show", ":0:a.txt").stdout, h.git(dir, "show", ":0:a.txt").stdout,
"a\nb\nc", "a\nb\nc",
"the index reverts to HEAD content for the unstaged hunk" "the index reverts to HEAD content for the unstaged hunk"
) )
end) end
)
t.test("reset_hunk restores the index content for a change", function() t.test("reset_hunk restores the index content for a change", function()
local _, buf, state = setup("a\nb\nc\n", "a\nB\nc\n") local _, buf, state = setup("a\nb\nc\n", "a\nB\nc\n")
+17 -17
View File
@@ -80,28 +80,28 @@ t.test("M.open(HEAD:<path>) loads file content at HEAD", function()
object.open(r, "HEAD:a.txt", { split = false }) object.open(r, "HEAD:a.txt", { split = false })
t.eq(vim.api.nvim_buf_get_name(0), "git://" .. sha .. ":a.txt") t.eq(vim.api.nvim_buf_get_name(0), "git://" .. sha .. ":a.txt")
t.eq( t.eq(vim.api.nvim_buf_get_lines(0, 0, -1, false), { "first", "second" })
vim.api.nvim_buf_get_lines(0, 0, -1, false),
{ "first", "second" }
)
end) end)
t.test("M.open on a merge commit diffs against the first parent only", function() t.test(
local dir = h.make_repo({ ["a.txt"] = "one\n" }) "M.open on a merge commit diffs against the first parent only",
t.write(dir, "a.txt", "two\n") function()
h.git(dir, "stash") local dir = h.make_repo({ ["a.txt"] = "one\n" })
local stash = h.git(dir, "rev-parse", "stash@{0}").stdout t.write(dir, "a.txt", "two\n")
local r = assert(require("git.core.repo").resolve(dir)) h.git(dir, "stash")
local stash = h.git(dir, "rev-parse", "stash@{0}").stdout
local r = assert(require("git.core.repo").resolve(dir))
object.open(r, stash, { split = false }) object.open(r, stash, { split = false })
local count = 0 local count = 0
for _, l in ipairs(vim.api.nvim_buf_get_lines(0, 0, -1, false)) do for _, l in ipairs(vim.api.nvim_buf_get_lines(0, 0, -1, false)) do
if l:match("^diff %-%-git ") then if l:match("^diff %-%-git ") then
count = count + 1 count = count + 1
end
end end
t.eq(count, 1, "the stashed file's diff appears once, not per-parent")
end end
t.eq(count, 1, "the stashed file's diff appears once, not per-parent") )
end)
t.test("M.open errors on a bogus base, no buffer is opened", function() t.test("M.open errors on a bogus base, no buffer is opened", function()
local dir = h.make_repo({ a = "first\n" }) local dir = h.make_repo({ a = "first\n" })
+117 -91
View File
@@ -235,27 +235,33 @@ t.test("status_entry_for: exact match on case-sensitive repo", function()
t.eq(r:status_entry_for("foo"), nil, "case mismatch returns nil") t.eq(r:status_entry_for("foo"), nil, "case mismatch returns nil")
end) end)
t.test("status_entry_for: case-insensitive fallback when core.ignorecase=true", function() t.test(
local dir = h.make_repo({ Foo = "x" }) "status_entry_for: case-insensitive fallback when core.ignorecase=true",
h.git(dir, "config", "core.ignorecase", "true") function()
t.write(dir, "Foo", "modified") local dir = h.make_repo({ Foo = "x" })
local r = assert(require("git.core.repo").resolve(dir)) h.git(dir, "config", "core.ignorecase", "true")
wait_initial(r) t.write(dir, "Foo", "modified")
t.truthy(r:status_entry_for("Foo"), "exact match") local r = assert(require("git.core.repo").resolve(dir))
t.truthy(r:status_entry_for("foo"), "lowercase finds Foo") wait_initial(r)
t.truthy(r:status_entry_for("FOO"), "uppercase finds Foo") t.truthy(r:status_entry_for("Foo"), "exact match")
end) t.truthy(r:status_entry_for("foo"), "lowercase finds Foo")
t.truthy(r:status_entry_for("FOO"), "uppercase finds Foo")
end
)
t.test("_invalidate matches stash_refs on refs/stash and logs/refs/stash", function() t.test(
local dir = h.make_repo({ a = "x" }) "_invalidate matches stash_refs on refs/stash and logs/refs/stash",
local r = assert(require("git.core.repo").resolve(dir)) function()
r._cache.stash_refs = {} local dir = h.make_repo({ a = "x" })
r:_invalidate("refs/stash") local r = assert(require("git.core.repo").resolve(dir))
t.eq(r._cache.stash_refs, nil) r._cache.stash_refs = {}
r._cache.stash_refs = {} r:_invalidate("refs/stash")
r:_invalidate("logs/refs/stash") t.eq(r._cache.stash_refs, nil)
t.eq(r._cache.stash_refs, nil) r._cache.stash_refs = {}
end) r:_invalidate("logs/refs/stash")
t.eq(r._cache.stash_refs, nil)
end
)
t.test("refresh with invalidate=true wipes cache on next fetch", function() t.test("refresh with invalidate=true wipes cache on next fetch", function()
local dir = h.make_repo({ a = "x" }) local dir = h.make_repo({ a = "x" })
@@ -271,83 +277,103 @@ t.test("refresh with invalidate=true wipes cache on next fetch", function()
t.eq(r._cache["resolve:abc"], nil) t.eq(r._cache["resolve:abc"], nil)
end) end)
t.test("refresh emits change.paths listing structurally-changed paths", function() t.test(
local dir = h.make_repo({ a = "1", b = "1" }) "refresh emits change.paths listing structurally-changed paths",
local r = assert(require("git.core.repo").resolve(dir)) function()
wait_initial(r) local dir = h.make_repo({ a = "1", b = "1" })
t.write(dir, "a", "2") local r = assert(require("git.core.repo").resolve(dir))
---@type ow.Git.Repo.Change? wait_initial(r)
local change_seen t.write(dir, "a", "2")
local unsub = r:on("change", function(change) ---@type ow.Git.Repo.Change?
change_seen = change local change_seen
end) local unsub = r:on("change", function(change)
r:refresh() change_seen = change
t.wait_for(function() end)
return change_seen ~= nil r:refresh()
end, "refresh emit", 2000) t.wait_for(function()
unsub() return change_seen ~= nil
local change = assert(change_seen) end, "refresh emit", 2000)
t.truthy(change.paths["a"]) unsub()
t.falsy(change.paths["b"], "b is unchanged structurally") local change = assert(change_seen)
end) t.truthy(change.paths["a"])
t.falsy(change.paths["b"], "b is unchanged structurally")
end
)
t.test("submodule: parent enumerates initialized submodules by default", function() t.test(
local outer_path = h.make_submodule_repo() "submodule: parent enumerates initialized submodules by default",
local outer = assert(require("git.core.repo").resolve(outer_path)) function()
t.truthy(outer._submodules["sub"], "sub recorded as submodule") local outer_path = h.make_submodule_repo()
end) local outer = assert(require("git.core.repo").resolve(outer_path))
t.truthy(outer._submodules["sub"], "sub recorded as submodule")
end
)
t.test("submodule: eagerly creates child Repos and subscribes by default", function() t.test(
local outer_path = h.make_submodule_repo() "submodule: eagerly creates child Repos and subscribes by default",
local outer = assert(require("git.core.repo").resolve(outer_path)) function()
wait_initial(outer) local outer_path = h.make_submodule_repo()
local inner = require("git.core.repo").all()[outer_path .. "/sub"] local outer = assert(require("git.core.repo").resolve(outer_path))
t.truthy(inner, "inner Repo eagerly created") wait_initial(outer)
t.truthy(outer._submodules["sub"] and outer._submodules["sub"].unsub, "inner subscribed by outer") local inner = require("git.core.repo").all()[outer_path .. "/sub"]
t.truthy(inner, "inner Repo eagerly created")
t.truthy(
outer._submodules["sub"] and outer._submodules["sub"].unsub,
"inner subscribed by outer"
)
t.write(outer_path .. "/sub", "a", "modified\n") t.write(outer_path .. "/sub", "a", "modified\n")
---@type ow.Git.Repo.Change? ---@type ow.Git.Repo.Change?
local outer_change local outer_change
local unsub = outer:on("change", function(change) local unsub = outer:on("change", function(change)
outer_change = change outer_change = change
end) end)
inner:refresh() inner:refresh()
t.wait_for(function() t.wait_for(function()
return outer_change ~= nil return outer_change ~= nil
end, "outer notified by inner refresh", 2000) end, "outer notified by inner refresh", 2000)
unsub() unsub()
local entry = outer.status.entries["sub"] local entry = outer.status.entries["sub"]
t.truthy(entry, "outer sub entry now present") t.truthy(entry, "outer sub entry now present")
t.eq(entry.kind, "changed") t.eq(entry.kind, "changed")
end) end
)
t.test("submodule: no eager creation when flag is explicitly disabled", function() t.test(
vim.g.git_submodule_recursion = false "submodule: no eager creation when flag is explicitly disabled",
t.defer(function() function()
vim.g.git_submodule_recursion = nil vim.g.git_submodule_recursion = false
end) t.defer(function()
local outer_path = h.make_submodule_repo() vim.g.git_submodule_recursion = nil
local outer = assert(require("git.core.repo").resolve(outer_path)) end)
wait_initial(outer) local outer_path = h.make_submodule_repo()
t.eq( local outer = assert(require("git.core.repo").resolve(outer_path))
require("git.core.repo").all()[outer_path .. "/sub"], wait_initial(outer)
nil, t.eq(
"inner Repo not created when flag is false" require("git.core.repo").all()[outer_path .. "/sub"],
) nil,
t.eq(next(outer._submodules), nil) "inner Repo not created when flag is false"
end) )
t.eq(next(outer._submodules), nil)
end
)
t.test("submodule: outer created after inner picks up existing child", function() t.test(
local outer_path = h.make_submodule_repo() "submodule: outer created after inner picks up existing child",
local inner = assert( function()
require("git.core.repo").resolve(outer_path .. "/sub") local outer_path = h.make_submodule_repo()
) local inner =
wait_initial(inner) assert(require("git.core.repo").resolve(outer_path .. "/sub"))
local outer = assert(require("git.core.repo").resolve(outer_path)) wait_initial(inner)
wait_initial(outer) local outer = assert(require("git.core.repo").resolve(outer_path))
t.truthy(outer._submodules["sub"] and outer._submodules["sub"].unsub, "outer subscribed to pre-existing inner") wait_initial(outer)
end) t.truthy(
outer._submodules["sub"] and outer._submodules["sub"].unsub,
"outer subscribed to pre-existing inner"
)
end
)
t.test("watcher cleans up after a slash-branch dir is removed", function() t.test("watcher cleans up after a slash-branch dir is removed", function()
local dir = h.make_repo({ a = "x" }) local dir = h.make_repo({ a = "x" })
+30 -19
View File
@@ -1,5 +1,5 @@
local t = require("test")
local status = require("git.core.status") local status = require("git.core.status")
local t = require("test")
local NUL = "\0" local NUL = "\0"
@@ -204,7 +204,10 @@ t.test("mark_for: changed staged modified", function()
path = "x", path = "x",
staged = "modified", staged = "modified",
} }
t.eq(status.mark_for(entry, "staged"), { char = "M", hl = "GitStagedModified" }) t.eq(
status.mark_for(entry, "staged"),
{ char = "M", hl = "GitStagedModified" }
)
end) end)
t.test("mark_for: changed unstaged deleted uses GitUnstagedDeleted", function() t.test("mark_for: changed unstaged deleted uses GitUnstagedDeleted", function()
@@ -213,7 +216,10 @@ t.test("mark_for: changed unstaged deleted uses GitUnstagedDeleted", function()
path = "x", path = "x",
unstaged = "deleted", unstaged = "deleted",
} }
t.eq(status.mark_for(entry, "unstaged"), { char = "D", hl = "GitUnstagedDeleted" }) t.eq(
status.mark_for(entry, "unstaged"),
{ char = "D", hl = "GitUnstagedDeleted" }
)
end) end)
t.test("mark_for: changed renamed uses per-side renamed hl", function() t.test("mark_for: changed renamed uses per-side renamed hl", function()
@@ -223,7 +229,10 @@ t.test("mark_for: changed renamed uses per-side renamed hl", function()
staged = "renamed", staged = "renamed",
orig = "y", orig = "y",
} }
t.eq(status.mark_for(entry, "staged"), { char = "R", hl = "GitStagedRenamed" }) t.eq(
status.mark_for(entry, "staged"),
{ char = "R", hl = "GitStagedRenamed" }
)
end) end)
t.test("mark_for: untracked / ignored / unmerged ignore side", function() t.test("mark_for: untracked / ignored / unmerged ignore side", function()
@@ -364,24 +373,26 @@ t.test("entry_equal: differing unmerged conflict returns false", function()
t.falsy(status.entry_equal(a, b)) t.falsy(status.entry_equal(a, b))
end) end)
t.test("diff_entries: detects additions, removals, and modifications", function() t.test(
local prior = { "diff_entries: detects additions, removals, and modifications",
a = { kind = "changed", path = "a", staged = "modified" }, function()
b = { kind = "untracked", path = "b" }, local prior = {
} a = { kind = "changed", path = "a", staged = "modified" },
local next_ = { b = { kind = "untracked", path = "b" },
a = { kind = "changed", path = "a", staged = "added" }, }
c = { kind = "untracked", path = "c" }, local next_ = {
} a = { kind = "changed", path = "a", staged = "added" },
local changed = status.diff_entries(prior, next_) c = { kind = "untracked", path = "c" },
t.truthy(changed.a, "a modified") }
t.truthy(changed.b, "b removed") local changed = status.diff_entries(prior, next_)
t.truthy(changed.c, "c added") t.truthy(changed.a, "a modified")
end) t.truthy(changed.b, "b removed")
t.truthy(changed.c, "c added")
end
)
t.test("diff_entries: empty when entries match", function() t.test("diff_entries: empty when entries match", function()
local prior = { a = { kind = "untracked", path = "a" } } local prior = { a = { kind = "untracked", path = "a" } }
local next_ = { a = { kind = "untracked", path = "a" } } local next_ = { a = { kind = "untracked", path = "a" } }
t.eq(status.diff_entries(prior, next_), {}) t.eq(status.diff_entries(prior, next_), {})
end) end)
+71 -78
View File
@@ -406,82 +406,75 @@ t.test("sidebar buffer name does not get written to disk", function()
) )
end) end)
t.test( t.test("diffsplit from sidebar resets cursor so panes stay in sync", function()
"diffsplit from sidebar resets cursor so panes stay in sync", local committed, worktree = {}, {}
function() for i = 1, 100 do
local committed, worktree = {}, {} committed[i] = "line " .. i
for i = 1, 100 do worktree[i] = i == 10 and "CHANGED " .. i
committed[i] = "line " .. i or i == 40 and "CHANGED " .. i
worktree[i] = i == 10 or i == 70 and "CHANGED " .. i
and "CHANGED " .. i or i == 90 and "CHANGED " .. i
or i == 40 and "CHANGED " .. i or ("line " .. i)
or i == 70 and "CHANGED " .. i
or i == 90 and "CHANGED " .. i
or ("line " .. i)
end
local repo = h.make_repo({
["file.txt"] = table.concat(committed, "\n") .. "\n",
})
t.write(repo, "file.txt", table.concat(worktree, "\n") .. "\n")
vim.cmd("cd " .. repo)
-- Open the worktree file in a normal window and position cursor in
-- what becomes a folded section after diff is set up.
vim.cmd("edit file.txt")
vim.api.nvim_win_set_cursor(0, { 50, 0 })
require("git.status_view").open({ placement = "sidebar" })
local sidebar_buf, sidebar_win = find_sidebar()
assert(sidebar_buf and sidebar_win)
local r = assert(require("git.core.repo").find(vim.fn.getcwd()))
r:refresh()
t.wait_for(function()
return r.status and #r.status:rows("unstaged") > 0
end, "git status to report unstaged changes")
local entry_line
for i, l in
ipairs(vim.api.nvim_buf_get_lines(sidebar_buf, 0, -1, false))
do
if l:match("file.txt$") then
entry_line = i
break
end
end
if not entry_line then
error("entry line should exist")
end
vim.api.nvim_set_current_win(sidebar_win)
vim.api.nvim_win_set_cursor(sidebar_win, { entry_line, 0 })
t.press("<Tab>")
t.wait_for(function()
return find_diff_win("left") ~= nil
and find_diff_win("right") ~= nil
end, "diff pair to appear")
local left_win = assert(find_diff_win("left"))
local right_win = assert(find_diff_win("right"))
local left_top =
vim.api.nvim_win_call(left_win, function() return vim.fn.line("w0") end)
local right_top = vim.api.nvim_win_call(
right_win,
function() return vim.fn.line("w0") end
)
t.eq(
left_top,
right_top,
"left and right panes should have the same topline after diffsplit"
)
t.eq(
vim.api.nvim_win_get_cursor(left_win),
{ 1, 0 },
"left pane should start at line 1"
)
t.eq(
vim.api.nvim_win_get_cursor(right_win),
{ 1, 0 },
"right pane should start at line 1"
)
end end
) local repo = h.make_repo({
["file.txt"] = table.concat(committed, "\n") .. "\n",
})
t.write(repo, "file.txt", table.concat(worktree, "\n") .. "\n")
vim.cmd("cd " .. repo)
-- Open the worktree file in a normal window and position cursor in
-- what becomes a folded section after diff is set up.
vim.cmd("edit file.txt")
vim.api.nvim_win_set_cursor(0, { 50, 0 })
require("git.status_view").open({ placement = "sidebar" })
local sidebar_buf, sidebar_win = find_sidebar()
assert(sidebar_buf and sidebar_win)
local r = assert(require("git.core.repo").find(vim.fn.getcwd()))
r:refresh()
t.wait_for(function()
return r.status and #r.status:rows("unstaged") > 0
end, "git status to report unstaged changes")
local entry_line
for i, l in ipairs(vim.api.nvim_buf_get_lines(sidebar_buf, 0, -1, false)) do
if l:match("file.txt$") then
entry_line = i
break
end
end
if not entry_line then
error("entry line should exist")
end
vim.api.nvim_set_current_win(sidebar_win)
vim.api.nvim_win_set_cursor(sidebar_win, { entry_line, 0 })
t.press("<Tab>")
t.wait_for(function()
return find_diff_win("left") ~= nil and find_diff_win("right") ~= nil
end, "diff pair to appear")
local left_win = assert(find_diff_win("left"))
local right_win = assert(find_diff_win("right"))
local left_top = vim.api.nvim_win_call(left_win, function()
return vim.fn.line("w0")
end)
local right_top = vim.api.nvim_win_call(right_win, function()
return vim.fn.line("w0")
end)
t.eq(
left_top,
right_top,
"left and right panes should have the same topline after diffsplit"
)
t.eq(
vim.api.nvim_win_get_cursor(left_win),
{ 1, 0 },
"left pane should start at line 1"
)
t.eq(
vim.api.nvim_win_get_cursor(right_win),
{ 1, 0 },
"right pane should start at line 1"
)
end)