18
18
#include "message.h"
19
19
#include "refs.h"
20
20
#include "object.h"
21
+ #include "oidarray.h"
21
22
22
23
void git_commit__free (void * _commit )
23
24
{
@@ -37,94 +38,143 @@ void git_commit__free(void *_commit)
37
38
git__free (commit );
38
39
}
39
40
40
- static int git_commit__create_internal (
41
- git_oid * id ,
41
+ static int git_commit__create_buffer_internal (
42
+ git_buf * out ,
42
43
git_repository * repo ,
43
- const char * update_ref ,
44
44
const git_signature * author ,
45
45
const git_signature * committer ,
46
46
const char * message_encoding ,
47
47
const char * message ,
48
48
const git_oid * tree ,
49
- git_commit_parent_callback parent_cb ,
50
- void * parent_payload ,
51
- bool validate )
49
+ git_array_oid_t * parents )
52
50
{
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 ;
57
51
size_t i = 0 ;
58
- git_odb * odb ;
59
52
const git_oid * parent ;
60
53
61
- assert (id && repo && tree && parent_cb );
54
+ assert (out && repo && tree );
62
55
63
- if (validate && !git_object__is_valid (repo , tree , GIT_OBJ_TREE ))
64
- return -1 ;
56
+ git_oid__writebuf (out , "tree " , tree );
65
57
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 );
70
61
}
71
- giterr_clear ();
72
62
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' );
75
70
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
+ }
77
80
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 ;
78
94
while ((parent = parent_cb (i , parent_payload )) != NULL ) {
79
95
if (validate && !git_object__is_valid (repo , parent , GIT_OBJ_COMMIT )) {
80
96
error = -1 ;
81
97
goto on_error ;
82
98
}
83
99
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 );
87
104
i ++ ;
88
105
}
89
106
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 ))) {
93
108
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 ;
95
111
}
96
112
97
- git_signature__writebuf (& commit , "author " , author );
98
- git_signature__writebuf (& commit , "committer " , committer );
113
+ return 0 ;
99
114
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
+ }
102
119
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 ;
104
139
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 ;
107
159
108
160
if (git_repository_odb__weakptr (& odb , repo ) < 0 )
109
- goto on_error ;
161
+ goto cleanup ;
110
162
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 ;
113
165
114
- git_buf_free (& commit );
115
166
116
167
if (update_ref != NULL ) {
117
168
error = git_reference__update_for_commit (
118
169
repo , ref , update_ref , id , "commit" );
119
- git_reference_free (ref );
120
- return error ;
170
+ goto cleanup ;
121
171
}
122
172
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 ;
128
178
}
129
179
130
180
int git_commit_create_from_callback (
@@ -739,3 +789,34 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r
739
789
git_buf_clear (signed_data );
740
790
return error ;
741
791
}
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