@@ -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(
171172int 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)
255281GIT_COMMIT_GETTER (const git_signature * , committer , commit -> committer )
256282GIT_COMMIT_GETTER (const char * , message , commit - > message )
257283GIT_COMMIT_GETTER (const char * , message_encoding , commit - > message_encoding )
284+ GIT_COMMIT_GETTER (const char * , raw_header , commit - > raw_header )
258285GIT_COMMIT_GETTER (git_time_t , time , commit - > committer - > when .time )
259286GIT_COMMIT_GETTER (int , time_offset , commit - > committer - > when .offset )
260287GIT_COMMIT_GETTER (unsigned int , parentcount , (unsigned int )commit -> parent_ids .length )
0 commit comments