]> git.proxmox.com Git - libgit2.git/blame - src/commit_list.c
install as examples
[libgit2.git] / src / commit_list.c
CommitLineData
4ff192d3 1/*
359fc2d2 2 * Copyright (C) the libgit2 contributors. All rights reserved.
4ff192d3
BS
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 "commit_list.h"
eae0bfdc 9
4ff192d3
BS
10#include "revwalk.h"
11#include "pool.h"
12#include "odb.h"
0c9c969a 13#include "commit.h"
4ff192d3 14
4075e060 15int git_commit_list_time_cmp(const void *a, const void *b)
4ff192d3 16{
5e2a29a7
CMN
17 int64_t time_a = ((git_commit_list_node *) a)->time;
18 int64_t time_b = ((git_commit_list_node *) b)->time;
4ff192d3 19
5e2a29a7
CMN
20 if (time_a < time_b)
21 return 1;
22 if (time_a > time_b)
23 return -1;
24
25 return 0;
4ff192d3
BS
26}
27
28git_commit_list *git_commit_list_insert(git_commit_list_node *item, git_commit_list **list_p)
29{
30 git_commit_list *new_list = git__malloc(sizeof(git_commit_list));
31 if (new_list != NULL) {
32 new_list->item = item;
33 new_list->next = *list_p;
34 }
35 *list_p = new_list;
36 return new_list;
37}
38
39git_commit_list *git_commit_list_insert_by_date(git_commit_list_node *item, git_commit_list **list_p)
40{
41 git_commit_list **pp = list_p;
42 git_commit_list *p;
43
44 while ((p = *pp) != NULL) {
3736b64f 45 if (git_commit_list_time_cmp(p->item, item) > 0)
4ff192d3
BS
46 break;
47
48 pp = &p->next;
49 }
50
51 return git_commit_list_insert(item, pp);
52}
53
54git_commit_list_node *git_commit_list_alloc_node(git_revwalk *walk)
55{
d3416dfe 56 return (git_commit_list_node *)git_pool_mallocz(&walk->commit_pool, 1);
4ff192d3
BS
57}
58
4ff192d3
BS
59static git_commit_list_node **alloc_parents(
60 git_revwalk *walk, git_commit_list_node *commit, size_t n_parents)
61{
6147f643
PP
62 size_t bytes;
63
4ff192d3
BS
64 if (n_parents <= PARENTS_PER_COMMIT)
65 return (git_commit_list_node **)((char *)commit + sizeof(git_commit_list_node));
66
6147f643
PP
67 if (git__multiply_sizet_overflow(&bytes, n_parents, sizeof(git_commit_list_node *)))
68 return NULL;
69
70 return (git_commit_list_node **)git_pool_malloc(&walk->commit_pool, bytes);
4ff192d3
BS
71}
72
73
74void git_commit_list_free(git_commit_list **list_p)
75{
76 git_commit_list *list = *list_p;
77
78 if (list == NULL)
79 return;
80
81 while (list) {
82 git_commit_list *temp = list;
83 list = temp->next;
84 git__free(temp);
85 }
86
87 *list_p = NULL;
88}
89
90git_commit_list_node *git_commit_list_pop(git_commit_list **stack)
91{
92 git_commit_list *top = *stack;
93 git_commit_list_node *item = top ? top->item : NULL;
94
95 if (top) {
96 *stack = top->next;
97 git__free(top);
98 }
99 return item;
100}
101
8842c75f
VM
102static int commit_quick_parse(
103 git_revwalk *walk,
0c9c969a
UG
104 git_commit_list_node *node,
105 git_odb_object *obj)
4ff192d3 106{
0c9c969a
UG
107 git_oid *parent_oid;
108 git_commit *commit;
109 int error;
110 size_t i;
4ff192d3 111
0c9c969a
UG
112 commit = git__calloc(1, sizeof(*commit));
113 GIT_ERROR_CHECK_ALLOC(commit);
114 commit->object.repo = walk->repo;
4ff192d3 115
0c9c969a
UG
116 if ((error = git_commit__parse_ext(commit, obj, GIT_COMMIT_PARSE_QUICK)) < 0) {
117 git__free(commit);
118 return error;
4ff192d3
BS
119 }
120
0c9c969a
UG
121 if (!git__is_uint16(git_array_size(commit->parent_ids))) {
122 git__free(commit);
123 git_error_set(GIT_ERROR_INVALID, "commit has more than 2^16 parents");
124 return -1;
125 }
4ff192d3 126
0c9c969a
UG
127 node->time = commit->committer->when.time;
128 node->out_degree = (uint16_t) git_array_size(commit->parent_ids);
129 node->parents = alloc_parents(walk, node, node->out_degree);
130 GIT_ERROR_CHECK_ALLOC(node->parents);
4ff192d3 131
0c9c969a
UG
132 git_array_foreach(commit->parent_ids, i, parent_oid) {
133 node->parents[i] = git_revwalk__commit_lookup(walk, parent_oid);
4ff192d3
BS
134 }
135
0c9c969a
UG
136 git_commit__free(commit);
137
138 node->parsed = 1;
4ff192d3 139
4ff192d3
BS
140 return 0;
141}
142
143int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit)
144{
145 git_odb_object *obj;
146 int error;
147
148 if (commit->parsed)
149 return 0;
150
151 if ((error = git_odb_read(&obj, walk->odb, &commit->oid)) < 0)
152 return error;
4ff192d3 153
ac3d33df
JK
154 if (obj->cached.type != GIT_OBJECT_COMMIT) {
155 git_error_set(GIT_ERROR_INVALID, "object is no commit object");
d5e44d84
RB
156 error = -1;
157 } else
0c9c969a 158 error = commit_quick_parse(walk, commit, obj);
d5e44d84 159
4ff192d3
BS
160 git_odb_object_free(obj);
161 return error;
162}
163