commit: generic parse mechanism This allows us to pick which data from a commit we're interested in. This will be used by the revwalk code, which is only interested in parents' and committer data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
diff --git a/src/commit.c b/src/commit.c
index 513fdcc..483bded 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -20,6 +20,7 @@
#include "message.h"
#include "refs.h"
#include "object.h"
+#include "array.h"
#include "oidarray.h"
void git_commit__free(void *_commit)
@@ -383,15 +384,16 @@ int git_commit_amend(
return error;
}
-int git_commit__parse_raw(void *_commit, const char *data, size_t size)
+static int commit_parse(git_commit *commit, const char *data, size_t size, unsigned int flags)
{
- git_commit *commit = _commit;
const char *buffer_start = data, *buffer;
const char *buffer_end = buffer_start + size;
git_oid parent_id;
size_t header_len;
git_signature dummy_sig;
+ assert(commit && data);
+
buffer = buffer_start;
/* Allocate for one, which will allow not to realloc 90% of the time */
@@ -399,8 +401,15 @@ int git_commit__parse_raw(void *_commit, const char *data, size_t size)
GIT_ERROR_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;
+ if (!(flags & GIT_COMMIT_PARSE_QUICK)) {
+ if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0)
+ goto bad_buffer;
+ } else {
+ size_t tree_len = strlen("tree ") + GIT_OID_HEXSZ + 1;
+ if (buffer + tree_len > buffer_end)
+ goto bad_buffer;
+ buffer += tree_len;
+ }
/*
* TODO: commit grafts!
@@ -413,11 +422,13 @@ int git_commit__parse_raw(void *_commit, const char *data, size_t size)
git_oid_cpy(new_id, &parent_id);
}
- commit->author = git__malloc(sizeof(git_signature));
- GIT_ERROR_CHECK_ALLOC(commit->author);
+ if (!(flags & GIT_COMMIT_PARSE_QUICK)) {
+ commit->author = git__malloc(sizeof(git_signature));
+ GIT_ERROR_CHECK_ALLOC(commit->author);
- if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0)
- return -1;
+ if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0)
+ return -1;
+ }
/* Some tools create multiple author fields, ignore the extra ones */
while (!git__prefixncmp(buffer, buffer_end - buffer, "author ")) {
@@ -435,6 +446,9 @@ int git_commit__parse_raw(void *_commit, const char *data, size_t size)
if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0)
return -1;
+ if (flags & GIT_COMMIT_PARSE_QUICK)
+ return 0;
+
/* Parse add'l header entries */
while (buffer < buffer_end) {
const char *eoln = buffer;
@@ -477,11 +491,19 @@ bad_buffer:
return -1;
}
+int git_commit__parse_raw(void *commit, const char *data, size_t size)
+{
+ return commit_parse(commit, data, size, 0);
+}
+
+int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags)
+{
+ return commit_parse(commit, git_odb_object_data(odb_obj), git_odb_object_size(odb_obj), flags);
+}
+
int git_commit__parse(void *_commit, git_odb_object *odb_obj)
{
- return git_commit__parse_raw(_commit,
- git_odb_object_data(odb_obj),
- git_odb_object_size(odb_obj));
+ return git_commit__parse_ext(_commit, odb_obj, 0);
}
#define GIT_COMMIT_GETTER(_rvalue, _name, _return) \
diff --git a/src/commit.h b/src/commit.h
index 9137a8f..318ce5c 100644
--- a/src/commit.h
+++ b/src/commit.h
@@ -37,4 +37,10 @@ void git_commit__free(void *commit);
int git_commit__parse(void *commit, git_odb_object *obj);
int git_commit__parse_raw(void *commit, const char *data, size_t size);
+typedef enum {
+ GIT_COMMIT_PARSE_QUICK = (1 << 0), /**< Only parse parents and committer info */
+} git_commit__parse_flags;
+
+int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags);
+
#endif