File Coverage

deps/libgit2/src/commit_list.c
Criterion Covered Total %
statement 66 77 85.7
branch 28 40 70.0
condition n/a
subroutine n/a
pod n/a
total 94 117 80.3


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