diff --git a/lua/lazy/manage/git.lua b/lua/lazy/manage/git.lua new file mode 100644 index 00000000..965d9426 --- /dev/null +++ b/lua/lazy/manage/git.lua @@ -0,0 +1,94 @@ +local Util = require("lazy.util") +local Semver = require("lazy.manage.semver") + +local M = {} + +---@param details? boolean +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 +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 +function M.get_target(plugin) + local branch = M.get_branch(plugin) + + if plugin.commit then + return { branch = branch, commit = plugin.commit } + end + if plugin.tag then + return { 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, version = last, tag = last.tag, commit = M.ref(plugin.dir, "tags/" .. last.tag) } + end + end + return { branch = branch, commit = branch.commit } +end + +function M.ref(repo, ref) + return Util.head(repo .. "/.git/refs/" .. ref) +end + +return M diff --git a/lua/lazy/manage/task/git.lua b/lua/lazy/manage/task/git.lua index b1a08c99..e42918ab 100644 --- a/lua/lazy/manage/task/git.lua +++ b/lua/lazy/manage/task/git.lua @@ -1,4 +1,5 @@ local Util = require("lazy.util") +local Git = require("lazy.manage.git") ---@type table local M = {} @@ -51,17 +52,17 @@ M.update = { "--update-shallow", "--progress", } - local git = assert(Util.git_info(self.plugin.dir)) + local git = assert(Git.info(self.plugin.dir)) self:spawn("git", { args = args, cwd = self.plugin.dir, on_exit = function(ok) if ok then - local git_new = assert(Util.git_info(self.plugin.dir)) + local git_new = assert(Git.info(self.plugin.dir)) self.plugin._.updated = { - from = git.hash, - to = git_new.hash, + from = git.commit, + to = git_new.commit, } self.plugin._.dirty = not vim.deep_equal(git, git_new) end diff --git a/lua/lazy/view/render.lua b/lua/lazy/view/render.lua index 48ded14d..15b5fa96 100644 --- a/lua/lazy/view/render.lua +++ b/lua/lazy/view/render.lua @@ -3,6 +3,7 @@ local Util = require("lazy.util") local Sections = require("lazy.view.sections") local Handler = require("lazy.core.handler") local Plugin = require("lazy.core.plugin") +local Git = require("lazy.manage.git") local Text = require("lazy.view.text") @@ -294,10 +295,18 @@ function M:details(plugin) ---@type string[][] local props = {} table.insert(props, { "uri", (plugin.uri:gsub("%.git$", "")), "@text.reference" }) - local git = Util.git_info(plugin.dir) + local git = Git.info(plugin.dir, true) if git then - table.insert(props, { "commit", git.hash:sub(1, 7), "LazyCommit" }) - table.insert(props, { "branch", git.branch }) + if git.version then + table.insert(props, { "version", tostring(git.version) }) + end + if git.tag then + table.insert(props, { "tag", git.tag }) + end + if git.branch then + table.insert(props, { "branch", git.branch }) + end + table.insert(props, { "commit", git.commit:sub(1, 7), "LazyCommit" }) end if Util.file_exists(plugin.dir .. "/README.md") then table.insert(props, { "readme", "README.md" })