@@ -338,86 +338,60 @@ static VALUE rb_git_commit_amend(VALUE self, VALUE rb_data)
338
338
return rugged_create_oid (& commit_oid );
339
339
}
340
340
341
- /*
342
- * call-seq:
343
- * Commit.create(repository, data = {}) -> oid
344
- *
345
- * Write a new +Commit+ object to +repository+, with the given +data+
346
- * arguments, passed as a +Hash+:
347
- *
348
- * - +:message+: a string with the full text for the commit's message
349
- * - +:committer+ (optional): a hash with the signature for the committer,
350
- * defaults to the signature from the configuration
351
- * - +:author+ (optional): a hash with the signature for the author,
352
- * defaults to the signature from the configuration
353
- * - +:parents+: an +Array+ with zero or more parents for this commit,
354
- * represented as <tt>Rugged::Commit</tt> instances, or OID +String+.
355
- * - +:tree+: the tree for this commit, represented as a <tt>Rugged::Tree</tt>
356
- * instance or an OID +String+.
357
- * - +:update_ref+ (optional): a +String+ with the name of a reference in the
358
- * repository which should be updated to point to this commit (e.g. "HEAD")
359
- *
360
- * When the commit is successfully written to disk, its +oid+ will be
361
- * returned as a hex +String+.
362
- *
363
- * author = {:email=>"[email protected] ", :time=>Time.now, :name=>"Vicent Mart\303\255"}
341
+ struct commit_data {
342
+ VALUE rb_err_obj ;
343
+
344
+ const char * update_ref ;
345
+ const char * message ;
346
+ git_tree * tree ;
347
+ git_signature * author ;
348
+ git_signature * committer ;
349
+ int parent_count ;
350
+ const git_commit * * parents ;
351
+ };
352
+
353
+ /**
354
+ * Parse the commit options into something we can re-use
364
355
*
365
- * Rugged::Commit.create(r,
366
- * :author => author,
367
- * :message => "Hello world\n\n",
368
- * :committer => author,
369
- * :parents => ["2cb831a8aea28b2c1b9c63385585b864e4d3bad1"],
370
- * :tree => some_tree) #=> "f148106ca58764adc93ad4e2d6b1d168422b9796"
356
+ * Note that parents may be set even when the function errors, so make
357
+ * sure to free this data.
371
358
*/
372
- static VALUE rb_git_commit_create ( VALUE self , VALUE rb_repo , VALUE rb_data )
359
+ static VALUE parse_commit_options ( struct commit_data * out , git_repository * repo , VALUE rb_data )
373
360
{
374
361
VALUE rb_message , rb_tree , rb_parents , rb_ref ;
375
- VALUE rb_err_obj = Qnil ;
376
- int parent_count , i , error = 0 ;
377
- const git_commit * * parents = NULL ;
378
- git_commit * * free_list = NULL ;
379
- git_tree * tree ;
380
- git_signature * author , * committer ;
381
- git_oid commit_oid ;
382
- git_repository * repo ;
383
- const char * update_ref = NULL ;
384
-
385
- Check_Type (rb_data , T_HASH );
386
-
387
- rugged_check_repo (rb_repo );
388
- Data_Get_Struct (rb_repo , git_repository , repo );
362
+ int error = 0 , parent_count , i ;
389
363
390
364
rb_ref = rb_hash_aref (rb_data , CSTR2SYM ("update_ref" ));
391
365
if (!NIL_P (rb_ref )) {
392
366
Check_Type (rb_ref , T_STRING );
393
- update_ref = StringValueCStr (rb_ref );
367
+ out -> update_ref = StringValueCStr (rb_ref );
394
368
}
395
369
396
370
rb_message = rb_hash_aref (rb_data , CSTR2SYM ("message" ));
397
371
Check_Type (rb_message , T_STRING );
372
+ out -> message = StringValueCStr (rb_message );
398
373
399
- committer = rugged_signature_get (
374
+ out -> committer = rugged_signature_get (
400
375
rb_hash_aref (rb_data , CSTR2SYM ("committer" )), repo
401
376
);
402
377
403
- author = rugged_signature_get (
378
+ out -> author = rugged_signature_get (
404
379
rb_hash_aref (rb_data , CSTR2SYM ("author" )), repo
405
380
);
406
381
407
382
rb_parents = rb_hash_aref (rb_data , CSTR2SYM ("parents" ));
408
383
Check_Type (rb_parents , T_ARRAY );
409
384
410
385
rb_tree = rb_hash_aref (rb_data , CSTR2SYM ("tree" ));
411
- tree = (git_tree * )rugged_object_get (repo , rb_tree , GIT_OBJ_TREE );
386
+ out -> tree = (git_tree * )rugged_object_get (repo , rb_tree , GIT_OBJ_TREE );
412
387
413
- parents = alloca (RARRAY_LEN (rb_parents ) * sizeof (void * ));
414
- free_list = alloca (RARRAY_LEN (rb_parents ) * sizeof (void * ));
388
+ out -> parents = xcalloc (RARRAY_LEN (rb_parents ), sizeof (void * ));
415
389
parent_count = 0 ;
416
390
417
391
for (i = 0 ; i < (int )RARRAY_LEN (rb_parents ); ++ i ) {
418
392
VALUE p = rb_ary_entry (rb_parents , i );
419
393
git_commit * parent = NULL ;
420
- git_commit * free_ptr = NULL ;
394
+ git_commit * tmp = NULL ;
421
395
422
396
if (NIL_P (p ))
423
397
continue ;
@@ -427,49 +401,106 @@ static VALUE rb_git_commit_create(VALUE self, VALUE rb_repo, VALUE rb_data)
427
401
428
402
error = git_oid_fromstr (& oid , StringValueCStr (p ));
429
403
if (error < GIT_OK )
430
- goto cleanup ;
404
+ goto out ;
431
405
432
406
error = git_commit_lookup (& parent , repo , & oid );
433
407
if (error < GIT_OK )
434
- goto cleanup ;
435
-
436
- free_ptr = parent ;
437
-
408
+ goto out ;
438
409
} else if (rb_obj_is_kind_of (p , rb_cRuggedCommit )) {
439
- Data_Get_Struct (p , git_commit , parent );
410
+ Data_Get_Struct (p , git_commit , tmp );
411
+ if ((error = git_object_dup ((git_object * * ) & parent , (git_object * ) tmp )) < 0 )
412
+ goto out ;
440
413
} else {
441
- rb_err_obj = rb_exc_new2 (rb_eTypeError , "Invalid type for parent object" );
442
- goto cleanup ;
414
+ out -> rb_err_obj = rb_exc_new2 (rb_eTypeError , "Invalid type for parent object" );
415
+ error = -1 ;
416
+ goto out ;
443
417
}
444
418
445
- parents [parent_count ] = parent ;
446
- free_list [parent_count ] = free_ptr ;
419
+ out -> parents [parent_count ] = parent ;
447
420
parent_count ++ ;
448
421
}
449
422
423
+ out :
424
+ out -> parent_count = parent_count ;
425
+ return error ;
426
+ }
427
+
428
+ static void free_commit_options (struct commit_data * commit_data )
429
+ {
430
+ int i ;
431
+
432
+ git_signature_free (commit_data -> author );
433
+ git_signature_free (commit_data -> committer );
434
+
435
+ git_object_free ((git_object * )commit_data -> tree );
436
+
437
+ for (i = 0 ; i < commit_data -> parent_count ; ++ i )
438
+ git_object_free ((git_object * ) commit_data -> parents [i ]);
439
+ xfree (commit_data -> parents );
440
+ }
441
+
442
+ /*
443
+ * call-seq:
444
+ * Commit.create(repository, data = {}) -> oid
445
+ *
446
+ * Write a new +Commit+ object to +repository+, with the given +data+
447
+ * arguments, passed as a +Hash+:
448
+ *
449
+ * - +:message+: a string with the full text for the commit's message
450
+ * - +:committer+ (optional): a hash with the signature for the committer,
451
+ * defaults to the signature from the configuration
452
+ * - +:author+ (optional): a hash with the signature for the author,
453
+ * defaults to the signature from the configuration
454
+ * - +:parents+: an +Array+ with zero or more parents for this commit,
455
+ * represented as <tt>Rugged::Commit</tt> instances, or OID +String+.
456
+ * - +:tree+: the tree for this commit, represented as a <tt>Rugged::Tree</tt>
457
+ * instance or an OID +String+.
458
+ * - +:update_ref+ (optional): a +String+ with the name of a reference in the
459
+ * repository which should be updated to point to this commit (e.g. "HEAD")
460
+ *
461
+ * When the commit is successfully written to disk, its +oid+ will be
462
+ * returned as a hex +String+.
463
+ *
464
+ * author = {:email=>"[email protected] ", :time=>Time.now, :name=>"Vicent Mart\303\255"}
465
+ *
466
+ * Rugged::Commit.create(r,
467
+ * :author => author,
468
+ * :message => "Hello world\n\n",
469
+ * :committer => author,
470
+ * :parents => ["2cb831a8aea28b2c1b9c63385585b864e4d3bad1"],
471
+ * :tree => some_tree) #=> "f148106ca58764adc93ad4e2d6b1d168422b9796"
472
+ */
473
+ static VALUE rb_git_commit_create (VALUE self , VALUE rb_repo , VALUE rb_data )
474
+ {
475
+ int error = 0 ;
476
+ struct commit_data commit_data = { Qnil };
477
+ git_oid commit_oid ;
478
+ git_repository * repo ;
479
+
480
+ Check_Type (rb_data , T_HASH );
481
+
482
+ rugged_check_repo (rb_repo );
483
+ Data_Get_Struct (rb_repo , git_repository , repo );
484
+
485
+ if ((error = parse_commit_options (& commit_data , repo , rb_data )) < 0 )
486
+ goto cleanup ;
487
+
450
488
error = git_commit_create (
451
489
& commit_oid ,
452
490
repo ,
453
- update_ref ,
454
- author ,
455
- committer ,
491
+ commit_data . update_ref ,
492
+ commit_data . author ,
493
+ commit_data . committer ,
456
494
NULL ,
457
- StringValueCStr ( rb_message ) ,
458
- tree ,
459
- parent_count ,
460
- parents );
495
+ commit_data . message ,
496
+ commit_data . tree ,
497
+ commit_data . parent_count ,
498
+ commit_data . parents );
461
499
462
500
cleanup :
463
- git_signature_free (author );
464
- git_signature_free (committer );
465
-
466
- git_object_free ((git_object * )tree );
467
-
468
- for (i = 0 ; i < parent_count ; ++ i )
469
- git_object_free ((git_object * )free_list [i ]);
470
-
471
- if (!NIL_P (rb_err_obj ))
472
- rb_exc_raise (rb_err_obj );
501
+ free_commit_options (& commit_data );
502
+ if (!NIL_P (commit_data .rb_err_obj ))
503
+ rb_exc_raise (commit_data .rb_err_obj );
473
504
474
505
rugged_exception_check (error );
475
506
0 commit comments