fix(git): fixed branch detection, get target commit from origin and always checkout a tag or commit so we dont need to use git merge

This commit is contained in:
Folke Lemaitre 2022-12-02 11:26:07 +01:00
parent 3e143c6017
commit ae379a62dc
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
3 changed files with 44 additions and 24 deletions

View File

@ -51,41 +51,54 @@ function M.get_versions(repo, spec)
end end
---@param plugin LazyPlugin ---@param plugin LazyPlugin
---@return {branch:string, commit?:string}? ---@return string?
function M.get_branch(plugin) function M.get_branch(plugin)
if plugin.branch then if plugin.branch then
return { return plugin.branch
branch = plugin.branch,
commit = M.ref(plugin.dir, "heads/" .. plugin.branch),
}
else else
-- we need to return the default branch
-- Try origin first
local main = M.ref(plugin.dir, "remotes/origin/HEAD") local main = M.ref(plugin.dir, "remotes/origin/HEAD")
if main then if main then
local branch = main:match("ref: refs/remotes/origin/(.*)") local branch = main:match("ref: refs/remotes/origin/(.*)")
if branch then if branch then
return { return branch
branch = branch,
commit = M.ref(plugin.dir, "heads/" .. branch),
}
end end
end end
-- fallback to local HEAD
main = assert(Util.head(plugin.dir .. "/.git/HEAD"))
return main and main:match("ref: refs/heads/(.*)")
end
end
-- Return the last commit for the given branch
---@param repo string
---@param branch string
---@param origin? boolean
function M.get_commit(repo, branch, origin)
if origin then
-- origin ref might not exist if it is the same as local
return M.ref(repo, "remotes/origin", branch) or M.ref(repo, "heads", branch)
else
return M.ref(repo, "heads", branch)
end end
end end
---@param plugin LazyPlugin ---@param plugin LazyPlugin
---@return GitInfo? ---@return GitInfo?
function M.get_target(plugin) function M.get_target(plugin)
local branch = M.get_branch(plugin) or M.info(plugin.dir) local branch = assert(M.get_branch(plugin))
if plugin.commit then if plugin.commit then
return { return {
branch = branch and branch.branch, branch = branch,
commit = plugin.commit, commit = plugin.commit,
} }
end end
if plugin.tag then if plugin.tag then
return { return {
branch = branch and branch.branch, branch = branch,
tag = plugin.tag, tag = plugin.tag,
commit = M.ref(plugin.dir, "tags/" .. plugin.tag), commit = M.ref(plugin.dir, "tags/" .. plugin.tag),
} }
@ -95,7 +108,7 @@ function M.get_target(plugin)
local last = Semver.last(M.get_versions(plugin.dir, version)) local last = Semver.last(M.get_versions(plugin.dir, version))
if last then if last then
return { return {
branch = branch and branch.branch, branch = branch,
version = last, version = last,
tag = last.tag, tag = last.tag,
commit = M.ref(plugin.dir, "tags/" .. last.tag), commit = M.ref(plugin.dir, "tags/" .. last.tag),
@ -103,11 +116,11 @@ function M.get_target(plugin)
end end
end end
---@diagnostic disable-next-line: return-type-mismatch ---@diagnostic disable-next-line: return-type-mismatch
return branch return { branch = branch, commit = M.get_commit(plugin.dir, branch, true) }
end end
function M.ref(repo, ref) function M.ref(repo, ...)
return Util.head(repo .. "/.git/refs/" .. ref) return Util.head(repo .. "/.git/refs/" .. table.concat({ ... }, "/"))
end end
return M return M

View File

@ -29,8 +29,7 @@ function M.update()
if not plugin._.is_local and plugin._.installed then if not plugin._.is_local and plugin._.installed then
local info = assert(Git.info(plugin.dir)) local info = assert(Git.info(plugin.dir))
if not info.branch then if not info.branch then
local branch = assert(Git.get_branch(plugin)) info.branch = assert(Git.get_branch(plugin))
info.branch = branch.branch
end end
info.commit = info.commit info.commit = info.commit
-- f:write(([[ [%q] = { branch = %q, commit = %q },]]):format(name, info.branch, info.commit) .. "\n") -- f:write(([[ [%q] = { branch = %q, commit = %q },]]):format(name, info.branch, info.commit) .. "\n")

View File

@ -30,6 +30,7 @@ M.log = {
elseif opts.check then elseif opts.check then
local info = assert(Git.info(self.plugin.dir)) local info = assert(Git.info(self.plugin.dir))
local target = assert(Git.get_target(self.plugin)) local target = assert(Git.get_target(self.plugin))
assert(target.commit, self.plugin.name .. " " .. target.branch)
table.insert(args, info.commit .. ".." .. target.commit) table.insert(args, info.commit .. ".." .. target.commit)
else else
vim.list_extend(args, opts.args or Config.options.git.log) vim.list_extend(args, opts.args or Config.options.git.log)
@ -76,22 +77,23 @@ M.clone = {
end, end,
} }
-- setup origin branches if needed
-- fetch will retrieve the data
M.branch = { M.branch = {
skip = function(plugin) skip = function(plugin)
if not plugin._.installed or plugin._.is_local then if not plugin._.installed or plugin._.is_local then
return true return true
end end
local branch = assert(Git.get_branch(plugin)) local branch = assert(Git.get_branch(plugin))
return branch and branch.commit return Git.get_commit(plugin.dir, branch)
end, end,
run = function(self) run = function(self)
local branch = assert(Git.get_branch(self.plugin))
local args = { local args = {
"remote", "remote",
"set-branches", "set-branches",
"--add", "--add",
"origin", "origin",
branch.branch, assert(Git.get_branch(self.plugin)),
} }
self:spawn("git", { self:spawn("git", {
@ -101,6 +103,7 @@ M.branch = {
end, end,
} }
-- fetches all needed origin branches
M.fetch = { M.fetch = {
skip = function(plugin) skip = function(plugin)
return not plugin._.installed or plugin._.is_local return not plugin._.installed or plugin._.is_local
@ -121,6 +124,8 @@ M.fetch = {
end, end,
} }
-- checkout to the target commit
-- branches will exists at this point, so so will the commit
M.checkout = { M.checkout = {
skip = function(plugin) skip = function(plugin)
return not plugin._.installed or plugin._.is_local return not plugin._.installed or plugin._.is_local
@ -131,7 +136,7 @@ M.checkout = {
local info = assert(Git.info(self.plugin.dir)) local info = assert(Git.info(self.plugin.dir))
local target = assert(Git.get_target(self.plugin)) local target = assert(Git.get_target(self.plugin))
-- if the plugin is locked and we did not just clone it, -- if the plugin is pinned and we did not just clone it,
-- then don't update -- then don't update
if self.plugin.pin and not self.plugin._.cloned then if self.plugin.pin and not self.plugin._.cloned then
target = info target = info
@ -139,6 +144,7 @@ M.checkout = {
local lock local lock
if opts.lockfile then if opts.lockfile then
-- restore to the lock if it exists
lock = Lock.get(self.plugin) lock = Lock.get(self.plugin)
if lock then if lock then
---@diagnostic disable-next-line: cast-local-type ---@diagnostic disable-next-line: cast-local-type
@ -146,6 +152,8 @@ M.checkout = {
end end
end end
-- dont run checkout if target is already reached.
-- unless we just clones, since then we won't have any data yet
if not self.plugin._.cloned and info.commit == target.commit and info.branch == target.branch then if not self.plugin._.cloned and info.commit == target.commit and info.branch == target.branch then
self.plugin._.updated = { self.plugin._.updated = {
from = info.commit, from = info.commit,
@ -165,8 +173,8 @@ M.checkout = {
table.insert(args, "tags/" .. target.tag) table.insert(args, "tags/" .. target.tag)
elseif self.plugin.commit then elseif self.plugin.commit then
table.insert(args, self.plugin.commit) table.insert(args, self.plugin.commit)
elseif target.branch then else
table.insert(args, target.branch) table.insert(args, target.commit)
end end
self:spawn("git", { self:spawn("git", {