libgit-thin: Introduces git_commit_to_str()
[git/libgit-gsoc.git] / libgit-thin / ltrevlist.c
blob96c4ccc91cc09c837641208459810b0441488584
1 /**
2 * @file
3 *
4 * Revision listing functions.
6 * The functions in this file implements revision listing in GIT
7 * repositories.
9 * Luiz Fernando N. Capitulino
10 * <lcapitulino@gmail.com>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <errno.h>
16 #include <cache.h>
17 #include <diff.h>
18 #include <commit.h>
19 #include <revision.h>
21 #include "ltsha1.h"
22 #include "ltcommit.h"
23 #include "ltrevlist.h"
25 struct hex_name {
26 struct hex_name *next;
27 char name[FLEX_ARRAY];
30 /**< Revsion listing options */
31 struct git_revlist_opt {
32 int prepare;
33 struct rev_info info;
34 struct hex_name *hex_head;
35 struct commit_list *list;
38 static void revlist_clear_commit_marks(struct git_revlist_opt *opt)
40 struct commit_list *list;
42 for (list = opt->list; list; list = list->next)
43 clear_commit_marks(list->item, -1);
46 /**
47 * Get the next commit object in the revision listing.
49 * \param opt git_revlist_opt structure which describe the rules
50 * of this revision listing
51 * \param commit git_commit structure to return the commit info
52 * into
54 * \return 1 on success (a commit have been retrieved), 0 on
55 * end-of-commit-list and -1 on error.
57 int git_revlist_next(struct git_revlist_opt *opt, struct git_commit *commit)
59 struct commit *p;
61 if (!opt || !commit) {
62 errno = EINVAL;
63 return -1;
66 if (!opt->prepare) {
67 int err;
69 err = prepare_revision_walk(&opt->info);
70 if (err)
71 return -1;
73 opt->prepare = 1;
76 p = get_revision(&opt->info);
77 if (!p)
78 return 0;
80 if (__git_commit_obj(commit)) {
81 __git_commit_free(commit);
82 __git_commit_init(commit);
85 __git_commit_obj_set(commit, p);
86 return 1;
89 /**
90 * Free all the memory allocated by a git_revlist_opt structure.
92 * \param opt git_revlist_opt structure to be freed
94 void git_revlist_free(struct git_revlist_opt *opt)
96 struct hex_name *p;
98 if (!opt)
99 return;
101 revlist_clear_commit_marks(opt);
102 free_commit_list(opt->list);
104 for (p = opt->hex_head; p;) {
105 struct hex_name *n = p->next;
106 free(p);
107 p = n;
110 free(opt);
114 * Allocate and initialize a git_revlist_opt structure.
116 * Default revision listing options:
118 * - Don't show merges
119 * - Descending chronological order
121 * \return A pointer to an allocated git_revlist_opt structure
122 * on success, NULL otherwise.
124 struct git_revlist_opt *git_revlist_init(void)
126 struct git_revlist_opt *opt;
128 opt = malloc(sizeof(*opt));
129 if (!opt)
130 return NULL;
132 init_revisions(&opt->info, NULL);
134 /* defaults */
135 opt->prepare = 0;
136 opt->info.no_merges = 1;
137 opt->hex_head = NULL;
138 opt->list = NULL;
140 return opt;
143 static int __revlist_add_commit(struct git_revlist_opt *opt,
144 unsigned char *sha1, int exclude)
146 int err;
147 struct hex_name *new;
148 struct commit *commit;
150 if (!opt || !sha1) {
151 errno = EINVAL;
152 return -1;
155 commit = lookup_commit_reference_gently(sha1, 1);
156 if (!commit)
157 return -1;
159 new = malloc(sizeof(*new) + GIT_HEX_LENGTH + 1);
160 if (!new)
161 return -1;
163 err = git_sha1_to_hex(sha1, new->name);
164 if (err) {
165 free(new);
166 return -1;
169 new->next = opt->hex_head;
170 opt->hex_head = new;
172 if (exclude)
173 commit->object.flags |= UNINTERESTING;
175 commit_list_insert(commit, &opt->list);
177 add_pending_object(&opt->info, &commit->object, new->name);
178 return 0;
182 * Include a commit into the revision listing.
184 * Should be called before using git_revlist_next().
186 * \param opt git_revlist_opt structure to include the commit into
187 * \param sha1 commit's 20-byte SHA1 array
189 * \return 0 on success, -1 otherwise.
191 int git_revlist_include(struct git_revlist_opt *opt, unsigned char *sha1)
193 return __revlist_add_commit(opt, sha1, 0);
197 * Exclude a commit into the revision listing.
199 * Should be called before using git_revlist_next().
201 * \param opt git_revlist_opt structure to exclude the commit from
202 * \param sha1 commit's 20-byte SHA1 array
204 * \return 0 on success, -1 otherwise.
206 int git_revlist_exclude(struct git_revlist_opt *opt, unsigned char *sha1)
208 return __revlist_add_commit(opt, sha1, 1);
212 * List commits in reverse order.
214 * By default commits are listed in descending chronological order,
215 * this function changes that behaivor and list commits in ascending
216 * chronological order.
218 * \param opt git_revlist_opt structure to set this option
220 * \return 0 on success, -1 otherwise.
222 int git_revlist_reverse(struct git_revlist_opt *opt)
224 if (!opt) {
225 errno = EINVAL;
226 return -1;
229 opt->info.reverse ^= 1;
230 return 0;
234 * Show merges.
236 * By default merge commits are not shown, this function changes that
237 * behaivor and list merge commits as well.
239 * \param opt git_revlist_opt structure to set this option
241 * \return 0 on success, -1 otherwise.
243 int git_revlist_show_merges(struct git_revlist_opt *opt)
245 if (!opt) {
246 errno = EINVAL;
247 return -1;
250 opt->info.no_merges = 0;
251 return 0;
255 * Specify the number of commits to list.
257 * By default all the reacheable commits will be listed, this
258 * option changes that behaivor and allows the caller to specify
259 * the number of commits to be listed.
261 * \param opt git_revlist_opt structure to set this option
262 * \param count number of commits to be listed
264 * \return 0 on success, -1 otherwise.
266 int git_revlist_max_count(struct git_revlist_opt *opt, size_t count)
268 if (!opt) {
269 errno = EINVAL;
270 return -1;
273 opt->info.max_count = (int) count;
274 return 0;