refactor(git): split engine into core subpackage

This commit is contained in:
2026-05-10 17:20:22 +02:00
parent 8624f825eb
commit f50a09ecac
21 changed files with 67 additions and 67 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
local commit = require("git.commit")
local object = require("git.object")
local repo = require("git.repo")
local util = require("git.util")
local repo = require("git.core.repo")
local util = require("git.core.util")
local M = {}
+2 -2
View File
@@ -1,6 +1,6 @@
local editor = require("git.editor")
local repo = require("git.repo")
local util = require("git.util")
local repo = require("git.core.repo")
local util = require("git.core.util")
local M = {}
+2 -2
View File
@@ -1,5 +1,5 @@
local status = require("git.status")
local util = require("git.util")
local status = require("git.core.status")
local util = require("git.core.util")
local M = {}
+3 -3
View File
@@ -1,6 +1,6 @@
local Revision = require("git.revision")
local repo = require("git.repo")
local util = require("git.util")
local Revision = require("git.core.revision")
local repo = require("git.core.repo")
local util = require("git.core.util")
local M = {}
+1 -1
View File
@@ -1,4 +1,4 @@
local util = require("git.util")
local util = require("git.core.util")
local M = {}
+2 -2
View File
@@ -1,5 +1,5 @@
local repo = require("git.repo")
local util = require("git.util")
local repo = require("git.core.repo")
local util = require("git.core.util")
local M = {}
+3 -3
View File
@@ -1,6 +1,6 @@
local Revision = require("git.revision")
local repo = require("git.repo")
local util = require("git.util")
local Revision = require("git.core.revision")
local repo = require("git.core.repo")
local util = require("git.core.util")
local M = {}
+4 -4
View File
@@ -1,9 +1,9 @@
local Revision = require("git.revision")
local Revision = require("git.core.revision")
local diff = require("git.diff")
local object = require("git.object")
local repo = require("git.repo")
local status = require("git.status")
local util = require("git.util")
local repo = require("git.core.repo")
local status = require("git.core.status")
local util = require("git.core.util")
local M = {}
+3 -3
View File
@@ -1,6 +1,6 @@
local repo = require("git.repo")
local status = require("git.status")
local util = require("git.util")
local repo = require("git.core.repo")
local status = require("git.core.status")
local util = require("git.core.util")
local M = {}
+8 -8
View File
@@ -44,37 +44,37 @@ local group = vim.api.nvim_create_augroup("ow.git", { clear = true })
vim.api.nvim_create_autocmd({ "BufReadPost", "BufNewFile" }, {
group = group,
callback = function(args)
require("git.repo").track(args.buf)
require("git.core.repo").track(args.buf)
end,
})
vim.api.nvim_create_autocmd({ "BufWritePost", "FileChangedShellPost" }, {
group = group,
callback = function(args)
require("git.repo").refresh(args.buf)
require("git.core.repo").refresh(args.buf)
end,
})
vim.api.nvim_create_autocmd({ "BufDelete", "BufWipeout" }, {
group = group,
callback = function(args)
require("git.repo").unbind(args.buf)
require("git.core.repo").unbind(args.buf)
end,
})
vim.api.nvim_create_autocmd("FocusGained", {
group = group,
callback = function()
require("git.repo").refresh_all()
require("git.core.repo").refresh_all()
end,
})
vim.api.nvim_create_autocmd("VimLeavePre", {
group = group,
callback = function()
require("git.repo").stop_all()
require("git.core.repo").stop_all()
end,
})
vim.api.nvim_create_autocmd({ "VimEnter", "DirChanged", "TabEnter" }, {
group = group,
callback = function()
require("git.repo").update_cwd_repo()
require("git.core.repo").update_cwd_repo()
end,
})
vim.api.nvim_create_autocmd("TabClosed", {
@@ -82,7 +82,7 @@ vim.api.nvim_create_autocmd("TabClosed", {
callback = function(args)
local tab = tonumber(args.file) --[[@as integer?]]
if tab then
require("git.repo").release_tab(tab)
require("git.core.repo").release_tab(tab)
end
end,
})
@@ -121,7 +121,7 @@ end, {
})
vim.api.nvim_create_user_command("Grefresh", function()
require("git.repo").refresh_all()
require("git.core.repo").refresh_all()
end, { desc = "Refresh git status for all repos" })
vim.api.nvim_create_user_command("Glog", function(opts)
+3 -3
View File
@@ -5,7 +5,7 @@ end)
---@class nvim_tree.api.decorator.UserDecorator
local Decorator = require("nvim-tree.api").Decorator
local repo = require("git.repo")
local repo = require("git.core.repo")
repo.on("refresh", function()
require("nvim-tree.api").tree.reload()
@@ -49,7 +49,7 @@ function GitDecorator:new()
self.highlight_range = "name"
end
local status = require("git.status")
local status = require("git.core.status")
---@param node Node
---@return ow.Git.Status.Mark[]?
@@ -150,7 +150,7 @@ require("nvim-tree").setup({
full_name = true,
root_folder_label = function(path)
local label = vim.fn.fnamemodify(path, ":~")
local r = require("git.repo").resolve(path)
local r = require("git.core.repo").resolve(path)
local git_head = r and r:head()
if git_head then
label = label .. ("  %s"):format(git_head)
+4 -4
View File
@@ -194,7 +194,7 @@ t.test("complete add returns only unstaged/untracked paths", function()
local dir = make_repo({ tracked = "x" })
t.write(dir, "tracked", "modified")
t.write(dir, "newfile", "new")
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
r:refresh()
t.wait_for(function()
return r.status and #vim.tbl_keys(r.status.entries) > 0
@@ -309,7 +309,7 @@ t.test(":G show <CR> on + line opens the blob URI", function()
t.write(dir, "a", "second\n")
h.git(dir, "add", "a")
h.git(dir, "commit", "-q", "-m", "second")
assert(require("git.repo").resolve(dir))
assert(require("git.core.repo").resolve(dir))
local blob = h.git(dir, "rev-parse", "HEAD:a").stdout
cmd.run({ "show", "HEAD" })
@@ -367,7 +367,7 @@ t.test("<CR> still dispatches after navigating away and back", function()
-- 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))
local r = assert(require("git.core.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()
@@ -397,7 +397,7 @@ end)
t.test(":G diff <CR> on + line falls back to worktree file", function()
local dir = make_repo({ a = "v1\n" })
t.write(dir, "a", "v2\n")
assert(require("git.repo").resolve(dir))
assert(require("git.core.repo").resolve(dir))
cmd.run({ "diff" })
wait_buf_populated("%[Git diff%]")
+1 -1
View File
@@ -59,7 +59,7 @@ function M.make_repo(files, opts)
pcall(vim.cmd.cd, "/tmp")
end
pcall(function()
require("git.repo").stop_all()
require("git.core.repo").stop_all()
end)
vim.wait(60)
for _, b in ipairs(vim.api.nvim_list_bufs()) do
+11 -11
View File
@@ -1,4 +1,4 @@
local Revision = require("git.revision")
local Revision = require("git.core.revision")
local h = require("test.git.helpers")
local object = require("git.object")
local t = require("test")
@@ -56,7 +56,7 @@ end)
t.test("M.open(HEAD) names buffer with full sha", function()
local dir = h.make_repo({ a = "first\n" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local sha = h.git(dir, "rev-parse", "HEAD").stdout
object.open(r, "HEAD", { split = false })
@@ -65,7 +65,7 @@ end)
t.test("M.open(<short sha>) canonicalizes to full sha", function()
local dir = h.make_repo({ a = "first\n" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local sha = h.git(dir, "rev-parse", "HEAD").stdout
local short = h.git(dir, "rev-parse", "--short", "HEAD").stdout
t.truthy(#short < #sha, "short sha must be shorter than full")
@@ -76,7 +76,7 @@ end)
t.test("M.open(HEAD:<path>) loads file content at HEAD", function()
local dir = h.make_repo({ ["a.txt"] = "first\nsecond\n" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local sha = h.git(dir, "rev-parse", "HEAD").stdout
object.open(r, "HEAD:a.txt", { split = false })
@@ -89,7 +89,7 @@ end)
t.test("M.open errors on a bogus base, no buffer is opened", function()
local dir = h.make_repo({ a = "first\n" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
t.quietly(function()
object.open(r, "deadbeefdeadbeef", { split = false })
@@ -99,7 +99,7 @@ end)
t.test("M.open errors on a missing path, no buffer is opened", function()
local dir = h.make_repo({ a = "first\n" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
t.quietly(function()
object.open(r, "HEAD:does-not-exist", { split = false })
@@ -109,7 +109,7 @@ end)
t.test("read_uri opens stage-0 entry as a writable index buffer", function()
local dir = h.make_repo({ ["a.txt"] = "first\n" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local rev = Revision.new({ stage = 0, path = "a.txt" })
local buf = object.buf_for(r, rev)
@@ -120,7 +120,7 @@ end)
t.test("open_under_cursor on a 'tree <sha>' line opens the tree", function()
local dir = h.make_repo({ a = "first\n" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local tree_sha = h.git(dir, "rev-parse", "HEAD^{tree}").stdout
object.open(r, "HEAD", { split = false })
@@ -136,7 +136,7 @@ t.test("open_under_cursor on a 'parent <sha>' line opens the parent", function()
t.write(dir, "a", "second\n")
h.git(dir, "add", "a")
h.git(dir, "commit", "-q", "-m", "second")
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local parent_sha = h.git(dir, "rev-parse", "HEAD~").stdout
object.open(r, "HEAD", { split = false })
@@ -149,7 +149,7 @@ end)
t.test("open_under_cursor on a '+++ b/<path>' line loads the blob", function()
local dir = h.make_repo({ ["a.txt"] = "first\n" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local blob_sha = h.git(dir, "rev-parse", "HEAD:a.txt").stdout
object.open(r, "HEAD", { split = false })
@@ -162,7 +162,7 @@ end)
t.test("open_under_cursor returns false on a non-dispatchable line", function()
local dir = h.make_repo({ a = "first\n" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
object.open(r, "HEAD", { split = false })
local lnum = assert(find_line(0, "author "), "expected an author line")
+13 -13
View File
@@ -15,7 +15,7 @@ t.test("list_refs returns heads, tags, remotes (no HEAD)", function()
local dir = h.make_repo({ a = "x" })
h.git(dir, "branch", "feature")
h.git(dir, "tag", "v1")
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local refs = r:list_refs()
table.sort(refs)
t.eq(refs, { "feature", "main", "v1" })
@@ -23,13 +23,13 @@ end)
t.test("list_pseudo_refs always includes HEAD", function()
local dir = h.make_repo({ a = "x" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
t.eq(r:list_pseudo_refs(), { "HEAD" })
end)
t.test("list_pseudo_refs picks up MERGE_HEAD when present", function()
local dir = h.make_repo({ a = "x" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
t.write(dir .. "/.git", "MERGE_HEAD", "deadbeef\n")
-- Bypass cache (file appeared after first scan).
r._cache = {}
@@ -40,7 +40,7 @@ end)
t.test("list_stash_refs is empty when no stash", function()
local dir = h.make_repo({ a = "x" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
t.eq(r:list_stash_refs(), {})
end)
@@ -48,7 +48,7 @@ t.test("list_stash_refs lists stash + entries when stash exists", function()
local dir = h.make_repo({ a = "x" })
t.write(dir, "a", "modified")
h.git(dir, "stash")
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local refs = r:list_stash_refs()
t.eq(#refs, 2)
t.eq(refs[1], "stash")
@@ -57,7 +57,7 @@ end)
t.test("get_cached memoizes by key", function()
local dir = h.make_repo({ a = "x" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local calls = 0
local v1 = r:get_cached("k", function()
calls = calls + 1
@@ -73,7 +73,7 @@ end)
t.test("cache clears after top-level .git change (commit)", function()
local dir = h.make_repo({ a = "x" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local _ = r:list_refs()
t.truthy(r._cache.refs)
t.write(dir, "b", "y")
@@ -85,7 +85,7 @@ end)
t.test("cache clears after slash-branch creation (polyfill)", function()
local dir = h.make_repo({ a = "x" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local _ = r:list_refs()
t.truthy(r._cache.refs)
h.git(dir, "branch", "feat/foo")
@@ -98,7 +98,7 @@ end)
t.test("cache clears after deeply nested slash branch", function()
local dir = h.make_repo({ a = "x" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local _ = r:list_refs()
h.git(dir, "branch", "deep/a/b/c")
wait_cleared(r, "refs")
@@ -109,7 +109,7 @@ end)
t.test("resolve_sha returns ok + full sha for a known blob", function()
local dir = h.make_repo({ a = "hello\n" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local blob = h.git(dir, "rev-parse", "HEAD:a").stdout
local short = blob:sub(1, 7)
local full, status = r:resolve_sha(short)
@@ -119,7 +119,7 @@ end)
t.test("resolve_sha returns missing for an unknown prefix", function()
local dir = h.make_repo({ a = "x" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local full, status = r:resolve_sha("0000deadbeef")
t.eq(full, nil)
t.eq(status, "missing")
@@ -127,7 +127,7 @@ end)
t.test("resolve_sha caches by prefix", function()
local dir = h.make_repo({ a = "x" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
local blob = h.git(dir, "rev-parse", "HEAD:a").stdout
local short = blob:sub(1, 7)
local _, _ = r:resolve_sha(short)
@@ -136,7 +136,7 @@ end)
t.test("watcher cleans up after a slash-branch dir is removed", function()
local dir = h.make_repo({ a = "x" })
local r = assert(require("git.repo").resolve(dir))
local r = assert(require("git.core.repo").resolve(dir))
h.git(dir, "branch", "feat/foo")
-- Wait for the dynamic watcher on .git/refs/heads/feat to be added.
local feat_path = dir .. "/.git/refs/heads/feat"
+1 -1
View File
@@ -1,5 +1,5 @@
local t = require("test")
local status = require("git.status")
local status = require("git.core.status")
local NUL = "\0"
+3 -3
View File
@@ -71,7 +71,7 @@ local function setup_sidebar_with_unstaged_file(
assert(sidebar_win, "sidebar window should exist")
local r = assert(
require("git.repo").find(vim.fn.getcwd()),
require("git.core.repo").find(vim.fn.getcwd()),
"repo should resolve for the test worktree"
)
r:refresh()
@@ -102,7 +102,7 @@ t.test("stage with diff open: sidebar cursor stays put", function()
return find_diff_win("left") ~= nil
end, "diff windows to appear")
local r = assert(require("git.repo").find(vim.fn.getcwd()))
local r = assert(require("git.core.repo").find(vim.fn.getcwd()))
vim.api.nvim_set_current_win(sidebar_win)
t.press("s")
t.wait_for(function()
@@ -139,7 +139,7 @@ t.test(
"left diff foldmethod should be 'diff' after Tab"
)
local r = assert(require("git.repo").find(vim.fn.getcwd()))
local r = assert(require("git.core.repo").find(vim.fn.getcwd()))
vim.api.nvim_set_current_win(sidebar_win)
t.press("s")
t.wait_for(function()
+1 -1
View File
@@ -1,5 +1,5 @@
local t = require("test")
local util = require("git.util")
local util = require("git.core.util")
local function fresh_buf()
local buf = vim.api.nvim_create_buf(false, true)