-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
/
Copy pathcommit.jl
134 lines (120 loc) · 5.22 KB
/
commit.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# This file is a part of Julia. License is MIT: https://julialang.org/license
"""
message(c::GitCommit, raw::Bool=false)
Return the commit message describing the changes made in commit `c`. If
`raw` is `false`, return a slightly "cleaned up" message (which has any
leading newlines removed). If `raw` is `true`, the message is not stripped
of any such newlines.
"""
function message(c::GitCommit, raw::Bool=false)
local msg_ptr::Cstring
msg_ptr = raw ? ccall((:git_commit_message_raw, :libgit2), Cstring, (Ptr{Void},), c.ptr) :
ccall((:git_commit_message, :libgit2), Cstring, (Ptr{Void},), c.ptr)
if msg_ptr == C_NULL
return nothing
end
return unsafe_string(msg_ptr)
end
"""
author(c::GitCommit)
Return the `Signature` of the author of the commit `c`. The author is
the person who made changes to the relevant file(s). See also [`committer`](@ref).
"""
function author(c::GitCommit)
ptr = ccall((:git_commit_author, :libgit2), Ptr{SignatureStruct}, (Ptr{Void},), c.ptr)
@assert ptr != C_NULL
return Signature(ptr)
end
"""
committer(c::GitCommit)
Return the `Signature` of the committer of the commit `c`. The committer is
the person who committed the changes originally authored by the [`author`](@ref), but
need not be the same as the `author`, for example, if the `author` emailed a patch to
a `committer` who committed it.
"""
function committer(c::GitCommit)
ptr = ccall((:git_commit_committer, :libgit2), Ptr{SignatureStruct}, (Ptr{Void},), c.ptr)
@assert ptr != C_NULL
return Signature(ptr)
end
function Base.show(io::IO, c::GitCommit)
authstr = sprint(show, author(c))
cmtrstr = sprint(show, committer(c))
print(io, "Git Commit:\nCommit Author: $authstr\nCommitter: $cmtrstr\nSHA: $(GitHash(c))\nMessage:\n$(message(c))")
end
function commit(repo::GitRepo,
refname::AbstractString,
msg::AbstractString,
author::GitSignature,
committer::GitSignature,
tree::GitTree,
parents::GitCommit...)
commit_id_ptr = Ref(GitHash())
nparents = length(parents)
parentptrs = Ptr{Void}[c.ptr for c in parents]
@check ccall((:git_commit_create, :libgit2), Cint,
(Ptr{GitHash}, Ptr{Void}, Ptr{UInt8},
Ptr{SignatureStruct}, Ptr{SignatureStruct},
Ptr{UInt8}, Ptr{UInt8}, Ptr{Void},
Csize_t, Ptr{Ptr{Void}}),
commit_id_ptr, repo.ptr, isempty(refname) ? C_NULL : refname,
author.ptr, committer.ptr,
C_NULL, msg, tree.ptr,
nparents, nparents > 0 ? parentptrs : C_NULL)
return commit_id_ptr[]
end
"""
commit(repo::GitRepo, msg::AbstractString; kwargs...) -> GitHash
Wrapper around [`git_commit_create`](https://libgit2.github.com/libgit2/#HEAD/group/commit/git_commit_create).
Create a commit in the repository `repo`. `msg` is the commit message. Return the OID of the new commit.
The keyword arguments are:
* `refname::AbstractString=Consts.HEAD_FILE`: if not NULL, the name of the reference to update to point to
the new commit. For example, `"HEAD"` will update the HEAD of the current branch. If the reference does
not yet exist, it will be created.
* `author::Signature = Signature(repo)` is a `Signature` containing information about the person who authored the commit.
* `committer::Signature = Signature(repo)` is a `Signature` containing information about the person who commited the commit to
the repository. Not necessarily the same as `author`, for instance if `author` emailed a patch to
`committer` who committed it.
* `tree_id::GitHash = GitHash()` is a git tree to use to create the commit, showing its ancestry and relationship with
any other history. `tree` must belong to `repo`.
* `parent_ids::Vector{GitHash}=GitHash[]` is a list of commits by [`GitHash`](@ref) to use as parent
commits for the new one, and may be empty. A commit might have multiple parents if it is a merge commit, for example.
"""
function commit(repo::GitRepo, msg::AbstractString;
refname::AbstractString=Consts.HEAD_FILE,
author::Signature = Signature(repo),
committer::Signature = Signature(repo),
tree_id::GitHash = GitHash(),
parent_ids::Vector{GitHash}=GitHash[])
# Retrieve tree identifier
if iszero(tree_id)
tree_id = with(GitIndex, repo) do idx; write_tree!(idx) end
end
# Retrieve parents from HEAD
if isempty(parent_ids)
try # if throws then HEAD not found -> empty repo
push!(parent_ids, GitHash(repo, refname))
end
end
# return commit id
commit_id = GitHash()
# get necessary objects
tree = GitTree(repo, tree_id)
auth_sig = convert(GitSignature, author)
comm_sig = convert(GitSignature, committer)
parents = GitCommit[]
try
for id in parent_ids
push!(parents, GitCommit(repo, id))
end
commit_id = commit(repo, refname, msg, auth_sig, comm_sig, tree, parents...)
finally
for parent in parents
close(parent)
end
close(tree)
close(auth_sig)
close(comm_sig)
end
return commit_id
end