feat(git): added support for packed-refs. Fixes #260

This commit is contained in:
Folke Lemaitre 2022-12-31 09:32:35 +01:00
parent f656706de0
commit 865ff414c7
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
2 changed files with 43 additions and 10 deletions

View File

@ -11,13 +11,13 @@ local M = {}
---@param details? boolean Fetching details is slow! Don't loop over a plugin to fetch all details! ---@param details? boolean Fetching details is slow! Don't loop over a plugin to fetch all details!
---@return GitInfo? ---@return GitInfo?
function M.info(repo, details) function M.info(repo, details)
local line = Util.head(repo .. "/.git/HEAD") local line = M.head(repo)
if line then if line then
---@type string, string ---@type string, string
local ref, branch = line:match("ref: (refs/heads/(.*))") local ref, branch = line:match("ref: refs/(heads/(.*))")
local ret = ref and { local ret = ref and {
branch = branch, branch = branch,
commit = Util.head(repo .. "/.git/" .. ref), commit = M.ref(repo, ref),
} or { commit = line } } or { commit = line }
if details then if details then
@ -33,6 +33,10 @@ function M.info(repo, details)
end end
end end
function M.head(repo)
return Util.head(repo .. "/.git/HEAD")
end
---@class TaggedSemver: Semver ---@class TaggedSemver: Semver
---@field tag string ---@field tag string
@ -41,17 +45,32 @@ function M.get_versions(repo, spec)
local range = Semver.range(spec or "*") local range = Semver.range(spec or "*")
---@type TaggedSemver[] ---@type TaggedSemver[]
local versions = {} local versions = {}
Util.ls(repo .. "/.git/refs/tags", function(_, name) for _, tag in ipairs(M.get_tags(repo)) do
local v = Semver.version(name) local v = Semver.version(tag)
---@cast v TaggedSemver ---@cast v TaggedSemver
if v and range:matches(v) then if v and range:matches(v) then
v.tag = name v.tag = tag
table.insert(versions, v) table.insert(versions, v)
end end
end) end
return versions return versions
end end
function M.get_tags(repo)
---@type string[]
local ret = {}
Util.ls(repo .. "/.git/refs/tags", function(_, name)
ret[#ret + 1] = name
end)
for name in pairs(M.packed_refs(repo)) do
local tag = name:match("^tags/(.*)")
if tag then
ret[#ret + 1] = tag
end
end
return ret
end
---@param plugin LazyPlugin ---@param plugin LazyPlugin
---@return string? ---@return string?
function M.get_branch(plugin) function M.get_branch(plugin)
@ -69,7 +88,7 @@ function M.get_branch(plugin)
end end
-- fallback to local HEAD -- fallback to local HEAD
main = assert(Util.head(plugin.dir .. "/.git/HEAD")) main = assert(M.head(plugin.dir))
return main and main:match("ref: refs/heads/(.*)") return main and main:match("ref: refs/heads/(.*)")
end end
end end
@ -133,7 +152,22 @@ function M.ref(repo, ...)
end end
-- otherwise just get the ref -- otherwise just get the ref
return Util.head(repo .. "/.git/refs/" .. ref) return Util.head(repo .. "/.git/refs/" .. ref) or M.packed_refs(repo)[ref]
end
function M.packed_refs(repo)
local ok, refs = pcall(Util.read_file, repo .. "/.git/packed-refs")
---@type table<string,string>
local ret = {}
if ok then
for _, line in ipairs(vim.split(refs, "\n")) do
local ref, name = line:match("^(.*) refs/(.*)$")
if ref then
ret[name] = ref
end
end
end
return ret
end end
-- this is slow, so don't use on a loop over all plugins! -- this is slow, so don't use on a loop over all plugins!

View File

@ -58,7 +58,6 @@ M.clone = {
self.plugin.url, self.plugin.url,
"--filter=blob:none", "--filter=blob:none",
"--recurse-submodules", "--recurse-submodules",
"--single-branch",
"--progress", "--progress",
} }