Skip to content
This repository has been archived by the owner on Dec 16, 2022. It is now read-only.

Commit

Permalink
Wrap, doc, test GitBlame (JuliaLang#22469)
Browse files Browse the repository at this point in the history
* Wrap, doc, test GitBlame

* Fixup docs

* Fix counthunks

* Fix char doc
  • Loading branch information
kshyatt authored and DrTodd13 committed Jun 26, 2017
1 parent e53da99 commit 7ce76dc
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 0 deletions.
37 changes: 37 additions & 0 deletions base/libgit2/blame.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

function GitBlame(repo::GitRepo, path::AbstractString; options::BlameOptions=BlameOptions())
blame_ptr_ptr = Ref{Ptr{Void}}(C_NULL)
@check ccall((:git_blame_file, :libgit2), Cint,
(Ptr{Ptr{Void}}, Ptr{Void}, Cstring, Ptr{BlameOptions}),
blame_ptr_ptr, repo.ptr, path, Ref(options))
return GitBlame(repo, blame_ptr_ptr[])
end

function counthunks(blame::GitBlame)
return ccall((:git_blame_get_hunk_count, :libgit2), Int32, (Ptr{Void},), blame.ptr)
end

function Base.getindex(blame::GitBlame, i::Integer)
if !(1 <= i <= counthunks(blame))
throw(BoundsError(blame, (i,)))
end
hunk_ptr = ccall((:git_blame_get_hunk_byindex, :libgit2),
Ptr{BlameHunk},
(Ptr{Void}, Csize_t), blame.ptr, i-1)
return unsafe_load(hunk_ptr)
end

function Base.show(io::IO, blame_hunk::BlameHunk)
println(io, "GitBlameHunk:")
println(io, "Original path: ", blame_hunk.orig.path)
println(io, "Lines in hunk: ", blame_hunk.lines_in_hunk)
println(io, "Final commit oid: ", blame_hunk.final_commit_id)
print(io, "Final signature: ")
show(io, blame_hunk.final_signature)
println()
println(io, "Original commit oid: ", blame_hunk.orig_commit_id)
print(io, "Original signature: ")
show(io, blame_hunk.orig_signature)
println()
end
1 change: 1 addition & 0 deletions base/libgit2/libgit2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ include("tag.jl")
include("blob.jl")
include("diff.jl")
include("rebase.jl")
include("blame.jl")
include("status.jl")
include("tree.jl")
include("callbacks.jl")
Expand Down
53 changes: 53 additions & 0 deletions base/libgit2/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,21 @@ Matches the [`git_merge_options`](https://libgit2.github.com/libgit2/#HEAD/type/
file_flags::GIT_MERGE_FILE = Consts.MERGE_FILE_DEFAULT
end

"""
LibGit2.BlameOptions
Matches the [`git_blame_options`](https://libgit2.github.com/libgit2/#HEAD/type/git_blame_options) struct.
"""
@kwdef struct BlameOptions
version::Cuint = 1
flags::UInt32 = 0
min_match_characters::UInt16 = 20
newest_commit::GitHash
oldest_commit::GitHash
min_line::Csize_t = 1
max_line::Csize_t = 0
end

"""
LibGit2.PushOptions
Expand Down Expand Up @@ -562,6 +577,7 @@ for (typ, owntyp, sup, cname) in [
(:GitDiffStats, :GitRepo, :AbstractGitObject, :git_diff_stats),
(:GitAnnotated, :GitRepo, :AbstractGitObject, :git_annotated_commit),
(:GitRebase, :GitRepo, :AbstractGitObject, :git_rebase),
(:GitBlame, :GitRepo, :AbstractGitObject, :git_blame),
(:GitStatus, :GitRepo, :AbstractGitObject, :git_status_list),
(:GitBranchIter, :GitRepo, :AbstractGitObject, :git_branch_iterator),
(:GitConfigIter, nothing, :AbstractGitObject, :git_config_iterator),
Expand Down Expand Up @@ -658,6 +674,43 @@ mutable struct Signature
time_offset::Cint
end

"""
LibGit2.BlameHunk
Matches the [`git_blame_hunk`](https://libgit2.github.com/libgit2/#HEAD/type/git_blame_hunk) struct.
The fields represent:
* `lines_in_hunk`: the number of lines in this hunk of the blame.
* `final_commit_id`: the [`GitHash`](@ref) of the commit where this section was last changed.
* `final_start_line_number`: the *one based* line number in the file where the
hunk starts, in the *final* version of the file.
* `final_signature`: the signature of the person who last modified this hunk. You will
need to pass this to [`Signature`](@ref) to access its fields.
* `orig_commit_id`: the [`GitHash`](@ref) of the commit where this hunk was first found.
* `orig_path`: the path to the file where the hunk originated. This may be different
than the current/final path, for instance if the file has been moved.
* `orig_start_line_number`: the *one based* line number in the file where the
hunk starts, in the *original* version of the file at `orig_path`.
* `orig_signature`: the signature of the person who introduced this hunk. You will
need to pass this to [`Signature`](@ref) to access its fields.
* `boundary`: `'1'` if the original commit is a "boundary" commit (for instance, if it's
equal to an oldest commit set in `options`).
"""
@kwdef struct BlameHunk
lines_in_hunk::Csize_t

final_commit_id::GitHash
final_start_line_number::Csize_t
final_signature::Ptr{SignatureStruct}

orig_commit_id::GitHash
orig_path::Cstring
orig_start_line_number::Csize_t
orig_signature::Ptr{SignatureStruct}

boundary::Char
end


""" Resource management helper function
"""
function with(f::Function, obj)
Expand Down
8 changes: 8 additions & 0 deletions test/libgit2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,14 @@ mktempdir() do dir
@test showstr[5] == "Message:"
@test showstr[6] == commit_msg1
@test LibGit2.revcount(repo, string(commit_oid1), string(commit_oid3)) == (-1,0)

blame = LibGit2.GitBlame(repo, test_file)
@test LibGit2.counthunks(blame) == 3
@test_throws BoundsError getindex(blame, LibGit2.counthunks(blame)+1)
@test_throws BoundsError getindex(blame, 0)
sig = LibGit2.Signature(blame[1].orig_signature)
@test sig.name == cmtr.name
@test sig.email == cmtr.email
finally
close(cmt)
end
Expand Down

0 comments on commit 7ce76dc

Please sign in to comment.