1010#include "revwalk.h"
1111#include "pool.h"
1212#include "odb.h"
13+ #include "commit.h"
1314
1415int git_commit_list_time_cmp (const void * a , const void * b )
1516{
@@ -55,17 +56,6 @@ git_commit_list_node *git_commit_list_alloc_node(git_revwalk *walk)
5556 return (git_commit_list_node * )git_pool_mallocz (& walk -> commit_pool , 1 );
5657}
5758
58- static int commit_error (git_commit_list_node * commit , const char * msg )
59- {
60- char commit_oid [GIT_OID_HEXSZ + 1 ];
61- git_oid_fmt (commit_oid , & commit -> oid );
62- commit_oid [GIT_OID_HEXSZ ] = '\0' ;
63-
64- git_error_set (GIT_ERROR_ODB , "failed to parse commit %s - %s" , commit_oid , msg );
65-
66- return -1 ;
67- }
68-
6959static git_commit_list_node * * alloc_parents (
7060 git_revwalk * walk , git_commit_list_node * commit , size_t n_parents )
7161{
@@ -111,77 +101,42 @@ git_commit_list_node *git_commit_list_pop(git_commit_list **stack)
111101
112102static int commit_quick_parse (
113103 git_revwalk * walk ,
114- git_commit_list_node * commit ,
115- const uint8_t * buffer ,
116- size_t buffer_len )
104+ git_commit_list_node * node ,
105+ git_odb_object * obj )
117106{
118- const size_t parent_len = strlen ("parent " ) + GIT_OID_HEXSZ + 1 ;
119- const uint8_t * buffer_end = buffer + buffer_len ;
120- const uint8_t * parents_start , * committer_start ;
121- int i , parents = 0 ;
122- int64_t commit_time ;
123-
124- buffer += strlen ("tree " ) + GIT_OID_HEXSZ + 1 ;
125-
126- parents_start = buffer ;
127- while (buffer + parent_len < buffer_end && memcmp (buffer , "parent " , strlen ("parent " )) == 0 ) {
128- parents ++ ;
129- buffer += parent_len ;
130- }
131-
132- commit -> parents = alloc_parents (walk , commit , parents );
133- GIT_ERROR_CHECK_ALLOC (commit -> parents );
134-
135- buffer = parents_start ;
136- for (i = 0 ; i < parents ; ++ i ) {
137- git_oid oid ;
138-
139- if (git_oid_fromstr (& oid , (const char * )buffer + strlen ("parent " )) < 0 )
140- return -1 ;
107+ git_oid * parent_oid ;
108+ git_commit * commit ;
109+ int error ;
110+ size_t i ;
141111
142- commit -> parents [ i ] = git_revwalk__commit_lookup ( walk , & oid );
143- if (commit -> parents [ i ] == NULL )
144- return -1 ;
112+ commit = git__calloc ( 1 , sizeof ( * commit ) );
113+ GIT_ERROR_CHECK_ALLOC (commit );
114+ commit -> object . repo = walk -> repo ;
145115
146- buffer += parent_len ;
116+ if ((error = git_commit__parse_ext (commit , obj , GIT_COMMIT_PARSE_QUICK )) < 0 ) {
117+ git__free (commit );
118+ return error ;
147119 }
148120
149- commit -> out_degree = (unsigned short )parents ;
150-
151- if ((committer_start = buffer = memchr (buffer , '\n' , buffer_end - buffer )) == NULL )
152- return commit_error (commit , "object is corrupted" );
153-
154- buffer ++ ;
155-
156- if ((buffer = memchr (buffer , '\n' , buffer_end - buffer )) == NULL )
157- return commit_error (commit , "object is corrupted" );
158-
159- /* Skip trailing spaces */
160- while (buffer > committer_start && git__isspace (* buffer ))
161- buffer -- ;
162-
163- /* Seek for the beginning of the pack of digits */
164- while (buffer > committer_start && git__isdigit (* buffer ))
165- buffer -- ;
166-
167- /* Skip potential timezone offset */
168- if ((buffer > committer_start ) && (* buffer == '+' || * buffer == '-' )) {
169- buffer -- ;
121+ if (!git__is_uint16 (git_array_size (commit -> parent_ids ))) {
122+ git__free (commit );
123+ git_error_set (GIT_ERROR_INVALID , "commit has more than 2^16 parents" );
124+ return -1 ;
125+ }
170126
171- while (buffer > committer_start && git__isspace (* buffer ))
172- buffer -- ;
127+ node -> time = commit -> committer -> when .time ;
128+ node -> out_degree = (uint16_t ) git_array_size (commit -> parent_ids );
129+ node -> parents = alloc_parents (walk , node , node -> out_degree );
130+ GIT_ERROR_CHECK_ALLOC (node -> parents );
173131
174- while ( buffer > committer_start && git__isdigit ( * buffer ))
175- buffer -- ;
132+ git_array_foreach ( commit -> parent_ids , i , parent_oid ) {
133+ node -> parents [ i ] = git_revwalk__commit_lookup ( walk , parent_oid ) ;
176134 }
177135
178- if ((buffer == committer_start ) ||
179- (git__strntol64 (& commit_time , (char * )(buffer + 1 ),
180- buffer_end - buffer + 1 , NULL , 10 ) < 0 ))
181- return commit_error (commit , "cannot parse commit time" );
136+ git_commit__free (commit );
137+
138+ node -> parsed = 1 ;
182139
183- commit -> time = commit_time ;
184- commit -> parsed = 1 ;
185140 return 0 ;
186141}
187142
@@ -200,10 +155,7 @@ int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit)
200155 git_error_set (GIT_ERROR_INVALID , "object is no commit object" );
201156 error = -1 ;
202157 } else
203- error = commit_quick_parse (
204- walk , commit ,
205- (const uint8_t * )git_odb_object_data (obj ),
206- git_odb_object_size (obj ));
158+ error = commit_quick_parse (walk , commit , obj );
207159
208160 git_odb_object_free (obj );
209161 return error ;
0 commit comments