/* * call-seq: * branches.create(name, target, options = {}) -> branch * * Create a new branch with the given +name+, pointing to the +target+. * * +name+ needs to be a branch name, not an absolute reference path * (e.g. +development+ instead of +refs/heads/development+). * * +target+ needs to be an existing commit in the given repository. * * The following options can be passed in the +options+ Hash: * * :force :: * Overwrites the branch with the given +name+, if it already exists, * instead of raising an exception. * * If a branch with the given +name+ already exists and +:force+ is not +true+, * an exception will be raised. * * Returns a Rugged::Branch for the newly created branch. */ static VALUE rb_git_branch_collection_create(int argc, VALUE *argv, VALUE self) { VALUE rb_repo = rugged_owner(self), rb_name, rb_target, rb_options; git_repository *repo; git_reference *branch; git_commit *target; int error, force = 0; rb_scan_args(argc, argv, "20:", &rb_name, &rb_target, &rb_options); rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); Check_Type(rb_name, T_STRING); Check_Type(rb_target, T_STRING); if (!NIL_P(rb_options)) { force = RTEST(rb_hash_aref(rb_options, CSTR2SYM("force"))); } target = (git_commit *)rugged_object_get(repo, rb_target, GIT_OBJ_COMMIT); error = git_branch_create(&branch, repo, StringValueCStr(rb_name), target, force); git_commit_free(target); rugged_exception_check(error); return rugged_branch_new(rb_repo, branch); }
static VALUE rb_git_commit_tree_SET(VALUE self, VALUE val) { git_commit *commit; git_tree *tree; RUGGED_OBJ_UNWRAP(self, git_commit, commit); tree = (git_tree *)rugged_object_get(git_object_owner((git_object *)commit), val, GIT_OBJ_TREE); git_commit_set_tree(commit, tree); return Qnil; }
static VALUE rb_git_tag_target_SET(VALUE self, VALUE val) { git_tag *tag; git_object *target; RUGGED_OBJ_UNWRAP(self, git_tag, tag); target = rugged_object_get(git_object_owner((git_object *)tag), val, GIT_OBJ_ANY); git_tag_set_target(tag, target); return Qnil; }
/* * call-seq: * tags.create(name, target[, force = false][, annotation = nil]) -> oid * * Create a new tag with the specified +name+ on +target+ in +repo+. * * If +annotation+ is not +nil+, it will cause the creation of an annotated tag object. * +annotation+ has to contain the following key value pairs: * * :tagger :: * An optional Hash containing a git signature. Defaults to the signature * from the configuration if only `:message` is given. Will cause the * creation of an annotated tag object if present. * * :message :: * An optional string containing the message for the new tag. * * Returns the OID of the newly created tag. */ static VALUE rb_git_tag_collection_create(int argc, VALUE *argv, VALUE self) { git_oid tag_oid; git_repository *repo = NULL; git_object *target = NULL; int error, force = 0; VALUE rb_repo = rugged_owner(self), rb_name, rb_target, rb_force, rb_annotation; rb_scan_args(argc, argv, "21:", &rb_name, &rb_target, &rb_force, &rb_annotation); rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); Check_Type(rb_name, T_STRING); if (!NIL_P(rb_force)) force = rugged_parse_bool(rb_force); target = rugged_object_get(repo, rb_target, GIT_OBJ_ANY); if (NIL_P(rb_annotation)) { error = git_tag_create_lightweight( &tag_oid, repo, StringValueCStr(rb_name), target, force ); } else { git_signature *tagger = rugged_signature_get( rb_hash_aref(rb_annotation, CSTR2SYM("tagger")), repo ); VALUE rb_message = rb_hash_aref(rb_annotation, CSTR2SYM("message")); Check_Type(rb_message, T_STRING); error = git_tag_create( &tag_oid, repo, StringValueCStr(rb_name), target, tagger, StringValueCStr(rb_message), force ); git_signature_free(tagger); } git_object_free(target); rugged_exception_check(error); return rb_git_tag_collection_aref(self, rb_name); }
/* * call-seq: * walker.hide(commit) -> nil * * Hide the given +commit+ (and all its parents) from the * output in the revision walk. */ static VALUE rb_git_walker_hide(VALUE self, VALUE rb_commit) { git_revwalk *walk; git_commit *commit; int error; Data_Get_Struct(self, git_revwalk, walk); commit = (git_commit *)rugged_object_get( git_revwalk_repository(walk), rb_commit, GIT_OBJ_COMMIT); error = git_revwalk_hide(walk, git_object_id((git_object *)commit)); git_commit_free(commit); rugged_exception_check(error); return Qnil; }
/* * call-seq: * tags.create_annotation(name, target, annotation) -> annotation * * Create a new annotated tag object with the specified +name+ on +target+ in * +repo+. * * Unlike the +create+ method, +create_annotation+ simply creates a tag * object. It does not write a tag ref. * * +annotation+ must have the following keys: * * :tagger :: * An optional Hash containing a git signature. Defaults to the signature * from the configuration if only `:message` is given. Will cause the * creation of an annotated tag object if present. * * :message :: * An optional string containing the message for the new tag. * * Returns an instance of Rugged::Tag::Annotation representing the newly * created annotation. */ static VALUE rb_git_tag_collection_create_annotation(VALUE self, VALUE rb_name, VALUE rb_target, VALUE rb_annotation) { git_oid tag_oid; git_repository *repo = NULL; git_object *target = NULL, *tag = NULL; git_signature *tagger = NULL; VALUE rb_message; int error; VALUE rb_repo = rugged_owner(self); rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); Check_Type(rb_name, T_STRING); target = rugged_object_get(repo, rb_target, GIT_OBJ_ANY); rb_message = rb_hash_aref(rb_annotation, CSTR2SYM("message")); Check_Type(rb_message, T_STRING); tagger = rugged_signature_get( rb_hash_aref(rb_annotation, CSTR2SYM("tagger")), repo ); error = git_tag_annotation_create( &tag_oid, repo, StringValueCStr(rb_name), target, tagger, StringValueCStr(rb_message) ); git_object_free(target); git_signature_free(tagger); rugged_exception_check(error); error = git_object_lookup(&tag, repo, &tag_oid, GIT_OBJ_TAG); rugged_exception_check(error); return rugged_object_new(rb_repo, tag); }
/* * 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+ (optional): a hash with the signature for the committer, * defaults to the signature from the configuration * - +:author+ (optional): a hash with the signature for the author, * defaults to the signature from the configuration * - +: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=>"*****@*****.**", :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, rb_ref; VALUE rb_err_obj = Qnil; int parent_count, i, error = 0; 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); rugged_check_repo(rb_repo); 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")), repo ); author = rugged_signature_get( rb_hash_aref(rb_data, CSTR2SYM("author")), repo ); rb_parents = rb_hash_aref(rb_data, CSTR2SYM("parents")); Check_Type(rb_parents, T_ARRAY); rb_tree = rb_hash_aref(rb_data, CSTR2SYM("tree")); tree = (git_tree *)rugged_object_get(repo, rb_tree, GIT_OBJ_TREE); parents = alloca(RARRAY_LEN(rb_parents) * sizeof(void *)); free_list = alloca(RARRAY_LEN(rb_parents) * sizeof(void *)); parent_count = 0; 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_OK) goto cleanup; error = git_commit_lookup(&parent, repo, &oid); 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 { rb_err_obj = rb_exc_new2(rb_eTypeError, "Invalid type for parent object"); goto cleanup; } parents[parent_count] = parent; free_list[parent_count] = free_ptr; parent_count++; } error = git_commit_create( &commit_oid, repo, update_ref, author, committer, NULL, StringValueCStr(rb_message), tree, parent_count, parents); cleanup: git_signature_free(author); git_signature_free(committer); git_object_free((git_object *)tree); for (i = 0; i < parent_count; ++i) git_object_free((git_object *)free_list[i]); if (!NIL_P(rb_err_obj)) rb_exc_raise(rb_err_obj); rugged_exception_check(error); return rugged_create_oid(&commit_oid); }
/* * call-seq: * commit.amend(data = {}) -> oid * * Amend a commit object, with the given +data+ * arguments, passed as a +Hash+: * * - +:message+: a string with the full text for the commit's message * - +:committer+ (optional): a hash with the signature for the committer, * defaults to the signature from the configuration * - +:author+ (optional): a hash with the signature for the author, * defaults to the signature from the configuration * - +:tree+: the tree for this amended 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 amended commit (e.g. "HEAD") * * When the amended commit is successfully written to disk, its +oid+ will be * returned as a hex +String+. * * author = {:email=>"*****@*****.**", :time=>Time.now, :name=>"Vicent Mart\303\255"} * * commit.amend( * :author => author, * :message => "Updated Hello world\n\n", * :committer => author, * :tree => some_tree) #=> "f148106ca58764adc93ad4e2d6b1d168422b9796" */ static VALUE rb_git_commit_amend(VALUE self, VALUE rb_data) { VALUE rb_message, rb_tree, rb_ref, owner; int error = 0; git_commit *commit_to_amend; char *message = NULL; git_tree *tree = NULL; git_signature *author = NULL, *committer = NULL; git_oid commit_oid; git_repository *repo; const char *update_ref = NULL; Check_Type(rb_data, T_HASH); Data_Get_Struct(self, git_commit, commit_to_amend); owner = rugged_owner(self); Data_Get_Struct(owner, 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")); if (!NIL_P(rb_message)) { Check_Type(rb_message, T_STRING); message = StringValueCStr(rb_message); } rb_tree = rb_hash_aref(rb_data, CSTR2SYM("tree")); if (!NIL_P(rb_tree)) tree = (git_tree *)rugged_object_get(repo, rb_tree, GIT_OBJ_TREE); if (!NIL_P(rb_hash_aref(rb_data, CSTR2SYM("committer")))) { committer = rugged_signature_get( rb_hash_aref(rb_data, CSTR2SYM("committer")), repo ); } if (!NIL_P(rb_hash_aref(rb_data, CSTR2SYM("author")))) { author = rugged_signature_get( rb_hash_aref(rb_data, CSTR2SYM("author")), repo ); } error = git_commit_amend( &commit_oid, commit_to_amend, update_ref, author, committer, NULL, message, tree); git_signature_free(author); git_signature_free(committer); git_object_free((git_object *)tree); rugged_exception_check(error); return rugged_create_oid(&commit_oid); }
/** * Parse the commit options into something we can re-use * * Note that parents may be set even when the function errors, so make * sure to free this data. */ static VALUE parse_commit_options(struct commit_data *out, git_repository *repo, VALUE rb_data) { VALUE rb_message, rb_tree, rb_parents, rb_ref; int error = 0, parent_count, i; rb_ref = rb_hash_aref(rb_data, CSTR2SYM("update_ref")); if (!NIL_P(rb_ref)) { Check_Type(rb_ref, T_STRING); out->update_ref = StringValueCStr(rb_ref); } rb_message = rb_hash_aref(rb_data, CSTR2SYM("message")); Check_Type(rb_message, T_STRING); out->message = StringValueCStr(rb_message); out->committer = rugged_signature_get( rb_hash_aref(rb_data, CSTR2SYM("committer")), repo ); out->author = rugged_signature_get( rb_hash_aref(rb_data, CSTR2SYM("author")), repo ); rb_parents = rb_hash_aref(rb_data, CSTR2SYM("parents")); Check_Type(rb_parents, T_ARRAY); rb_tree = rb_hash_aref(rb_data, CSTR2SYM("tree")); out->tree = (git_tree *)rugged_object_get(repo, rb_tree, GIT_OBJ_TREE); out->parents = xcalloc(RARRAY_LEN(rb_parents), sizeof(void *)); parent_count = 0; for (i = 0; i < (int)RARRAY_LEN(rb_parents); ++i) { VALUE p = rb_ary_entry(rb_parents, i); git_commit *parent = NULL; git_commit *tmp = NULL; if (NIL_P(p)) continue; if (TYPE(p) == T_STRING) { git_oid oid; error = git_oid_fromstr(&oid, StringValueCStr(p)); if (error < GIT_OK) goto out; error = git_commit_lookup(&parent, repo, &oid); if (error < GIT_OK) goto out; } else if (rb_obj_is_kind_of(p, rb_cRuggedCommit)) { Data_Get_Struct(p, git_commit, tmp); if ((error = git_object_dup((git_object **) &parent, (git_object *) tmp)) < 0) goto out; } else { out->rb_err_obj = rb_exc_new2(rb_eTypeError, "Invalid type for parent object"); error = -1; goto out; } out->parents[parent_count] = parent; parent_count++; } out: out->parent_count = parent_count; return error; }