1818#include "message.h"
1919#include "refs.h"
2020#include "object.h"
21+ #include "oidarray.h"
2122
2223void git_commit__free (void * _commit )
2324{
@@ -37,94 +38,143 @@ void git_commit__free(void *_commit)
3738 git__free (commit );
3839}
3940
40- static int git_commit__create_internal (
41- git_oid * id ,
41+ static int git_commit__create_buffer_internal (
42+ git_buf * out ,
4243 git_repository * repo ,
43- const char * update_ref ,
4444 const git_signature * author ,
4545 const git_signature * committer ,
4646 const char * message_encoding ,
4747 const char * message ,
4848 const git_oid * tree ,
49- git_commit_parent_callback parent_cb ,
50- void * parent_payload ,
51- bool validate )
49+ git_array_oid_t * parents )
5250{
53- git_reference * ref = NULL ;
54- int error = 0 , matched_parent = 0 ;
55- const git_oid * current_id = NULL ;
56- git_buf commit = GIT_BUF_INIT ;
5751 size_t i = 0 ;
58- git_odb * odb ;
5952 const git_oid * parent ;
6053
61- assert (id && repo && tree && parent_cb );
54+ assert (out && repo && tree );
6255
63- if (validate && !git_object__is_valid (repo , tree , GIT_OBJ_TREE ))
64- return -1 ;
56+ git_oid__writebuf (out , "tree " , tree );
6557
66- if (update_ref ) {
67- error = git_reference_lookup_resolved (& ref , repo , update_ref , 10 );
68- if (error < 0 && error != GIT_ENOTFOUND )
69- return error ;
58+ for (i = 0 ; i < git_array_size (* parents ); i ++ ) {
59+ parent = git_array_get (* parents , i );
60+ git_oid__writebuf (out , "parent " , parent );
7061 }
71- giterr_clear ();
7262
73- if (ref )
74- current_id = git_reference_target (ref );
63+ git_signature__writebuf (out , "author " , author );
64+ git_signature__writebuf (out , "committer " , committer );
65+
66+ if (message_encoding != NULL )
67+ git_buf_printf (out , "encoding %s\n" , message_encoding );
68+
69+ git_buf_putc (out , '\n' );
7570
76- git_oid__writebuf (& commit , "tree " , tree );
71+ if (git_buf_puts (out , message ) < 0 )
72+ goto on_error ;
73+
74+ return 0 ;
75+
76+ on_error :
77+ git_buf_free (out );
78+ return -1 ;
79+ }
7780
81+ static int validate_tree_and_parents (git_array_oid_t * parents , git_repository * repo , const git_oid * tree ,
82+ git_commit_parent_callback parent_cb , void * parent_payload ,
83+ const git_oid * current_id , bool validate )
84+ {
85+ size_t i ;
86+ int error ;
87+ git_oid * parent_cpy ;
88+ const git_oid * parent ;
89+
90+ if (validate && !git_object__is_valid (repo , tree , GIT_OBJ_TREE ))
91+ return -1 ;
92+
93+ i = 0 ;
7894 while ((parent = parent_cb (i , parent_payload )) != NULL ) {
7995 if (validate && !git_object__is_valid (repo , parent , GIT_OBJ_COMMIT )) {
8096 error = -1 ;
8197 goto on_error ;
8298 }
8399
84- git_oid__writebuf (& commit , "parent " , parent );
85- if (i == 0 && current_id && git_oid_equal (current_id , parent ))
86- matched_parent = 1 ;
100+ parent_cpy = git_array_alloc (* parents );
101+ GITERR_CHECK_ALLOC (parent_cpy );
102+
103+ git_oid_cpy (parent_cpy , parent );
87104 i ++ ;
88105 }
89106
90- if (ref && !matched_parent ) {
91- git_reference_free (ref );
92- git_buf_free (& commit );
107+ if (current_id && git_oid_cmp (current_id , git_array_get (* parents , 0 ))) {
93108 giterr_set (GITERR_OBJECT , "failed to create commit: current tip is not the first parent" );
94- return GIT_EMODIFIED ;
109+ error = GIT_EMODIFIED ;
110+ goto on_error ;
95111 }
96112
97- git_signature__writebuf (& commit , "author " , author );
98- git_signature__writebuf (& commit , "committer " , committer );
113+ return 0 ;
99114
100- if (message_encoding != NULL )
101- git_buf_printf (& commit , "encoding %s\n" , message_encoding );
115+ on_error :
116+ git_array_clear (* parents );
117+ return error ;
118+ }
102119
103- git_buf_putc (& commit , '\n' );
120+ static int git_commit__create_internal (
121+ git_oid * id ,
122+ git_repository * repo ,
123+ const char * update_ref ,
124+ const git_signature * author ,
125+ const git_signature * committer ,
126+ const char * message_encoding ,
127+ const char * message ,
128+ const git_oid * tree ,
129+ git_commit_parent_callback parent_cb ,
130+ void * parent_payload ,
131+ bool validate )
132+ {
133+ int error ;
134+ git_odb * odb ;
135+ git_reference * ref = NULL ;
136+ git_buf buf = GIT_BUF_INIT ;
137+ const git_oid * current_id = NULL ;
138+ git_array_oid_t parents = GIT_ARRAY_INIT ;
104139
105- if (git_buf_puts (& commit , message ) < 0 )
106- goto on_error ;
140+ if (update_ref ) {
141+ error = git_reference_lookup_resolved (& ref , repo , update_ref , 10 );
142+ if (error < 0 && error != GIT_ENOTFOUND )
143+ return error ;
144+ }
145+ giterr_clear ();
146+
147+ if (ref )
148+ current_id = git_reference_target (ref );
149+
150+ if ((error = validate_tree_and_parents (& parents , repo , tree , parent_cb , parent_payload , current_id , validate )) < 0 )
151+ goto cleanup ;
152+
153+ error = git_commit__create_buffer_internal (& buf , repo , author , committer ,
154+ message_encoding , message , tree ,
155+ & parents );
156+
157+ if (error < 0 )
158+ goto cleanup ;
107159
108160 if (git_repository_odb__weakptr (& odb , repo ) < 0 )
109- goto on_error ;
161+ goto cleanup ;
110162
111- if (git_odb_write (id , odb , commit .ptr , commit .size , GIT_OBJ_COMMIT ) < 0 )
112- goto on_error ;
163+ if (git_odb_write (id , odb , buf .ptr , buf .size , GIT_OBJ_COMMIT ) < 0 )
164+ goto cleanup ;
113165
114- git_buf_free (& commit );
115166
116167 if (update_ref != NULL ) {
117168 error = git_reference__update_for_commit (
118169 repo , ref , update_ref , id , "commit" );
119- git_reference_free (ref );
120- return error ;
170+ goto cleanup ;
121171 }
122172
123- return 0 ;
124-
125- on_error :
126- git_buf_free (& commit );
127- return -1 ;
173+ cleanup :
174+ git_array_clear ( parents );
175+ git_reference_free ( ref );
176+ git_buf_free (& buf );
177+ return error ;
128178}
129179
130180int git_commit_create_from_callback (
@@ -739,3 +789,34 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r
739789 git_buf_clear (signed_data );
740790 return error ;
741791}
792+
793+ int git_commit_create_buffer (git_buf * out ,
794+ git_repository * repo ,
795+ const git_signature * author ,
796+ const git_signature * committer ,
797+ const char * message_encoding ,
798+ const char * message ,
799+ const git_tree * tree ,
800+ size_t parent_count ,
801+ const git_commit * parents [])
802+ {
803+ int error ;
804+ commit_parent_data data = { parent_count , parents , repo };
805+ git_array_oid_t parents_arr = GIT_ARRAY_INIT ;
806+ const git_oid * tree_id ;
807+
808+ assert (tree && git_tree_owner (tree ) == repo );
809+
810+ tree_id = git_tree_id (tree );
811+
812+ if ((error = validate_tree_and_parents (& parents_arr , repo , tree_id , commit_parent_from_array , & data , NULL , true)) < 0 )
813+ return error ;
814+
815+ error = git_commit__create_buffer_internal (
816+ out , repo , author , committer ,
817+ message_encoding , message , tree_id ,
818+ & parents_arr );
819+
820+ git_array_clear (parents_arr );
821+ return error ;
822+ }
0 commit comments