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")
+20 -12
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
ipairs(vim.api.nvim_buf_get_extmarks(buf, ns, 0, -1, {
details = true, details = true,
})) do }))
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,7 +439,9 @@ 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(
"toggle_stage refreshes the gutter when status stays modified",
function()
local _, buf = setup("a\nb\nc\nd\ne\n", "A\nb\nC\nd\nE\n") local _, buf = setup("a\nb\nc\nd\ne\n", "A\nb\nC\nd\nE\n")
t.eq(#assert(hunks.state(buf)).hunks, 3) t.eq(#assert(hunks.state(buf)).hunks, 3)
@@ -452,7 +456,8 @@ t.test("toggle_stage refreshes the gutter when status stays modified", function(
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,7 +504,9 @@ 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(
"toggle_stage unstages correctly when buffer lines are shifted",
function()
local dir, buf = setup("a\nb\nc\n", "a\nb\nC\n") local dir, buf = setup("a\nb\nc\n", "a\nb\nC\n")
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)
@@ -524,7 +531,8 @@ t.test("toggle_stage unstages correctly when buffer lines are shifted", function
"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")
+6 -6
View File
@@ -80,13 +80,12 @@ 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(
"M.open on a merge commit diffs against the first parent only",
function()
local dir = h.make_repo({ ["a.txt"] = "one\n" }) local dir = h.make_repo({ ["a.txt"] = "one\n" })
t.write(dir, "a.txt", "two\n") t.write(dir, "a.txt", "two\n")
h.git(dir, "stash") h.git(dir, "stash")
@@ -101,7 +100,8 @@ t.test("M.open on a merge commit diffs against the first parent only", function(
end end
end end
t.eq(count, 1, "the stashed file's diff appears once, not per-parent") t.eq(count, 1, "the stashed file's diff appears once, not per-parent")
end) 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" })
+46 -20
View File
@@ -235,7 +235,9 @@ 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(
"status_entry_for: case-insensitive fallback when core.ignorecase=true",
function()
local dir = h.make_repo({ Foo = "x" }) local dir = h.make_repo({ Foo = "x" })
h.git(dir, "config", "core.ignorecase", "true") h.git(dir, "config", "core.ignorecase", "true")
t.write(dir, "Foo", "modified") t.write(dir, "Foo", "modified")
@@ -244,9 +246,12 @@ t.test("status_entry_for: case-insensitive fallback when core.ignorecase=true",
t.truthy(r:status_entry_for("Foo"), "exact match") t.truthy(r:status_entry_for("Foo"), "exact match")
t.truthy(r:status_entry_for("foo"), "lowercase finds Foo") t.truthy(r:status_entry_for("foo"), "lowercase finds Foo")
t.truthy(r:status_entry_for("FOO"), "uppercase finds Foo") t.truthy(r:status_entry_for("FOO"), "uppercase finds Foo")
end) end
)
t.test("_invalidate matches stash_refs on refs/stash and logs/refs/stash", function() t.test(
"_invalidate matches stash_refs on refs/stash and logs/refs/stash",
function()
local dir = h.make_repo({ a = "x" }) local dir = h.make_repo({ a = "x" })
local r = assert(require("git.core.repo").resolve(dir)) local r = assert(require("git.core.repo").resolve(dir))
r._cache.stash_refs = {} r._cache.stash_refs = {}
@@ -255,7 +260,8 @@ t.test("_invalidate matches stash_refs on refs/stash and logs/refs/stash", funct
r._cache.stash_refs = {} r._cache.stash_refs = {}
r:_invalidate("logs/refs/stash") r:_invalidate("logs/refs/stash")
t.eq(r._cache.stash_refs, nil) t.eq(r._cache.stash_refs, nil)
end) 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,7 +277,9 @@ 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(
"refresh emits change.paths listing structurally-changed paths",
function()
local dir = h.make_repo({ a = "1", b = "1" }) local dir = h.make_repo({ a = "1", b = "1" })
local r = assert(require("git.core.repo").resolve(dir)) local r = assert(require("git.core.repo").resolve(dir))
wait_initial(r) wait_initial(r)
@@ -289,21 +297,30 @@ t.test("refresh emits change.paths listing structurally-changed paths", function
local change = assert(change_seen) local change = assert(change_seen)
t.truthy(change.paths["a"]) t.truthy(change.paths["a"])
t.falsy(change.paths["b"], "b is unchanged structurally") t.falsy(change.paths["b"], "b is unchanged structurally")
end) end
)
t.test("submodule: parent enumerates initialized submodules by default", function() t.test(
"submodule: parent enumerates initialized submodules by default",
function()
local outer_path = h.make_submodule_repo() local outer_path = h.make_submodule_repo()
local outer = assert(require("git.core.repo").resolve(outer_path)) local outer = assert(require("git.core.repo").resolve(outer_path))
t.truthy(outer._submodules["sub"], "sub recorded as submodule") t.truthy(outer._submodules["sub"], "sub recorded as submodule")
end) end
)
t.test("submodule: eagerly creates child Repos and subscribes by default", function() t.test(
"submodule: eagerly creates child Repos and subscribes by default",
function()
local outer_path = h.make_submodule_repo() local outer_path = h.make_submodule_repo()
local outer = assert(require("git.core.repo").resolve(outer_path)) local outer = assert(require("git.core.repo").resolve(outer_path))
wait_initial(outer) wait_initial(outer)
local inner = require("git.core.repo").all()[outer_path .. "/sub"] local inner = require("git.core.repo").all()[outer_path .. "/sub"]
t.truthy(inner, "inner Repo eagerly created") t.truthy(inner, "inner Repo eagerly created")
t.truthy(outer._submodules["sub"] and outer._submodules["sub"].unsub, "inner subscribed by outer") 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?
@@ -320,9 +337,12 @@ t.test("submodule: eagerly creates child Repos and subscribes by default", funct
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(
"submodule: no eager creation when flag is explicitly disabled",
function()
vim.g.git_submodule_recursion = false vim.g.git_submodule_recursion = false
t.defer(function() t.defer(function()
vim.g.git_submodule_recursion = nil vim.g.git_submodule_recursion = nil
@@ -336,18 +356,24 @@ t.test("submodule: no eager creation when flag is explicitly disabled", function
"inner Repo not created when flag is false" "inner Repo not created when flag is false"
) )
t.eq(next(outer._submodules), nil) t.eq(next(outer._submodules), nil)
end) end
t.test("submodule: outer created after inner picks up existing child", function()
local outer_path = h.make_submodule_repo()
local inner = assert(
require("git.core.repo").resolve(outer_path .. "/sub")
) )
t.test(
"submodule: outer created after inner picks up existing child",
function()
local outer_path = h.make_submodule_repo()
local inner =
assert(require("git.core.repo").resolve(outer_path .. "/sub"))
wait_initial(inner) wait_initial(inner)
local outer = assert(require("git.core.repo").resolve(outer_path)) local outer = assert(require("git.core.repo").resolve(outer_path))
wait_initial(outer) wait_initial(outer)
t.truthy(outer._submodules["sub"] and outer._submodules["sub"].unsub, "outer subscribed to pre-existing inner") t.truthy(
end) 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" })
+18 -7
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,7 +373,9 @@ 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(
"diff_entries: detects additions, removals, and modifications",
function()
local prior = { local prior = {
a = { kind = "changed", path = "a", staged = "modified" }, a = { kind = "changed", path = "a", staged = "modified" },
b = { kind = "untracked", path = "b" }, b = { kind = "untracked", path = "b" },
@@ -377,11 +388,11 @@ t.test("diff_entries: detects additions, removals, and modifications", function(
t.truthy(changed.a, "a modified") t.truthy(changed.a, "a modified")
t.truthy(changed.b, "b removed") t.truthy(changed.b, "b removed")
t.truthy(changed.c, "c added") t.truthy(changed.c, "c added")
end) 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)
+11 -18
View File
@@ -406,14 +406,11 @@ 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",
function()
local committed, worktree = {}, {} local committed, worktree = {}, {}
for i = 1, 100 do for i = 1, 100 do
committed[i] = "line " .. i committed[i] = "line " .. i
worktree[i] = i == 10 worktree[i] = i == 10 and "CHANGED " .. i
and "CHANGED " .. i
or i == 40 and "CHANGED " .. i or i == 40 and "CHANGED " .. i
or i == 70 and "CHANGED " .. i or i == 70 and "CHANGED " .. i
or i == 90 and "CHANGED " .. i or i == 90 and "CHANGED " .. i
@@ -440,9 +437,7 @@ t.test(
end, "git status to report unstaged changes") end, "git status to report unstaged changes")
local entry_line local entry_line
for i, l in for i, l in ipairs(vim.api.nvim_buf_get_lines(sidebar_buf, 0, -1, false)) do
ipairs(vim.api.nvim_buf_get_lines(sidebar_buf, 0, -1, false))
do
if l:match("file.txt$") then if l:match("file.txt$") then
entry_line = i entry_line = i
break break
@@ -456,18 +451,17 @@ t.test(
vim.api.nvim_win_set_cursor(sidebar_win, { entry_line, 0 }) vim.api.nvim_win_set_cursor(sidebar_win, { entry_line, 0 })
t.press("<Tab>") t.press("<Tab>")
t.wait_for(function() t.wait_for(function()
return find_diff_win("left") ~= nil return find_diff_win("left") ~= nil and find_diff_win("right") ~= nil
and find_diff_win("right") ~= nil
end, "diff pair to appear") end, "diff pair to appear")
local left_win = assert(find_diff_win("left")) local left_win = assert(find_diff_win("left"))
local right_win = assert(find_diff_win("right")) local right_win = assert(find_diff_win("right"))
local left_top = local left_top = vim.api.nvim_win_call(left_win, function()
vim.api.nvim_win_call(left_win, function() return vim.fn.line("w0") end) return vim.fn.line("w0")
local right_top = vim.api.nvim_win_call( end)
right_win, local right_top = vim.api.nvim_win_call(right_win, function()
function() return vim.fn.line("w0") end return vim.fn.line("w0")
) end)
t.eq( t.eq(
left_top, left_top,
right_top, right_top,
@@ -483,5 +477,4 @@ t.test(
{ 1, 0 }, { 1, 0 },
"right pane should start at line 1" "right pane should start at line 1"
) )
end end)
)