Add unit tests for Commit parsing
[libgit2.git] / src / commit.c
blob1b30c5d6f15d06aaf5e4edc55d33d440890416fc
1 /*
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.
26 #include <time.h>
28 #include "common.h"
29 #include "commit.h"
30 #include "revwalk.h"
31 #include "git/odb.h"
33 const git_oid *git_commit_id(git_commit *c)
35 return &c->id;
38 git_commit *git_commit_lookup(git_revpool *pool, const git_oid *id)
40 git_obj commit_obj;
41 git_commit *commit = NULL;
43 if (pool == NULL || pool->db == NULL)
44 return NULL;
47 * TODO: check if the commit is already cached in the
48 * revpool instead of loading it from the odb
51 if (git_odb_read(&commit_obj, pool->db, id) < 0)
52 return NULL;
54 if (commit_obj.type != GIT_OBJ_COMMIT)
55 goto error_cleanup;
57 commit = git__malloc(sizeof(git_commit));
58 memset(commit, 0x0, sizeof(git_commit));
60 git_oid_cpy(&commit->id, id);
61 commit->pool = pool;
63 if (git_commit__parse_buffer(commit, commit_obj.data, commit_obj.len) < 0)
64 goto error_cleanup;
66 return commit;
68 error_cleanup:
69 git_obj_close(&commit_obj);
70 free(commit);
72 return NULL;
75 int git_commit__parse_time(time_t *commit_time, char *buffer, const char *buffer_end)
77 if (memcmp(buffer, "author ", 7) != 0)
78 return -1;
80 buffer = memchr(buffer, '\n', buffer_end - buffer);
81 if (buffer == 0 || buffer >= buffer_end)
82 return -1;
84 if (memcmp(buffer, "committer ", 10) != 0)
85 return -1;
87 buffer = memchr(buffer, '\n', buffer_end - buffer);
88 if (buffer == 0 || buffer >= buffer_end)
89 return -1;
91 *commit_time = strtol(buffer, &buffer, 10);
93 return (buffer < buffer_end) ? 0 : -1;
96 int git_commit__parse_oid(git_oid *oid, char **buffer_out, const char *buffer_end, const char *header)
98 size_t sha_len = GIT_OID_HEXSZ;
99 size_t header_len = strlen(header);
101 char *buffer = *buffer_out;
103 if (buffer + (header_len + sha_len + 1) > buffer_end)
104 return -1;
106 if (memcmp(buffer, header, header_len) != 0)
107 return -1;
109 if (buffer[header_len + sha_len] != '\n')
110 return -1;
112 if (git_oid_mkstr(oid, buffer + header_len) < 0)
113 return -1;
115 *buffer_out = buffer + (header_len + sha_len + 1);
117 return 0;
120 int git_commit__parse_buffer(git_commit *commit, void *data, size_t len)
122 char *buffer = (char *)data;
123 const char *buffer_end = (char *)data + len;
125 git_oid oid;
127 if (commit->parsed)
128 return 0;
130 if (git_commit__parse_oid(&oid, &buffer, buffer_end, "tree ") < 0)
131 return -1;
134 * TODO: load tree into commit object
135 * TODO: commit grafts!
138 while (git_commit__parse_oid(&oid, &buffer, buffer_end, "parent ") == 0) {
139 git_commit *parent;
141 if ((parent = git_commit_lookup(commit->pool, &oid)) == NULL)
142 return -1;
144 // TODO: push the new commit into the revpool
147 if (git_commit__parse_time(&commit->commit_time, buffer, buffer_end) < 0)
148 return -1;
150 commit->parsed = 1;
152 return 0;