ext/rugged/rugged_commit.c in rugged-0.16.0 vs ext/rugged/rugged_commit.c in rugged-0.17.0b1
- old
+ new
@@ -1,20 +1,20 @@
/*
* The MIT License
*
* Copyright (c) 2011 GitHub, Inc
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
@@ -31,10 +31,23 @@
VALUE rb_cRuggedCommit;
/*
* Commit code
*/
+/*
+ * call-seq:
+ * commit.message -> msg
+ *
+ * Return the message of this commit. This includes the full body of the
+ * message, with the short description, detailed descritpion, and any
+ * optional footers or signatures after it.
+ *
+ * In Ruby 1.9.X, the returned string will be encoded with the encoding
+ * specified in the +Encoding+ header of the commit, if available.
+ *
+ * commit.message #=> "add a lot of RDoc docs\n\nthis includes docs for commit and blob"
+ */
static VALUE rb_git_commit_message_GET(VALUE self)
{
git_commit *commit;
#ifdef HAVE_RUBY_ENCODING_H
@@ -51,38 +64,88 @@
#endif
return rugged_str_new2(git_commit_message(commit), encoding);
}
+/*
+ * call-seq:
+ * commit.committer -> signature
+ *
+ * Return the signature for the committer of this +commit+. The signature
+ * is returned as a +Hash+ containing +:name+, +:email+ of the author
+ * and +:time+ of the change.
+ *
+ * The committer of a commit is the person who actually applied the changes
+ * of the commit; in most cases it's the same as the author.
+ *
+ * In Ruby 1.9.X, the returned string will be encoded with the encoding
+ * specified in the +Encoding+ header of the commit, if available.
+ *
+ * commit.committer #=> {:email=>"tanoku@gmail.com", :time=>Tue Jan 24 05:42:45 UTC 2012, :name=>"Vicent Mart\303\255"}
+ */
static VALUE rb_git_commit_committer_GET(VALUE self)
{
git_commit *commit;
Data_Get_Struct(self, git_commit, commit);
return rugged_signature_new(
git_commit_committer(commit),
git_commit_message_encoding(commit));
}
+/*
+ * call-seq:
+ * commit.author -> signature
+ *
+ * Return the signature for the author of this +commit+. The signature
+ * is returned as a +Hash+ containing +:name+, +:email+ of the author
+ * and +:time+ of the change.
+ *
+ * The author of the commit is the person who intially created the changes.
+ *
+ * In Ruby 1.9.X, the returned string will be encoded with the encoding
+ * specified in the +Encoding+ header of the commit, if available.
+ *
+ * commit.author #=> {:email=>"tanoku@gmail.com", :time=>Tue Jan 24 05:42:45 UTC 2012, :name=>"Vicent Mart\303\255"}
+ */
static VALUE rb_git_commit_author_GET(VALUE self)
{
git_commit *commit;
Data_Get_Struct(self, git_commit, commit);
return rugged_signature_new(
git_commit_author(commit),
git_commit_message_encoding(commit));
}
-static VALUE rb_git_commit_time_GET(VALUE self)
+/*
+ * call-seq:
+ * commit.epoch_time -> t
+ *
+ * Return the time when this commit was made effective. This is the same value
+ * as the +:time+ attribute for +commit.committer+, but represented as an +Integer+
+ * value in seconds since the Epoch.
+ *
+ * commit.time #=> 1327383765
+ */
+static VALUE rb_git_commit_epoch_time_GET(VALUE self)
{
git_commit *commit;
Data_Get_Struct(self, git_commit, commit);
return ULONG2NUM(git_commit_time(commit));
}
+/*
+ * call-seq:
+ * commit.tree -> tree
+ *
+ * Return the tree pointed at by this +commit+. The tree is
+ * returned as a +Rugged::Tree+ object.
+ *
+ * commit.tree #=> #<Rugged::Tree:0x10882c680>
+ */
static VALUE rb_git_commit_tree_GET(VALUE self)
{
git_commit *commit;
git_tree *tree;
VALUE owner;
@@ -95,10 +158,43 @@
rugged_exception_check(error);
return rugged_object_new(owner, (git_object *)tree);
}
+/*
+ * call-seq:
+ * commit.tree_oid -> oid
+ *
+ * Return the tree oid pointed at by this +commit+. The tree is
+ * returned as a String object.
+ *
+ * commit.tree #=> "f148106ca58764adc93ad4e2d6b1d168422b9796"
+ */
+static VALUE rb_git_commit_tree_oid_GET(VALUE self)
+{
+ git_commit *commit;
+ const git_oid *tree_oid;
+ int error;
+
+ Data_Get_Struct(self, git_commit, commit);
+
+ tree_oid = git_commit_tree_oid(commit);
+
+ return rugged_create_oid(tree_oid);
+}
+
+/*
+ * call-seq:
+ * commit.parents -> [commit, ...]
+ *
+ * Return the parent(s) of this commit as an array of +Rugged::Commit+
+ * objects. An array is always returned even when the commit has only
+ * one or zero parents.
+ *
+ * commit.parents #=> => [#<Rugged::Commit:0x108828918>]
+ * root.parents #=> []
+ */
static VALUE rb_git_commit_parents_GET(VALUE self)
{
git_commit *commit;
git_commit *parent;
unsigned int n, parent_count;
@@ -118,26 +214,97 @@
}
return ret_arr;
}
+/*
+ * call-seq:
+ * commit.parent_oids -> [oid, ...]
+ *
+ * Return the parent oid(s) of this commit as an array of oid String
+ * objects. An array is always returned even when the commit has only
+ * one or zero parents.
+ *
+ * commit.parent_oids #=> => ["2cb831a8aea28b2c1b9c63385585b864e4d3bad1", ...]
+ * root.parent_oids #=> []
+ */
+static VALUE rb_git_commit_parent_oids_GET(VALUE self)
+{
+ git_commit *commit;
+ const git_oid *parent_oid;
+ unsigned int n, parent_count;
+ VALUE ret_arr;
+ int error;
+
+ Data_Get_Struct(self, git_commit, commit);
+
+ parent_count = git_commit_parentcount(commit);
+ ret_arr = rb_ary_new2((long)parent_count);
+
+ for (n = 0; n < parent_count; n++) {
+ parent_oid = git_commit_parent_oid(commit, n);
+ if (parent_oid) {
+ rb_ary_push(ret_arr, rugged_create_oid(parent_oid));
+ }
+ }
+
+ return ret_arr;
+}
+
+/*
+ * call-seq:
+ * Commit.create(repository, data = {}) -> oid
+ *
+ * Write a new +Commit+ object to +repository+, with the given +data+
+ * arguments, passed as a +Hash+:
+ *
+ * - +:message+: a string with the full text for the commit's message
+ * - +:committer+: a hash with the signature for the committer
+ * - +:author+: a hash with the signature for the author
+ * - +:parents+: an +Array+ with zero or more parents for this commit,
+ * represented as <tt>Rugged::Commit</tt> instances, or OID +String+.
+ * - +:tree+: the tree for this commit, represented as a <tt>Rugged::Tree</tt>
+ * instance or an OID +String+.
+ * - +:update_ref+ (optional): a +String+ with the name of a reference in the
+ * repository which should be updated to point to this commit (e.g. "HEAD")
+ *
+ * When the commit is successfully written to disk, its +oid+ will be
+ * returned as a hex +String+.
+ *
+ * author = {:email=>"tanoku@gmail.com", :time=>Time.now, :name=>"Vicent Mart\303\255"}
+ *
+ * Rugged::Commit.create(r,
+ * :author => author,
+ * :message => "Hello world\n\n",
+ * :committer => author,
+ * :parents => ["2cb831a8aea28b2c1b9c63385585b864e4d3bad1"],
+ * :tree => some_tree) #=> "f148106ca58764adc93ad4e2d6b1d168422b9796"
+ */
static VALUE rb_git_commit_create(VALUE self, VALUE rb_repo, VALUE rb_data)
{
- VALUE rb_message, rb_tree, rb_parents;
+ VALUE rb_message, rb_tree, rb_parents, rb_ref;
int parent_count, i, error;
- const git_commit **parents;
+ const git_commit **parents = NULL;
+ git_commit **free_list = NULL;
git_tree *tree;
git_signature *author, *committer;
git_oid commit_oid;
git_repository *repo;
+ const char *update_ref = NULL;
Check_Type(rb_data, T_HASH);
if (!rb_obj_is_kind_of(rb_repo, rb_cRuggedRepo))
rb_raise(rb_eTypeError, "Expeting a Rugged::Repository instance");
Data_Get_Struct(rb_repo, git_repository, repo);
+ rb_ref = rb_hash_aref(rb_data, CSTR2SYM("update_ref"));
+ if (!NIL_P(rb_ref)) {
+ Check_Type(rb_ref, T_STRING);
+ update_ref = StringValueCStr(rb_ref);
+ }
+
rb_message = rb_hash_aref(rb_data, CSTR2SYM("message"));
Check_Type(rb_message, T_STRING);
committer = rugged_signature_get(
rb_hash_aref(rb_data, CSTR2SYM("committer"))
@@ -151,42 +318,50 @@
Check_Type(rb_parents, T_ARRAY);
rb_tree = rb_hash_aref(rb_data, CSTR2SYM("tree"));
tree = (git_tree *)rugged_object_load(repo, rb_tree, GIT_OBJ_TREE);
- parent_count = (int)RARRAY_LEN(rb_parents);
- parents = malloc(parent_count * sizeof(void*));
+ parents = xmalloc(RARRAY_LEN(rb_parents) * sizeof(void *));
+ free_list = xmalloc(RARRAY_LEN(rb_parents) * sizeof(void *));
+ parent_count = 0;
- for (i = 0; i < parent_count; ++i) {
+ for (i = 0; i < (int)RARRAY_LEN(rb_parents); ++i) {
VALUE p = rb_ary_entry(rb_parents, i);
git_commit *parent = NULL;
+ git_commit *free_ptr = NULL;
+ if (NIL_P(p))
+ continue;
+
if (TYPE(p) == T_STRING) {
git_oid oid;
error = git_oid_fromstr(&oid, StringValueCStr(p));
- if (error < GIT_SUCCESS)
+ if (error < GIT_OK)
goto cleanup;
error = git_commit_lookup(&parent, repo, &oid);
- if (error < GIT_SUCCESS)
+ if (error < GIT_OK)
goto cleanup;
+ free_ptr = parent;
+
} else if (rb_obj_is_kind_of(p, rb_cRuggedCommit)) {
Data_Get_Struct(p, git_commit, parent);
} else {
- error = GIT_EINVALIDTYPE;
- goto cleanup;
+ rb_raise(rb_eTypeError, "Invalid type for parent object");
}
- parents[i] = parent;
+ parents[parent_count] = parent;
+ free_list[parent_count] = free_ptr;
+ parent_count++;
}
error = git_commit_create(
&commit_oid,
repo,
- NULL,
+ update_ref,
author,
committer,
NULL,
StringValueCStr(rb_message),
tree,
@@ -198,13 +373,14 @@
git_signature_free(committer);
git_object_free((git_object *)tree);
for (i = 0; i < parent_count; ++i)
- git_object_free((git_object *)parents[i]);
+ git_object_free((git_object *)free_list[i]);
- free(parents);
+ xfree(parents);
+ xfree(free_list);
rugged_exception_check(error);
return rugged_create_oid(&commit_oid);
}
@@ -213,12 +389,14 @@
rb_cRuggedCommit = rb_define_class_under(rb_mRugged, "Commit", rb_cRuggedObject);
rb_define_singleton_method(rb_cRuggedCommit, "create", rb_git_commit_create, 2);
rb_define_method(rb_cRuggedCommit, "message", rb_git_commit_message_GET, 0);
- rb_define_method(rb_cRuggedCommit, "time", rb_git_commit_time_GET, 0);
+ rb_define_method(rb_cRuggedCommit, "epoch_time", rb_git_commit_epoch_time_GET, 0);
rb_define_method(rb_cRuggedCommit, "committer", rb_git_commit_committer_GET, 0);
rb_define_method(rb_cRuggedCommit, "author", rb_git_commit_author_GET, 0);
rb_define_method(rb_cRuggedCommit, "tree", rb_git_commit_tree_GET, 0);
+ rb_define_method(rb_cRuggedCommit, "tree_oid", rb_git_commit_tree_oid_GET, 0);
rb_define_method(rb_cRuggedCommit, "parents", rb_git_commit_parents_GET, 0);
+ rb_define_method(rb_cRuggedCommit, "parent_oids", rb_git_commit_parent_oids_GET, 0);
}