From d4923b1832c605c02bcd11e2f79344b6946fda95 Mon Sep 17 00:00:00 2001 From: SuperBo Date: Thu, 13 Jun 2024 08:04:18 +0700 Subject: [PATCH] fix: fix signed commit with initial branch --- lua/fugit2/core/git_gpg.lua | 31 +++++++++++++++++++++----- lua/fugit2/git2.lua | 40 ++++++++++++++++++++++++++++++---- lua/fugit2/libgit2.lua | 2 ++ lua/fugit2/view/git_status.lua | 2 +- 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/lua/fugit2/core/git_gpg.lua b/lua/fugit2/core/git_gpg.lua index 5329436..621df9e 100644 --- a/lua/fugit2/core/git_gpg.lua +++ b/lua/fugit2/core/git_gpg.lua @@ -3,6 +3,7 @@ local uv = vim.uv or vim.loop local PlenaryJob = require "plenary.job" +local git2 = require "fugit2.git2" local gpgme = require "fugit2.core.gpgme" local utils = require "fugit2.utils" @@ -117,20 +118,38 @@ end ---@return integer err ---@return string err_msg local function create_commit_with_sign(repo, commit_content, gpg_sign, msg) - local commit_id, head, err + local commit_id, head, head_direct, err commit_id, err = repo:create_commit_with_signature(commit_content, gpg_sign, nil) if not commit_id then return nil, err, "Failed to create commit with sign" end - head, err = repo:head() + head, err = repo:reference_lookup "HEAD" if not head then - return nil, err, "Failed to get git head" + return nil, err, "Failed to lookup HEAD" end - _, err = head:set_target(commit_id, utils.lines_head(msg)) - if err ~= 0 then - return nil, err, "Failed to set head to new commit" + head_direct, err = head:resolve() + if head_direct then + -- normal branch + _, err = head_direct:set_target(commit_id, "commit: " .. utils.lines_head(msg)) + if err ~= 0 then + return nil, err, "Failed to set head to new commit" + end + elseif err == git2.GIT_ERROR.GIT_ENOTFOUND then + -- initial branch + local head_ref_name = head:symbolic_target() + if not head_ref_name then + return nil, err, "Failed to get HEAD sympolic target" + end + + head, err = repo:create_reference(head_ref_name, commit_id, false, "commit (initial): " .. utils.lines_head(msg)) + if err ~= 0 then + return nil, err, "Failed to create initial reference " .. head_ref_name + end + else + -- error + return nil, err, "Failed to get HEAD target" end return commit_id, 0, "" diff --git a/lua/fugit2/git2.lua b/lua/fugit2/git2.lua index 1492370..0af1d10 100644 --- a/lua/fugit2/git2.lua +++ b/lua/fugit2/git2.lua @@ -1022,8 +1022,8 @@ function Reference:target() return nil, 0 end --- Conditionally creates a new reference --- with the same name as the given reference. +---Conditionally creates a new reference +---with the same name as the given reference. ---@param oid GitObjectId ---@param message string ---@return GitReference? @@ -1038,7 +1038,20 @@ function Reference:set_target(oid, message) return Reference.new(ref[0]), 0 end --- Recursively peel reference until object of the specified type is found. +---Resolves a symbolic reference to a direct reference. +---@return GitReference? ref git reference +---@return GIT_ERROR err error code +function Reference:resolve() + local ref = libgit2.git_reference_double_pointer() + local err = libgit2.C.git_reference_resolve(ref, self.ref) + if err ~= 0 then + return nil, err + end + + return Reference.new(ref[0]), 0 +end + +---Recursively peel reference until object of the specified type is found. ---@param type GIT_OBJECT ---@return GitObject? ---@return integer Git Error code @@ -2406,7 +2419,26 @@ function Repository:reference_name_to_id(refname) return ObjectId.borrow(oid), 0 end --- Gets commit from a reference. +---Creates a new direct reference. +---@param name string name of the reference. +---@param oid GitObjectId object id pointed to by the reference. +---@param is_force boolean is force. +---@param log_message string line long message to be appended to the reflog. +---@return GitReference? ref direct reference +---@return GIT_ERROR err error code +function Repository:create_reference(name, oid, is_force, log_message) + local git_ref = libgit2.git_reference_double_pointer() + local force = is_force and 1 or 0 + + local err = libgit2.C.git_reference_create(git_ref, self.repo, name, oid.oid, force, log_message) + if err ~= 0 then + return nil, err + end + + return Reference.new(git_ref[0]), 0 +end + +---Gets commit from a reference. ---@param oid GitObjectId ---@return GitCommit? ---@return GIT_ERROR diff --git a/lua/fugit2/libgit2.lua b/lua/fugit2/libgit2.lua index d0548e9..ab1793c 100644 --- a/lua/fugit2/libgit2.lua +++ b/lua/fugit2/libgit2.lua @@ -500,6 +500,8 @@ ffi.cdef [[ int git_reference_name_to_id(git_oid *out, git_repository *repo, const char *name); int git_reference_lookup(git_reference **out, git_repository *repo, const char *name); const char * git_reference_symbolic_target(const git_reference *ref); + int git_reference_create(git_reference **out, git_repository *repo, const char *name, const git_oid *id, int force, const char *log_message); + int git_reference_symbolic_create(git_reference **out, git_repository *repo, const char *name, const char *target, int force, const char *log_message); int git_revwalk_new(git_revwalk **walker, git_repository *repo); int git_revwalk_push(git_revwalk *walk, const git_oid *oid); diff --git a/lua/fugit2/view/git_status.lua b/lua/fugit2/view/git_status.lua index 2226fe2..3f98346 100644 --- a/lua/fugit2/view/git_status.lua +++ b/lua/fugit2/view/git_status.lua @@ -1,6 +1,6 @@ -- Fugit2 Git Status module -local uv = vim.loop +local uv = vim.uv or vim.loop local NuiLayout = require "nui.layout" local NuiLine = require "nui.line"