]> git.proxmox.com Git - libgit2.git/blob - src/annotated_commit.c
New upstream version 1.3.0+dfsg.1
[libgit2.git] / src / annotated_commit.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8 #include "annotated_commit.h"
9
10 #include "refs.h"
11 #include "cache.h"
12
13 #include "git2/commit.h"
14 #include "git2/refs.h"
15 #include "git2/repository.h"
16 #include "git2/annotated_commit.h"
17 #include "git2/revparse.h"
18 #include "git2/tree.h"
19 #include "git2/index.h"
20
21 static int annotated_commit_init(
22 git_annotated_commit **out,
23 git_commit *commit,
24 const char *description)
25 {
26 git_annotated_commit *annotated_commit;
27 int error = 0;
28
29 GIT_ASSERT_ARG(out);
30 GIT_ASSERT_ARG(commit);
31
32 *out = NULL;
33
34 annotated_commit = git__calloc(1, sizeof(git_annotated_commit));
35 GIT_ERROR_CHECK_ALLOC(annotated_commit);
36
37 annotated_commit->type = GIT_ANNOTATED_COMMIT_REAL;
38
39 if ((error = git_commit_dup(&annotated_commit->commit, commit)) < 0)
40 goto done;
41
42 git_oid_fmt(annotated_commit->id_str, git_commit_id(commit));
43 annotated_commit->id_str[GIT_OID_HEXSZ] = '\0';
44
45 if (!description)
46 description = annotated_commit->id_str;
47
48 annotated_commit->description = git__strdup(description);
49 GIT_ERROR_CHECK_ALLOC(annotated_commit->description);
50
51 done:
52 if (!error)
53 *out = annotated_commit;
54
55 return error;
56 }
57
58 static int annotated_commit_init_from_id(
59 git_annotated_commit **out,
60 git_repository *repo,
61 const git_oid *id,
62 const char *description)
63 {
64 git_commit *commit = NULL;
65 int error = 0;
66
67 GIT_ASSERT_ARG(out);
68 GIT_ASSERT_ARG(repo);
69 GIT_ASSERT_ARG(id);
70
71 *out = NULL;
72
73 if ((error = git_commit_lookup(&commit, repo, id)) < 0)
74 goto done;
75
76 error = annotated_commit_init(out, commit, description);
77
78 done:
79 git_commit_free(commit);
80 return error;
81 }
82
83 int git_annotated_commit_lookup(
84 git_annotated_commit **out,
85 git_repository *repo,
86 const git_oid *id)
87 {
88 return annotated_commit_init_from_id(out, repo, id, NULL);
89 }
90
91 int git_annotated_commit_from_commit(
92 git_annotated_commit **out,
93 git_commit *commit)
94 {
95 return annotated_commit_init(out, commit, NULL);
96 }
97
98 int git_annotated_commit_from_revspec(
99 git_annotated_commit **out,
100 git_repository *repo,
101 const char *revspec)
102 {
103 git_object *obj, *commit;
104 int error;
105
106 GIT_ASSERT_ARG(out);
107 GIT_ASSERT_ARG(repo);
108 GIT_ASSERT_ARG(revspec);
109
110 if ((error = git_revparse_single(&obj, repo, revspec)) < 0)
111 return error;
112
113 if ((error = git_object_peel(&commit, obj, GIT_OBJECT_COMMIT))) {
114 git_object_free(obj);
115 return error;
116 }
117
118 error = annotated_commit_init(out, (git_commit *)commit, revspec);
119
120 git_object_free(obj);
121 git_object_free(commit);
122
123 return error;
124 }
125
126 int git_annotated_commit_from_ref(
127 git_annotated_commit **out,
128 git_repository *repo,
129 const git_reference *ref)
130 {
131 git_object *peeled;
132 int error = 0;
133
134 GIT_ASSERT_ARG(out);
135 GIT_ASSERT_ARG(repo);
136 GIT_ASSERT_ARG(ref);
137
138 *out = NULL;
139
140 if ((error = git_reference_peel(&peeled, ref, GIT_OBJECT_COMMIT)) < 0)
141 return error;
142
143 error = annotated_commit_init_from_id(out,
144 repo,
145 git_object_id(peeled),
146 git_reference_name(ref));
147
148 if (!error) {
149 (*out)->ref_name = git__strdup(git_reference_name(ref));
150 GIT_ERROR_CHECK_ALLOC((*out)->ref_name);
151 }
152
153 git_object_free(peeled);
154 return error;
155 }
156
157 int git_annotated_commit_from_head(
158 git_annotated_commit **out,
159 git_repository *repo)
160 {
161 git_reference *head;
162 int error;
163
164 GIT_ASSERT_ARG(out);
165 GIT_ASSERT_ARG(repo);
166
167 *out = NULL;
168
169 if ((error = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0)
170 return -1;
171
172 error = git_annotated_commit_from_ref(out, repo, head);
173
174 git_reference_free(head);
175 return error;
176 }
177
178 int git_annotated_commit_from_fetchhead(
179 git_annotated_commit **out,
180 git_repository *repo,
181 const char *branch_name,
182 const char *remote_url,
183 const git_oid *id)
184 {
185 GIT_ASSERT_ARG(out);
186 GIT_ASSERT_ARG(repo);
187 GIT_ASSERT_ARG(branch_name);
188 GIT_ASSERT_ARG(remote_url);
189 GIT_ASSERT_ARG(id);
190
191 if (annotated_commit_init_from_id(out, repo, id, branch_name) < 0)
192 return -1;
193
194 (*out)->ref_name = git__strdup(branch_name);
195 GIT_ERROR_CHECK_ALLOC((*out)->ref_name);
196
197 (*out)->remote_url = git__strdup(remote_url);
198 GIT_ERROR_CHECK_ALLOC((*out)->remote_url);
199
200 return 0;
201 }
202
203
204 const git_oid *git_annotated_commit_id(
205 const git_annotated_commit *annotated_commit)
206 {
207 GIT_ASSERT_ARG_WITH_RETVAL(annotated_commit, NULL);
208 return git_commit_id(annotated_commit->commit);
209 }
210
211 const char *git_annotated_commit_ref(
212 const git_annotated_commit *annotated_commit)
213 {
214 GIT_ASSERT_ARG_WITH_RETVAL(annotated_commit, NULL);
215 return annotated_commit->ref_name;
216 }
217
218 void git_annotated_commit_free(git_annotated_commit *annotated_commit)
219 {
220 if (annotated_commit == NULL)
221 return;
222
223 switch (annotated_commit->type) {
224 case GIT_ANNOTATED_COMMIT_REAL:
225 git_commit_free(annotated_commit->commit);
226 git_tree_free(annotated_commit->tree);
227 git__free((char *)annotated_commit->description);
228 git__free((char *)annotated_commit->ref_name);
229 git__free((char *)annotated_commit->remote_url);
230 break;
231 case GIT_ANNOTATED_COMMIT_VIRTUAL:
232 git_index_free(annotated_commit->index);
233 git_array_clear(annotated_commit->parents);
234 break;
235 default:
236 abort();
237 }
238
239 git__free(annotated_commit);
240 }