1 /*
2  *             Copyright Sönke Ludwig 2014.
3  *  Distributed under the Boost Software License, Version 1.0.
4  *     (See accompanying file LICENSE_1_0.txt or copy at
5  *           http://www.boost.org/LICENSE_1_0.txt)
6  */
7 module git.commit;
8 
9 import git.object_;
10 import git.oid;
11 import git.repository;
12 import git.signature;
13 import git.tree;
14 import git.types;
15 import git.util;
16 import git.version_;
17 
18 import deimos.git2.commit;
19 import deimos.git2.types;
20 
21 import std.conv : to;
22 import std.string : toStringz;
23 import std.datetime;
24 
25 
26 GitCommit lookupCommit(GitRepo repo, GitOid oid)
27 {
28 	git_commit* ret;
29 	require(git_commit_lookup(&ret, repo.cHandle, &oid._get_oid()) == 0);
30 	return GitCommit(repo, ret);
31 }
32 
33 GitCommit lookupCommitPrefix(GitRepo repo, GitOid oid, size_t oid_length)
34 {
35 	git_commit* ret;
36 	require(git_commit_lookup_prefix(&ret, repo.cHandle, &oid._get_oid(), oid_length) == 0);
37 	return GitCommit(repo, ret);
38 }
39 
40 GitOid createCommit(GitRepo repo, string update_ref, GitSignature author, GitSignature committer, string message, GitTree tree, const(GitCommit)[] parents...)
41 {
42 	GitOid ret;
43 	assert(parents.length < int.max, "Number of parents may not exceed int.max");
44 	auto cparents = new const(git_commit)*[parents.length];
45 	foreach (i, ref cp; cparents) cp = parents[i].cHandle;
46 	require(git_commit_create(&ret._get_oid(), repo.cHandle,
47 		update_ref ? update_ref.toStringz : null, author.cHandle, committer.cHandle,
48 		null, message.toStringz, tree.cHandle, cast(int)cparents.length, cparents.ptr) == 0);
49 	return ret;
50 }
51 
52 
53 struct GitCommit {
54 	this(GitObject obj)
55 	{
56 		enforce(obj.type == GitType.commit, "GIT object is not a commit.");
57 		_object = obj;
58 	}
59 
60 	package this(GitRepo repo, git_commit* commit)
61 	{
62 		_object = GitObject(repo, cast(git_object*)commit);
63 	}
64 
65 	@property GitOid id() { return GitOid(*git_commit_id(this.cHandle)); }
66 	@property GitRepo owner() { return _object.owner; }
67 	@property string messageEncoding() { return git_commit_message_encoding(this.cHandle).to!string; }
68 	@property string message() { return git_commit_message(this.cHandle).to!string; }
69 	static if (targetLibGitVersion >= VersionInfo(0, 20, 0))
70 		@property string rawMessage() { return git_commit_message_raw(this.cHandle).to!string; }
71 
72 	@property SysTime commitTime()
73 	{
74 		git_time tm;
75 		tm.time = git_commit_time(this.cHandle);
76 		tm.offset = git_commit_time_offset(this.cHandle);
77 		return tm.toSysTime();
78 	}
79 
80 	@property GitSignature committer() { return GitSignature(this, git_commit_committer(this.cHandle)); }
81 	@property GitSignature author() { return GitSignature(this, git_commit_author(this.cHandle)); }
82 	static if (targetLibGitVersion >= VersionInfo(0, 20, 0))
83 		@property string rawHeader() { return git_commit_raw_header(this.cHandle).to!string; }
84 
85 	@property GitTree tree()
86 	{
87 		git_tree* ret;
88 		require(git_commit_tree(&ret, this.cHandle) == 0);
89 		return GitTree(this.owner, ret);
90 	}
91 	@property GitOid treeId() { return GitOid(*git_commit_tree_id(this.cHandle)); }
92 
93 	@property uint parentCount() { return git_commit_parentcount(this.cHandle); }
94 
95 	@property GitOid[] parentOids()
96 	{
97 		auto ret = new GitOid[parentCount];
98 		foreach (i; 0 .. cast(uint)ret.length) ret[i] = getParentOid(i);
99 		return ret;
100 	}
101 
102 	@property GitCommit[] parents()
103 	{
104 		auto ret = new GitCommit[parentCount];
105 		foreach (i; 0 .. cast(uint)ret.length) ret[i] = getParent(i);
106 		return ret;
107 	}
108 
109 	GitCommit getParent(uint index)
110 	{
111 		git_commit* ret;
112 		require(git_commit_parent(&ret, this.cHandle, index) == 0);
113 		return GitCommit(this.owner, ret);
114 	}
115 
116 	GitOid getParentOid(uint index)
117 	{
118 		return GitOid(*git_commit_parent_id(this.cHandle, index));
119 	}
120 
121 	GitCommit getNthGenAncestor(uint n)
122 	{
123 		git_commit* ret;
124 		require(git_commit_nth_gen_ancestor(&ret, this.cHandle, n) == 0);
125 		return GitCommit(this.owner, ret);
126 	}
127 
128 	package @property inout(git_commit)* cHandle() inout { return cast(inout(git_commit)*)_object.cHandle; }
129 
130 	private GitObject _object;
131 }