]>
Commit | Line | Data |
---|---|---|
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 | 15 | int 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 | ||
28 | git_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 | ||
39 | git_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 | ||
54 | git_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 |
59 | static 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 | ||
74 | void 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 | ||
90 | git_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 |
102 | static 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 | ||
143 | int 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 |