Skip to content

Commit f094f90

Browse files
arrbeeVicent Marti
authored andcommitted
Add raw header access to commit API
1 parent 8ba0ff6 commit f094f90

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

include/git2/commit.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ GIT_EXTERN(const git_signature *) git_commit_committer(const git_commit *commit)
129129
*/
130130
GIT_EXTERN(const git_signature *) git_commit_author(const git_commit *commit);
131131

132+
/**
133+
* Get the full raw text of the commit header.
134+
*
135+
* @param commit a previously loaded commit
136+
* @return the header text of the commit
137+
*/
138+
GIT_EXTERN(const char *) git_commit_raw_header(const git_commit *commit);
139+
132140
/**
133141
* Get the tree pointed to by a commit.
134142
*

src/commit.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ void git_commit__free(void *_commit)
4141
git_signature_free(commit->author);
4242
git_signature_free(commit->committer);
4343

44+
git__free(commit->raw_header);
4445
git__free(commit->message);
4546
git__free(commit->message_encoding);
4647
git__free(commit);
@@ -171,11 +172,33 @@ int git_commit_create(
171172
int git_commit__parse(void *_commit, git_odb_object *odb_obj)
172173
{
173174
git_commit *commit = _commit;
174-
const char *buffer = git_odb_object_data(odb_obj);
175-
const char *buffer_end = buffer + git_odb_object_size(odb_obj);
175+
const char *buffer_start = git_odb_object_data(odb_obj), *buffer;
176+
const char *buffer_end = buffer_start + git_odb_object_size(odb_obj);
176177
git_oid parent_id;
178+
size_t parent_count = 0, header_len;
177179

178-
if (git_vector_init(&commit->parent_ids, 4, NULL) < 0)
180+
/* find end-of-header (counting parents as we go) */
181+
for (buffer = buffer_start; buffer < buffer_end; ++buffer) {
182+
if (!strncmp("\n\n", buffer, 2)) {
183+
++buffer;
184+
break;
185+
}
186+
if (!strncmp("\nparent ", buffer, strlen("\nparent ")))
187+
++parent_count;
188+
}
189+
190+
header_len = buffer - buffer_start;
191+
commit->raw_header = git__strndup(buffer_start, header_len);
192+
GITERR_CHECK_ALLOC(commit->raw_header);
193+
194+
/* point "buffer" to header data */
195+
buffer = commit->raw_header;
196+
buffer_end = commit->raw_header + header_len;
197+
198+
if (parent_count < 1)
199+
parent_count = 1;
200+
201+
if (git_vector_init(&commit->parent_ids, parent_count, NULL) < 0)
179202
return -1;
180203

181204
if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0)
@@ -208,8 +231,8 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
208231
if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0)
209232
return -1;
210233

211-
/* Parse add'l header entries until blank line found */
212-
while (buffer < buffer_end && *buffer != '\n') {
234+
/* Parse add'l header entries */
235+
while (buffer < buffer_end) {
213236
const char *eoln = buffer;
214237
while (eoln < buffer_end && *eoln != '\n')
215238
++eoln;
@@ -223,15 +246,18 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
223246

224247
if (eoln < buffer_end && *eoln == '\n')
225248
++eoln;
226-
227249
buffer = eoln;
228250
}
229251

230-
/* buffer is now at the end of the header, double-check and move forward into the message */
231-
if (buffer < buffer_end && *buffer == '\n')
232-
buffer++;
252+
/* point "buffer" to data after header */
253+
buffer = git_odb_object_data(odb_obj);
254+
buffer_end = buffer + git_odb_object_size(odb_obj);
255+
256+
buffer += header_len;
257+
if (*buffer == '\n')
258+
++buffer;
233259

234-
/* parse commit message */
260+
/* extract commit message */
235261
if (buffer <= buffer_end) {
236262
commit->message = git__strndup(buffer, buffer_end - buffer);
237263
GITERR_CHECK_ALLOC(commit->message);
@@ -255,6 +281,7 @@ GIT_COMMIT_GETTER(const git_signature *, author, commit->author)
255281
GIT_COMMIT_GETTER(const git_signature *, committer, commit->committer)
256282
GIT_COMMIT_GETTER(const char *, message, commit->message)
257283
GIT_COMMIT_GETTER(const char *, message_encoding, commit->message_encoding)
284+
GIT_COMMIT_GETTER(const char *, raw_header, commit->raw_header)
258285
GIT_COMMIT_GETTER(git_time_t, time, commit->committer->when.time)
259286
GIT_COMMIT_GETTER(int, time_offset, commit->committer->when.offset)
260287
GIT_COMMIT_GETTER(unsigned int, parentcount, (unsigned int)commit->parent_ids.length)

src/commit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct git_commit {
2525

2626
char *message_encoding;
2727
char *message;
28+
char *raw_header;
2829
};
2930

3031
void git_commit__free(void *commit);

0 commit comments

Comments
 (0)