summaryrefslogtreecommitdiff
path: root/src/commit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/commit.c')
-rw-r--r--src/commit.c92
1 files changed, 23 insertions, 69 deletions
diff --git a/src/commit.c b/src/commit.c
index 227d5c4a5..1388cb3f5 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -328,87 +328,41 @@ int git_commit_amend(
return error;
}
-int git_commit__parse(void *_commit, git_odb_object *odb_obj)
+int git_commit__parse(void *obj, git_odb_object *odb_obj)
{
- git_commit *commit = _commit;
- const char *buffer_start = git_odb_object_data(odb_obj), *buffer;
- const char *buffer_end = buffer_start + git_odb_object_size(odb_obj);
- git_oid parent_id;
- size_t header_len;
-
- buffer = buffer_start;
+ int error = 0;
+ const char *start = git_odb_object_data(odb_obj);
+ const char *end = start + git_odb_object_size(odb_obj);
+ const char *body = NULL;
+ git_commit *commit = obj;
+ git_object_parse_t parser[] = {
+ { "tree", 4, GIT_PARSE_OID, { .id = &commit->tree_id } },
+ { "parent", 6, GIT_PARSE_OID_ARRAY, { .ids = &commit->parent_ids } },
+ { "author", 6, GIT_PARSE_SIGNATURE, { .sig = &commit->author } },
+ { "committer", 9, GIT_PARSE_SIGNATURE, { .sig = &commit->committer } },
+ { NULL, 0, GIT_PARSE_MODE_OPTIONAL },
+ { "encoding", 8, GIT_PARSE_TO_EOL, { .text = &commit->message_encoding } },
+ { NULL, 0, GIT_PARSE_BODY, { .body = &body } },
+ };
/* Allocate for one, which will allow not to realloc 90% of the time */
git_array_init_to_size(commit->parent_ids, 1);
GITERR_CHECK_ARRAY(commit->parent_ids);
- /* The tree is always the first field */
- if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0)
- goto bad_buffer;
-
- /*
- * TODO: commit grafts!
- */
-
- while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) {
- git_oid *new_id = git_array_alloc(commit->parent_ids);
- GITERR_CHECK_ALLOC(new_id);
-
- git_oid_cpy(new_id, &parent_id);
- }
-
- commit->author = git__malloc(sizeof(git_signature));
- GITERR_CHECK_ALLOC(commit->author);
-
- if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0)
- return -1;
-
- /* Always parse the committer; we need the commit time */
- commit->committer = git__malloc(sizeof(git_signature));
- GITERR_CHECK_ALLOC(commit->committer);
-
- if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0)
- return -1;
-
- /* Parse add'l header entries */
- while (buffer < buffer_end) {
- const char *eoln = buffer;
- if (buffer[-1] == '\n' && buffer[0] == '\n')
- break;
-
- while (eoln < buffer_end && *eoln != '\n')
- ++eoln;
+ error = git_object__parse_lines(GIT_OBJ_COMMIT, parser, start, end);
- if (git__prefixcmp(buffer, "encoding ") == 0) {
- buffer += strlen("encoding ");
-
- commit->message_encoding = git__strndup(buffer, eoln - buffer);
- GITERR_CHECK_ALLOC(commit->message_encoding);
+ /* strdup raw version of header data and commit message */
+ if (body != NULL) {
+ if (body > start) {
+ commit->raw_header = git__strndup(start, (body - 1) - start);
+ GITERR_CHECK_ALLOC(commit->raw_header);
}
- if (eoln < buffer_end && *eoln == '\n')
- ++eoln;
- buffer = eoln;
- }
-
- header_len = buffer - buffer_start;
- commit->raw_header = git__strndup(buffer_start, header_len);
- GITERR_CHECK_ALLOC(commit->raw_header);
-
- /* point "buffer" to data after header, +1 for the final LF */
- buffer = buffer_start + header_len + 1;
-
- /* extract commit message */
- if (buffer <= buffer_end) {
- commit->raw_message = git__strndup(buffer, buffer_end - buffer);
+ commit->raw_message = git__strndup(body, end - body);
GITERR_CHECK_ALLOC(commit->raw_message);
}
- return 0;
-
-bad_buffer:
- giterr_set(GITERR_OBJECT, "Failed to parse bad commit object");
- return -1;
+ return error;
}
#define GIT_COMMIT_GETTER(_rvalue, _name, _return) \