@@ -202,6 +202,100 @@ static int perform_fastforward(git_repository *repo, const git_oid *target_oid,
202202 return 0 ;
203203}
204204
205+ static void output_conflicts (git_index * index )
206+ {
207+ /* Handle conflicts */
208+ git_index_conflict_iterator * conflicts ;
209+ const git_index_entry * ancestor ;
210+ const git_index_entry * our ;
211+ const git_index_entry * their ;
212+ int err = 0 ;
213+
214+ check_lg2 (git_index_conflict_iterator_new (& conflicts , index ), "failed to create conflict iterator" , NULL );
215+
216+ while ((err = git_index_conflict_next (& ancestor , & our , & their , conflicts )) == 0 ) {
217+ fprintf (stderr , "conflict: a:%s o:%s t:%s\n" ,
218+ ancestor ? ancestor -> path : "" , our -> path , their -> path );
219+ }
220+
221+ if (err != GIT_ITEROVER ) {
222+ fprintf (stderr , "error iterating conflicts\n" );
223+ }
224+
225+ git_index_conflict_iterator_free (conflicts );
226+ }
227+
228+ static int create_merge_commit (git_repository * repo , git_index * index , merge_options * opts )
229+ {
230+ git_oid tree_oid , commit_oid ;
231+ git_tree * tree ;
232+ git_signature * sign ;
233+ git_reference * merge_ref = NULL ;
234+ git_annotated_commit * merge_commit ;
235+ git_reference * head_ref ;
236+ git_commit * * parents = calloc (opts -> annotated_count + 1 , sizeof (git_commit * ));
237+ const char * msg_target = NULL ;
238+ size_t msglen = 0 ;
239+ char * msg ;
240+ size_t i ;
241+ int err ;
242+
243+ /* Grab our needed references */
244+ check_lg2 (git_repository_head (& head_ref , repo ), "failed to get repo HEAD" , NULL );
245+ if (resolve_refish (& merge_commit , repo , opts -> heads [0 ])) {
246+ fprintf (stderr , "failed to resolve refish %s" , opts -> heads [0 ]);
247+ }
248+
249+ /* Maybe that's a ref, so DWIM it */
250+ err = git_reference_dwim (& merge_ref , repo , opts -> heads [0 ]);
251+ check_lg2 (err , "failed to DWIM reference" , giterr_last ()-> message );
252+
253+ /* Grab a signature */
254+ check_lg2 (git_signature_now (& sign , "Me" , "me@example.com" ), "failed to create signature" , NULL );
255+
256+ #define MERGE_COMMIT_MSG "Merge %s '%s'"
257+ /* Prepare a standard merge commit message */
258+ if (merge_ref != NULL ) {
259+ check_lg2 (git_branch_name (& msg_target , merge_ref ), "failed to get branch name of merged ref" , NULL );
260+ } else {
261+ msg_target = git_oid_tostr_s (git_annotated_commit_id (merge_commit ));
262+ }
263+
264+ msglen = snprintf (NULL , 0 , MERGE_COMMIT_MSG , (merge_ref ? "branch" : "commit" ), msg_target );
265+ if (msglen > 0 ) msglen ++ ;
266+ msg = malloc (msglen );
267+ err = snprintf (msg , msglen , MERGE_COMMIT_MSG , (merge_ref ? "branch" : "commit" ), msg_target );
268+
269+ /* This is only to silence the compiler */
270+ if (err < 0 ) goto cleanup ;
271+
272+ /* Setup our parent commits */
273+ err = git_reference_peel ((git_object * * )& parents [0 ], head_ref , GIT_OBJ_COMMIT );
274+ check_lg2 (err , "failed to peel head reference" , NULL );
275+ for (i = 0 ; i < opts -> annotated_count ; i ++ ) {
276+ git_commit_lookup (& parents [i + 1 ], repo , git_annotated_commit_id (opts -> annotated [i ]));
277+ }
278+
279+ /* Prepare our commit tree */
280+ check_lg2 (git_index_write_tree (& tree_oid , index ), "failed to write merged tree" , NULL );
281+ check_lg2 (git_tree_lookup (& tree , repo , & tree_oid ), "failed to lookup tree" , NULL );
282+
283+ /* Commit time ! */
284+ err = git_commit_create (& commit_oid ,
285+ repo , git_reference_name (head_ref ),
286+ sign , sign ,
287+ NULL , msg ,
288+ tree ,
289+ opts -> annotated_count + 1 , (const git_commit * * )parents );
290+ check_lg2 (err , "failed to create commit" , NULL );
291+
292+ /* We're done merging, cleanup the repository state */
293+ git_repository_state_cleanup (repo );
294+
295+ cleanup :
296+ return err ;
297+ }
298+
205299int main (int argc , char * * argv )
206300{
207301 git_repository * repo = NULL ;
@@ -280,90 +374,12 @@ int main(int argc, char **argv)
280374 check_lg2 (git_repository_index (& index , repo ), "failed to get repository index" , NULL );
281375
282376 if (git_index_has_conflicts (index )) {
283- /* Handle conflicts */
284- git_index_conflict_iterator * conflicts ;
285- const git_index_entry * ancestor ;
286- const git_index_entry * our ;
287- const git_index_entry * their ;
288-
289- check_lg2 (git_index_conflict_iterator_new (& conflicts , index ), "failed to create conflict iterator" , NULL );
290-
291- while ((err = git_index_conflict_next (& ancestor , & our , & their , conflicts )) == 0 ) {
292- fprintf (stderr , "conflict: a:%s o:%s t:%s\n" ,
293- ancestor ? ancestor -> path : "" , our -> path , their -> path );
294- }
295-
296- if (err != GIT_ITEROVER ) {
297- fprintf (stderr , "error iterating conflicts\n" );
298- }
299-
300- git_index_conflict_iterator_free (conflicts );
377+ output_conflicts (index );
301378 } else if (!opts .no_commit ) {
302- git_oid tree_oid , commit_oid ;
303- git_tree * tree ;
304- git_signature * sign ;
305- git_reference * merge_ref = NULL ;
306- git_annotated_commit * merge_commit ;
307- git_reference * head_ref ;
308- git_commit * * parents = calloc (opts .annotated_count + 1 , sizeof (git_commit * ));
309- const char * msg_target = NULL ;
310- size_t msglen = 0 ;
311- char * msg ;
312- size_t i ;
313- int err ;
314-
315- /* Grab our needed references */
316- check_lg2 (git_repository_head (& head_ref , repo ), "failed to get repo HEAD" , NULL );
317- if (resolve_refish (& merge_commit , repo , opts .heads [0 ])) {
318- fprintf (stderr , "failed to resolve refish %s" , opts .heads [0 ]);
319- }
320-
321- /* Maybe that's a ref, so DWIM it */
322- git_reference_dwim (& merge_ref , repo , opts .heads [0 ]);
323-
324- /* Grab a signature */
325- check_lg2 (git_signature_now (& sign , "Me" , "me@example.com" ), "failed to create signature" , NULL );
326-
327- #define MERGE_COMMIT_MSG "Merge %s '%s'\n"
328- /* Prepare a standard merge commit message */
329- if (merge_ref != NULL ) {
330- check_lg2 (git_branch_name (& msg_target , merge_ref ), "failed to get branch name of merged ref" , NULL );
331- } else {
332- msg_target = git_oid_tostr_s (git_annotated_commit_id (merge_commit ));
333- }
334-
335- msglen = snprintf (NULL , 0 , MERGE_COMMIT_MSG , (merge_ref ? "branch" : "commit" ), msg_target );
336- if (msglen > 0 ) msglen ++ ;
337- msg = malloc (msglen );
338- err = snprintf (msg , msglen , MERGE_COMMIT_MSG , (merge_ref ? "branch" : "commit" ), msg_target );
339-
340- /* This is only to silence the compiler */
341- if (err < 0 ) goto cleanup ;
342-
343- /* Setup our parent commits */
344- check_lg2 (git_reference_peel ((git_object * * )& parents [0 ], head_ref , GIT_OBJ_COMMIT ), "failed to peel head reference" , NULL );
345- for (i = 0 ; i < opts .annotated_count ; i ++ ) {
346- git_commit_lookup (& parents [i + 1 ], repo , git_annotated_commit_id (opts .annotated [i ]));
347- }
348-
349- /* Prepare our commit tree */
350- check_lg2 (git_index_write_tree (& tree_oid , index ), "failed to write merged tree" , NULL );
351- check_lg2 (git_tree_lookup (& tree , repo , & tree_oid ), "failed to lookup tree" , NULL );
352-
353- /* Commit time ! */
354- err = git_commit_create (& commit_oid ,
355- repo , git_reference_name (head_ref ),
356- sign , sign ,
357- NULL , msg ,
358- tree ,
359- opts .annotated_count + 1 , (const git_commit * * )parents );
360- check_lg2 (err , "failed to create commit" , NULL );
361-
362- /* We're done merging, cleanup the repository state */
363- git_repository_state_cleanup (repo );
364-
379+ create_merge_commit (repo , index , & opts );
365380 printf ("Merge made\n" );
366381 }
382+
367383cleanup :
368384 free (opts .heads );
369385 free (opts .annotated );
0 commit comments