2 * This file is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2,
4 * as published by the Free Software Foundation.
6 * In addition to the permissions in the GNU General Public License,
7 * the authors give you unlimited permission to link the compiled
8 * version of this file into combinations with other programs,
9 * and to distribute those combinations without any restriction
10 * coming from the use of this file. (The General Public License
11 * restrictions do apply in other respects; for example, they cover
12 * modification of the file, and distribution when not linked into
13 * a combined executable.)
15 * This file is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; see the file COPYING. If not, write to
22 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
33 const git_oid
*git_commit_id(git_commit
*c
)
38 void git_commit__mark_uninteresting(git_commit
*commit
)
43 git_commit_node
*parents
= commit
->parents
.head
;
45 commit
->uninteresting
= 1;
49 parents
->commit
->uninteresting
= 1;
50 parents
= parents
->next
;
54 git_commit
*git_commit_parse(git_revpool
*pool
, const git_oid
*id
)
56 git_commit
*commit
= NULL
;
58 if ((commit
= git_commit_lookup(pool
, id
)) == NULL
)
61 if (git_commit_parse_existing(commit
) < 0)
71 int git_commit_parse_existing(git_commit
*commit
)
78 if (git_odb_read(&commit_obj
, commit
->object
.pool
->db
, &commit
->object
.id
) < 0)
81 if (commit_obj
.type
!= GIT_OBJ_COMMIT
)
84 if (git_commit__parse_buffer(commit
, commit_obj
.data
, commit_obj
.len
) < 0)
87 git_obj_close(&commit_obj
);
92 git_obj_close(&commit_obj
);
96 git_commit
*git_commit_lookup(git_revpool
*pool
, const git_oid
*id
)
98 git_commit
*commit
= NULL
;
100 if (pool
== NULL
|| pool
->db
== NULL
)
103 commit
= git__malloc(sizeof(git_commit
));
108 memset(commit
, 0x0, sizeof(git_commit
));
110 // Initialize parent object
111 git_oid_cpy(&commit
->object
.id
, id
);
112 commit
->object
.pool
= pool
;
117 int git_commit__parse_time(time_t *commit_time
, char *buffer
, const char *buffer_end
)
119 if (memcmp(buffer
, "author ", 7) != 0)
122 buffer
= memchr(buffer
, '\n', buffer_end
- buffer
);
123 if (buffer
== 0 || buffer
>= buffer_end
)
126 if (memcmp(buffer
, "committer ", 10) != 0)
129 buffer
= memchr(buffer
, '\n', buffer_end
- buffer
);
130 if (buffer
== 0 || buffer
>= buffer_end
)
133 *commit_time
= strtol(buffer
, &buffer
, 10);
135 return (buffer
< buffer_end
) ? 0 : -1;
138 int git_commit__parse_oid(git_oid
*oid
, char **buffer_out
, const char *buffer_end
, const char *header
)
140 const size_t sha_len
= GIT_OID_HEXSZ
;
141 const size_t header_len
= strlen(header
);
143 char *buffer
= *buffer_out
;
145 if (buffer
+ (header_len
+ sha_len
+ 1) > buffer_end
)
148 if (memcmp(buffer
, header
, header_len
) != 0)
151 if (buffer
[header_len
+ sha_len
] != '\n')
154 if (git_oid_mkstr(oid
, buffer
+ header_len
) < 0)
157 *buffer_out
= buffer
+ (header_len
+ sha_len
+ 1);
162 int git_commit__parse_buffer(git_commit
*commit
, void *data
, size_t len
)
164 char *buffer
= (char *)data
;
165 const char *buffer_end
= (char *)data
+ len
;
172 if (git_commit__parse_oid(&oid
, &buffer
, buffer_end
, "tree ") < 0)
176 * TODO: load tree into commit object
177 * TODO: commit grafts!
180 while (git_commit__parse_oid(&oid
, &buffer
, buffer_end
, "parent ") == 0) {
183 if ((parent
= git_commit_lookup(commit
->object
.pool
, &oid
)) == NULL
)
186 // Inherit uninteresting flag
187 if (commit
->uninteresting
)
188 parent
->uninteresting
= 1;
190 git_commit_list_append(&commit
->parents
, parent
);
193 if (git_commit__parse_time(&commit
->commit_time
, buffer
, buffer_end
) < 0)
201 void git_commit_list_append(git_commit_list
*list
, git_commit
*commit
)
203 git_commit_node
*node
= NULL
;
205 node
= git__malloc(sizeof(git_commit_list
));
210 node
->commit
= commit
;
212 node
->prev
= list
->tail
;
214 if (list
->tail
== NULL
)
216 list
->head
= list
->tail
= node
;
220 list
->tail
->next
= node
;
227 git_commit
*git_commit_list_pop_back(git_commit_list
*list
)
229 git_commit_node
*node
;
232 if (list
->tail
== NULL
)
236 list
->tail
= list
->tail
->prev
;
237 if (list
->tail
== NULL
)
240 commit
= node
->commit
;
248 git_commit
*git_commit_list_pop_front(git_commit_list
*list
)
250 git_commit_node
*node
;
253 if (list
->head
== NULL
)
257 list
->head
= list
->head
->next
;
258 if (list
->head
== NULL
)
261 commit
= node
->commit
;
269 void git_commit_list_clear(git_commit_list
*list
, int free_commits
)
271 git_commit_node
*node
, *next_node
;
279 next_node
= node
->next
;
284 list
->head
= list
->tail
= NULL
;