diff --git a/lua/git/core/repo.lua b/lua/git/core/repo.lua index b9fcef1..ce65f08 100644 --- a/lua/git/core/repo.lua +++ b/lua/git/core/repo.lua @@ -143,6 +143,7 @@ function Repo:_invalidate(relpath) end if affects_resolve(relpath) then self:_clear_cache_prefix("resolve:") + self:_clear_cache_prefix("head_blob:") end if relpath == "index" then self:_clear_cache_prefix("index:") @@ -605,6 +606,15 @@ function Repo:index_sha(rel) return sha or nil end +---@param rel string worktree-relative path +---@return string? +function Repo:head_sha(rel) + local sha = self:get_cached("head_blob:" .. rel, function(self) + return self:rev_parse("HEAD:" .. rel, false) or false + end) + return sha or nil +end + ---@alias ow.Git.Repo.ResolveStatus "ok"|"ambiguous"|"missing" ---@param abbrev string diff --git a/test/git/repo_test.lua b/test/git/repo_test.lua index b22ab12..e418551 100644 --- a/test/git/repo_test.lua +++ b/test/git/repo_test.lua @@ -97,6 +97,25 @@ t.test("index_sha cache clears when the index is written", function() wait_cleared(r, "index:a", 2000) end) +t.test("head_sha returns the blob sha and caches it", function() + local dir = h.make_repo({ a = "x\n" }) + local r = assert(require("git.core.repo").resolve(dir)) + local sha = r:head_sha("a") + t.truthy(sha and #sha > 0, "head_sha returns the HEAD blob sha") + t.truthy(r._cache["head_blob:a"] ~= nil, "the result is cached") + t.eq(r:head_sha("a"), sha, "a cached call returns the same sha") +end) + +t.test("head_sha cache clears when HEAD moves", function() + local dir = h.make_repo({ a = "x\n" }) + local r = assert(require("git.core.repo").resolve(dir)) + r:head_sha("a") + t.truthy(r._cache["head_blob:a"] ~= nil, "sha is cached before the commit") + t.write(dir, "a", "y\n") + h.git(dir, "commit", "-aqm", "change") + wait_cleared(r, "head_blob:a", 2000) +end) + t.test("cache clears after top-level .git change (commit)", function() local dir = h.make_repo({ a = "x" }) local r = assert(require("git.core.repo").resolve(dir))