local Util = require("lazy.util") local Semver = require("lazy.manage.semver") local M = {} ---@alias GitInfo {branch?:string, commit?:string, tag?:string, version?:Semver} ---@param details? boolean ---@return GitInfo? function M.info(repo, details) local line = Util.head(repo .. "/.git/HEAD") if line then ---@type string, string local ref, branch = line:match("ref: (refs/heads/(.*))") local ret = ref and { branch = branch, commit = Util.head(repo .. "/.git/" .. ref), } or { commit = line } if details then Util.ls(repo .. "/.git/refs/tags", function(_, name) if M.ref(repo, "tags/" .. name) == ret.commit then ret.tag = name ret.version = Semver.version(name) return false end end) end return ret end end ---@class TaggedSemver: Semver ---@field tag string ---@param spec? string function M.get_versions(repo, spec) local range = Semver.range(spec or "*") ---@type TaggedSemver[] local versions = {} Util.ls(repo .. "/.git/refs/tags", function(_, name) local v = Semver.version(name) ---@cast v TaggedSemver if v and range:matches(v) then v.tag = name table.insert(versions, v) end end) return versions end ---@param plugin LazyPlugin ---@return {branch:string, commit?:string}? function M.get_branch(plugin) if plugin.branch then return { branch = plugin.branch, commit = M.ref(plugin.dir, "heads/" .. plugin.branch), } else local main = M.ref(plugin.dir, "remotes/origin/HEAD") if main then local branch = main:match("ref: refs/remotes/origin/(.*)") if branch then return { branch = branch, commit = M.ref(plugin.dir, "heads/" .. branch), } end end end end ---@param plugin LazyPlugin ---@return GitInfo? function M.get_target(plugin) local branch = M.get_branch(plugin) or M.info(plugin.dir) if plugin.commit then return { branch = branch and branch.branch, commit = plugin.commit, } end if plugin.tag then return { branch = branch and branch.branch, tag = plugin.tag, commit = M.ref(plugin.dir, "tags/" .. plugin.tag), } end if plugin.version then local last = Semver.last(M.get_versions(plugin.dir, plugin.version)) if last then return { branch = branch and branch.branch, version = last, tag = last.tag, commit = M.ref(plugin.dir, "tags/" .. last.tag), } end end ---@diagnostic disable-next-line: return-type-mismatch return branch end function M.ref(repo, ref) return Util.head(repo .. "/.git/refs/" .. ref) end return M