Add gitc_commit_is_signed() to stdlib/LibGit2

All,

Here’s my lame attempt to extend Julia’s LibGit2 API:

function gitc_commit_is_signed(repo::GitRepo, hstr::AbstractString,
                               sig_type::AbstractString)
        isempty(hstr) && return false
        if isempty(sig_type)
                sig_type = AbstractString("gpgsig")
        end
        is_signed = false

        sig  = LibGit2.Buffer()
        data = LibGit2.Buffer()
        oid  = Ref{LibGit2.GitHash}()
        oid  = LibGit2.GitHash(hstr)

        ret = ccall((:git_commit_extract_signature, :libgit2), Int64,
                (LibGit2.Buffer, LibGit2.Buffer,
                 Ptr{Cvoid}, Ptr{LibGit2.GitHash}, Cstring),
                sig, data, repo.ptr, Ref{oid}, sig_type)

        is_signed = ret == 0

        LibGit2.free(sig_ptr)
        LibGit2.free(data_ptr)

        return is_signed
end

From within my own script. I’m attempting to call:

https://libgit2.org/libgit2/#HEAD/group/commit/git_commit_extract_signature

To determine if a given commit is signed. Please note: This is not a signed tag, but rather a signed commit. The difference being that a signed commit becomes the HEAD of the current branch and a parent to the next commit. Whereas a signed tag refers to a commit, and can be added at any time since it never becomes a parent.

So, this thing has been blowing up in my face all day. :-/

julia> include("src/gitviz.jl")
ERROR: LoadError: MethodError: no method matching unsafe_convert(::Type{Ptr{LibGit2.GitHash}}, ::Type{Ref{GitHash("e4291860f44db818f8d9c8ffee44f2752d92ca30")}})
Closest candidates are:
  unsafe_convert(::Type{T<:Ptr}, ::T<:Ptr) where T<:Ptr at essentials.jl:347
  unsafe_convert(::Type{P<:Ptr}, ::Ptr) where P<:Ptr at essentials.jl:348
  unsafe_convert(::Type{Ptr{T}}, ::Array{T,N} where N) where T at pointer.jl:65
  ...
Stacktrace:
 [1] gitc_commit_is_signed(::GitRepo, ::String, ::String) at /Users/jason/src/all/gitviz.git/src/gitviz.jl:156
 [2] gitc_walk_branch(::GitRepo, ::String) at /Users/jason/src/all/gitviz.git/src/gitviz.jl:190
 [3] top-level scope at none:0
 [4] include at ./boot.jl:317 [inlined]
 [5] include_relative(::Module, ::String) at ./loading.jl:1038
 [6] include(::Module, ::String) at ./sysimg.jl:29
 [7] include(::String) at ./client.jl:388
 [8] top-level scope at none:0
in expression starting at /Users/jason/src/all/gitviz.git/src/gitviz.jl:244

This particular incantation is tying me in knots. Whereas

        w = LibGit2.GitRevWalker(repo)

        ccall((:git_revwalk_simplify_first_parent, :libgit2), Cvoid,
                (Ptr{LibGit2.GitRevWalker},), w.ptr)

        for c in LibGit2.with(w) do walker
                                LibGit2.map((oid, repo)->string(oid),
                                oid = LibGit2.GitHash(repo, b), walker)
                end

was extremely easy. Could anyone give me an assist with detecting signed commits? I’m happy to do a PR once I get something not so embarrassing working properly. I could also do a patch adding a “firstparent::Bool” to the GitRevWalker map() function.

Thanks,

Jason.

You’re reassigning the value of the variable oid, instead of assigning to the value contained in the Ref that oid points to. Change:
oid = LibGit2.GitHash(hstr)
to
oid[] = LibGit2.GitHash(hstr)
and then probably change the Ref{oid} within your ccall to just oid (or maybe not, I’m not great with ccalls).
That should hopefully work (assuming the rest of your code works too :slight_smile:).

1 Like