/* * call-seq: * index.read_tree(tree) * * Clear the current index and start the index again on top of +tree+ * * Further index operations (+add+, +update+, +remove+, etc) will * be considered changes on top of +tree+. */ static VALUE rb_git_index_readtree(VALUE self, VALUE rb_tree) { git_index *index; git_tree *tree; int error; Data_Get_Struct(self, git_index, index); Data_Get_Struct(rb_tree, git_tree, tree); if (!rb_obj_is_kind_of(rb_tree, rb_cRuggedTree)) { rb_raise(rb_eTypeError, "A Rugged::Tree instance is required"); } error = git_index_read_tree(index, tree); rugged_exception_check(error); return Qnil; }
/* * call-seq: * Index.new([path]) * * Create a bare index object based on the index file at +path+. * * Any index methods that rely on the ODB or a working directory (e.g. #add) * will raise a Rugged::IndexError. */ static VALUE rb_git_index_new(int argc, VALUE *argv, VALUE klass) { git_index *index; int error; VALUE rb_path; const char *path = NULL; if (rb_scan_args(argc, argv, "01", &rb_path) == 1) { Check_Type(rb_path, T_STRING); path = StringValueCStr(rb_path); } error = git_index_open(&index, path); rugged_exception_check(error); return rugged_index_new(klass, Qnil, index); }
/* * call-seq: * remote.push_url = url -> url * * Sets the remote's url for pushing without persisting it in the config. * Existing connections will not be updated. * * remote.push_url = '[email protected]/libgit2/rugged.git' #=> "[email protected]/libgit2/rugged.git" */ static VALUE rb_git_remote_set_push_url(VALUE self, VALUE rb_url) { VALUE rb_repo = rugged_owner(self); git_remote *remote; git_repository *repo; rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); Check_Type(rb_url, T_STRING); Data_Get_Struct(self, git_remote, remote); rugged_exception_check( git_remote_set_pushurl(repo, git_remote_name(remote), StringValueCStr(rb_url)) ); return rb_url; }
static VALUE each_tag(int argc, VALUE *argv, VALUE self, int tag_names_only) { git_repository *repo; git_strarray tags; size_t i; int error, exception = 0; VALUE rb_repo = rugged_owner(self), rb_pattern; const char *pattern = NULL; rb_scan_args(argc, argv, "01", &rb_pattern); if (!rb_block_given_p()) { VALUE symbol = tag_names_only ? CSTR2SYM("each_name") : CSTR2SYM("each"); return rb_funcall(self, rb_intern("to_enum"), 2, symbol, rb_pattern); } if (!NIL_P(rb_pattern)) { Check_Type(rb_pattern, T_STRING); pattern = StringValueCStr(rb_pattern); } rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); error = git_tag_list_match(&tags, pattern ? pattern : "", repo); rugged_exception_check(error); if (tag_names_only) { for (i = 0; !exception && i < tags.count; ++i) rb_protect(rb_yield, rb_str_new_utf8(tags.strings[i]), &exception); } else { for (i = 0; !exception && i < tags.count; ++i) { rb_protect(rb_yield, rb_git_tag_collection_aref(self, rb_str_new_utf8(tags.strings[i])), &exception); } } git_strarray_free(&tags); if (exception) rb_jump_tag(exception); return Qnil; }
/* * call-seq: * rebase.commit(author: nil, committer: committer, message: nil) -> oid or nil * * Commit the current patch. Any conflicts must have been resolved. * * If +author+ is +nil+, the existing author for the commit will be * used. If +message+ is +nil+, the existing message will be used. * * Returns a string containing the oid of the newly created commit, * or +nil+ if there are no changes to be committed. */ static VALUE rb_git_rebase_commit(int argc, VALUE *argv, VALUE self) { int error; git_oid id; git_rebase *rebase; git_signature *author = NULL, *committer; const char *message = NULL; VALUE rb_options, rb_author, rb_committer, rb_message; Data_Get_Struct(self, git_rebase, rebase); rb_scan_args(argc, argv, ":", &rb_options); Check_Type(rb_options, T_HASH); rb_author = rb_hash_aref(rb_options, CSTR2SYM("author")); rb_committer = rb_hash_aref(rb_options, CSTR2SYM("committer")); rb_message = rb_hash_aref(rb_options, CSTR2SYM("message")); if (!NIL_P(rb_message)) { Check_Type(rb_message, T_STRING); message = StringValueCStr(rb_message); } if (NIL_P(rb_committer)) rb_raise(rb_eArgError, "Expected non-nil committer"); else committer = rugged_signature_get(rb_committer, NULL); if (!NIL_P(rb_author)) author = rugged_signature_get(rb_author, NULL); error = git_rebase_commit(&id, rebase, author, committer, NULL, message); git_signature_free(author); git_signature_free(committer); if (error == GIT_EAPPLIED) { giterr_clear(); return Qnil; } rugged_exception_check(error); return rugged_create_oid(&id); }
/* * call-seq: * branch.upstream -> branch * * Returns the remote tracking branch, or +nil+ if the branch is * remote or has no tracking branch. */ static VALUE rb_git_branch_upstream(VALUE self) { git_reference *branch, *upstream_branch; int error; Data_Get_Struct(self, git_reference, branch); if (git_reference_is_remote(branch)) return Qnil; error = git_branch_upstream(&upstream_branch, branch); if (error == GIT_ENOTFOUND) return Qnil; rugged_exception_check(error); return rugged_branch_new(rugged_owner(self), upstream_branch); }
/* * call-seq: * commit.header_field(field_name) -> str * * Returns +commit+'s header field value. */ static VALUE rb_git_commit_header_field(VALUE self, VALUE rb_field) { git_buf header_field = { 0 }; VALUE rb_result; git_commit *commit; Check_Type(rb_field, T_STRING); Data_Get_Struct(self, git_commit, commit); rugged_exception_check( git_commit_header_field(&header_field, commit, StringValueCStr(rb_field)) ); rb_result = rb_enc_str_new(header_field.ptr, header_field.size, rb_utf8_encoding()); git_buf_free(&header_field); return rb_result; }
/* * call-seq: * remote.ls(options = {}) -> an_enumerator * remote.ls(options = {}) { |remote_head_hash| block } * * Connects +remote+ to list all references available along with their * associated commit ids. * * The given block is called once for each remote head with a Hash containing the * following keys: * * :local? :: * +true+ if the remote head is available locally, +false+ otherwise. * * :oid :: * The id of the object the remote head is currently pointing to. * * :loid :: * The id of the object the local copy of the remote head is currently * pointing to. Set to +nil+ if there is no local copy of the remote head. * * :name :: * The fully qualified reference name of the remote head. * * If no block is given, an enumerator will be returned. * * The following options can be passed in the +options+ Hash: * * :credentials :: * The credentials to use for the ls operation. Can be either an instance of one * of the Rugged::Credentials types, or a proc returning one of the former. * The proc will be called with the +url+, the +username+ from the url (if applicable) and * a list of applicable credential types. * * :headers :: * Extra HTTP headers to include with the request (only applies to http:// or https:// remotes) */ static VALUE rb_git_remote_ls(int argc, VALUE *argv, VALUE self) { git_remote *remote; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; git_strarray custom_headers = {0}; const git_remote_head **heads; struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, 0 }; VALUE rb_options; int error; size_t heads_len, i; Data_Get_Struct(self, git_remote, remote); rb_scan_args(argc, argv, ":", &rb_options); if (!rb_block_given_p()) return rb_funcall(self, rb_intern("to_enum"), 2, CSTR2SYM("ls"), rb_options); rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload); init_custom_headers(rb_options, &custom_headers); if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH, &callbacks, NULL, &custom_headers)) || (error = git_remote_ls(&heads, &heads_len, remote))) goto cleanup; for (i = 0; i < heads_len && !payload.exception; i++) rb_protect(rb_yield, rugged_rhead_new(heads[i]), &payload.exception); cleanup: git_remote_disconnect(remote); git_strarray_free(&custom_headers); if (payload.exception) rb_jump_tag(payload.exception); rugged_exception_check(error); return Qnil; }
/* * call-seq: * branches[name] -> branch * * Return the branch with the given +name+. * * Branches can be looked up by their relative (+development+) or absolute * (+refs/heads/development+) branch name. * * If a local branch and a remote branch both share the same short name * (e.g. +refs/heads/origin/master+ and +refs/remotes/origin/master+), * passing +origin/master+ as the +name+ will return the local branch. * You can explicitly request the local branch by passing * +heads/origin/master+, or the remote branch through +remotes/origin/master+. * * Returns the looked up branch, or +nil+ if the branch doesn't exist. */ static VALUE rb_git_branch_collection_aref(VALUE self, VALUE rb_name) { git_reference *branch; git_repository *repo; VALUE rb_repo = rugged_owner(self); int error; rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); Check_Type(rb_name, T_STRING); error = rugged_branch_lookup(&branch, repo, rb_name); if (error == GIT_ENOTFOUND) return Qnil; rugged_exception_check(error); return rugged_branch_new(rb_repo, branch); }
/* * call-seq: * Remote.lookup(repository, name) -> remote or nil * * Return an existing remote with +name+ in +repository+: * - +name+: a valid remote name * * Returns a new Rugged::Remote object or +nil+ if the * remote doesn't exist * * Rugged::Remote.lookup(@repo, 'origin') #=> #<Rugged::Remote:0x00000001fbfa80> */ static VALUE rb_git_remote_lookup(VALUE klass, VALUE rb_repo, VALUE rb_name) { git_remote *remote; git_repository *repo; int error; Check_Type(rb_name, T_STRING); rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); error = git_remote_load(&remote, repo, StringValueCStr(rb_name)); if (error == GIT_ENOTFOUND) return Qnil; rugged_exception_check(error); return rugged_remote_new(klass, rb_repo, remote); }
/* * call-seq: * branches.exist?(name) -> true or false * branches.exists?(name) -> true or false * * Check if a branch exists with the given +name+. */ static VALUE rb_git_branch_collection_exist_p(VALUE self, VALUE rb_name) { VALUE rb_repo = rugged_owner(self); git_repository *repo; git_reference *branch; int error; Check_Type(rb_name, T_STRING); Data_Get_Struct(rb_repo, git_repository, repo); error = rugged_branch_lookup(&branch, repo, rb_name); git_reference_free(branch); if (error == GIT_ENOTFOUND) return Qfalse; else rugged_exception_check(error); return Qtrue; }
/* * call-seq: * remotes.delete(remote) -> nil * remotes.delete(name) -> nil * * Delete the specified remote. * * repo.remotes.delete("origin") * # Remote no longer exists in the configuration. */ static VALUE rb_git_remote_collection_delete(VALUE self, VALUE rb_name_or_remote) { VALUE rb_repo = rugged_owner(self); git_repository *repo; int error; if (rb_obj_is_kind_of(rb_name_or_remote, rb_cRuggedRemote)) rb_name_or_remote = rb_funcall(rb_name_or_remote, rb_intern("name"), 0); if (TYPE(rb_name_or_remote) != T_STRING) rb_raise(rb_eTypeError, "Expecting a String or Rugged::Remote instance"); rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); error = git_remote_delete(repo, StringValueCStr(rb_name_or_remote)); rugged_exception_check(error); return Qnil; }
/* * call-seq: * Rugged.prettify_message(message, strip_comments) -> clean_message * * Process a commit or tag message into standard form, by stripping trailing spaces and * comments, and making sure that the message has a proper header line. */ static VALUE rb_git_prettify_message(VALUE self, VALUE rb_message, VALUE rb_strip_comments) { char *message; int strip_comments, message_len; VALUE result; Check_Type(rb_message, T_STRING); strip_comments = rugged_parse_bool(rb_strip_comments); message_len = (int)RSTRING_LEN(rb_message) + 2; message = xmalloc(message_len); message_len = git_message_prettify(message, message_len, StringValueCStr(rb_message), strip_comments); rugged_exception_check(message_len); result = rb_enc_str_new(message, message_len - 1, rb_utf8_encoding()); xfree(message); return result; }
static VALUE rb_git_remote_refspecs(VALUE self, git_direction direction) { git_remote *remote; int error = 0; git_strarray refspecs; VALUE rb_refspec_array; Data_Get_Struct(self, git_remote, remote); if (direction == GIT_DIRECTION_FETCH) error = git_remote_get_fetch_refspecs(&refspecs, remote); else error = git_remote_get_push_refspecs(&refspecs, remote); rugged_exception_check(error); rb_refspec_array = rugged_strarray_to_rb_ary(&refspecs); git_strarray_free(&refspecs); return rb_refspec_array; }
static VALUE rb_git_treebuilder_init(int argc, VALUE *argv, VALUE self) { git_treebuilder *builder; git_tree *tree = NULL; VALUE rb_object; int error; if (rb_scan_args(argc, argv, "01", &rb_object) == 1) { if (!rb_obj_is_kind_of(rb_object, rb_cRuggedTree)) rb_raise(rb_eTypeError, "A Rugged::Tree instance is required"); Data_Get_Struct(rb_object, git_tree, tree); } error = git_treebuilder_create(&builder, tree); rugged_exception_check(error); DATA_PTR(self) = builder; return Qnil; }
/* * call-seq: * Rugged.prettify_message(message, strip_comments = '#') -> clean_message * * Process a commit or tag message into standard form, by stripping trailing spaces and * comments, and making sure that the message has a proper header line. */ static VALUE rb_git_prettify_message(int argc, VALUE *argv, VALUE self) { char comment_char = '#'; int strip_comments = 1; git_buf message = { NULL }; VALUE rb_message, rb_strip; int error; VALUE result = Qnil; rb_scan_args(argc, argv, "11", &rb_message, &rb_strip); Check_Type(rb_message, T_STRING); switch (TYPE(rb_strip)) { case T_FALSE: strip_comments = 0; break; case T_STRING: if (RSTRING_LEN(rb_strip) > 0) comment_char = RSTRING_PTR(rb_strip)[0]; break; case T_TRUE: case T_NIL: default: break; } error = git_message_prettify(&message, StringValueCStr(rb_message), strip_comments, comment_char); if (!error) result = rb_enc_str_new(message.ptr, message.size, rb_utf8_encoding()); git_buf_free(&message); rugged_exception_check(error); return result; }
/* * call-seq: * Remote.new(repository, url) -> remote * * Return a new remote with +url+ in +repository+ , the remote is not persisted: * - +url+: a valid remote url * * Returns a new Rugged::Remote object * * Rugged::Remote.new(@repo, 'git://github.com/libgit2/libgit2.git') #=> #<Rugged::Remote:0x00000001fbfa80> */ static VALUE rb_git_remote_new(VALUE klass, VALUE rb_repo, VALUE rb_url) { git_remote *remote; git_repository *repo; int error; rugged_check_repo(rb_repo); rugged_validate_remote_url(rb_url); Data_Get_Struct(rb_repo, git_repository, repo); error = git_remote_create_anonymous( &remote, repo, StringValueCStr(rb_url), NULL); rugged_exception_check(error); return rugged_remote_new(klass, rb_repo, remote); }
/* * call-seq: * index.remove_dir(dir[, stage = 0]) -> nil * * Removes all entries under the given +dir+ with the given +stage+ * from the index. */ static VALUE rb_git_index_remove_directory(int argc, VALUE *argv, VALUE self) { git_index *index; int error, stage = 0; VALUE rb_dir, rb_stage; Data_Get_Struct(self, git_index, index); if (rb_scan_args(argc, argv, "11", &rb_dir, &rb_stage) > 1) { Check_Type(rb_stage, T_FIXNUM); stage = FIX2INT(rb_stage); } Check_Type(rb_dir, T_STRING); error = git_index_remove_directory(index, StringValueCStr(rb_dir), stage); rugged_exception_check(error); return Qnil; }
/* * call-seq: * remotes[name] -> remote or nil * * Lookup a remote in the collection with the given +name+. * * Returns a new Rugged::Remote object or +nil+ if the * remote doesn't exist. * * @repo.remotes["origin"] #=> #<Rugged::Remote:0x00000001fbfa80> */ static VALUE rb_git_remote_collection_aref(VALUE self, VALUE rb_name) { git_remote *remote; git_repository *repo; 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); error = git_remote_lookup(&remote, repo, StringValueCStr(rb_name)); if (error == GIT_ENOTFOUND) return Qnil; rugged_exception_check(error); return rugged_remote_new(rb_repo, remote); }
/* * call-seq: * Rebase.new(repo, branch, upstream[, onto][, options]) -> Rebase * * Initialize a new rebase operation. This will put +repo+ in a * rebase state. * * +branch+ is the branch to be rebased, and +upstream+ is the branch * which is to be the new base. If +onto+ is specified, this will be * the one base, and +upstream+ is used to determine which commits * from +branch+ to use for the rebase. * * You can pass merge and checkout options for the options hash, plus * a few rebase-specific ones: * * :quiet :: * If true, a flag will be set to ask tools to activate quiet * mode. This does not do anything for libgit2/rugged but can be * used to interact with other implementations. * * :inmemory :: * Do not put the repository in a rebase state but perform all the * operations in-memory. In case of conflicts, the RebaseOperation * returned by #next will contain the index which can be used to * resolve conflicts. * * :rewrite_notes_ref :: * Name of the notes reference used to rewrite notes for rebased * commits when finishing the rebase. If +nil+, it will be taken * from the configuration. */ static VALUE rb_git_rebase_new(int argc, VALUE* argv, VALUE klass) { int error = 0, exception = 0; git_rebase *rebase = NULL; git_repository *repo; git_annotated_commit *branch = NULL, *upstream = NULL, *onto = NULL; VALUE rb_repo, rb_branch, rb_upstream, rb_onto, rb_options; git_rebase_options options = GIT_REBASE_OPTIONS_INIT; rb_scan_args(argc, argv, "31:", &rb_repo, &rb_branch, &rb_upstream, &rb_onto, &rb_options); Data_Get_Struct(rb_repo, git_repository, repo); if ((exception = rugged_get_annotated_commit(&branch, rb_repo, rb_branch))) goto cleanup; if ((exception = rugged_get_annotated_commit(&upstream, rb_repo, rb_upstream))) goto cleanup; if (!NIL_P(rb_onto)) { if ((exception = rugged_get_annotated_commit(&onto, rb_repo, rb_onto))) goto cleanup; } parse_rebase_options(&options, rb_options); error = git_rebase_init(&rebase, repo, branch, upstream, onto, &options); cleanup: git_annotated_commit_free(branch); git_annotated_commit_free(upstream); git_annotated_commit_free(onto); if (error) { rugged_exception_check(error); } else if (exception) { rb_jump_tag(exception); } return rugged_rebase_new(klass, rb_repo, rebase); }
/* * call-seq: * remote.push(refspecs = nil, options = {}) -> hash * * Pushes the given +refspecs+ to the given +remote+. Returns a hash that contains * key-value pairs that reflect pushed refs and error messages, if applicable. * * You can optionally pass in an alternative list of +refspecs+ to use instead of the push * refspecs already configured for +remote+. * * The following options can be passed in the +options+ Hash: * * :credentials :: * The credentials to use for the push operation. Can be either an instance of one * of the Rugged::Credentials types, or a proc returning one of the former. * The proc will be called with the +url+, the +username+ from the url (if applicable) and * a list of applicable credential types. * * :update_tips :: * A callback that will be executed each time a reference is updated remotely. It will be * passed the +refname+, +old_oid+ and +new_oid+. * * Example: * * remote = Rugged::Remote.lookup(@repo, 'origin') * remote.push(["refs/heads/master", ":refs/heads/to_be_deleted"]) */ static VALUE rb_git_remote_push(int argc, VALUE *argv, VALUE self) { VALUE rb_refspecs, rb_options; VALUE rb_repo = rugged_owner(self); git_repository *repo; git_remote *remote; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; git_strarray refspecs; git_push_options opts = GIT_PUSH_OPTIONS_INIT; int error = 0; struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, rb_hash_new(), 0 }; rb_scan_args(argc, argv, "01:", &rb_refspecs, &rb_options); rugged_rb_ary_to_strarray(rb_refspecs, &refspecs); rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); Data_Get_Struct(self, git_remote, remote); rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload); if ((error = git_remote_set_callbacks(remote, &callbacks))) goto cleanup; error = git_remote_push(remote, &refspecs, &opts); cleanup: xfree(refspecs.strings); if (payload.exception) rb_jump_tag(payload.exception); rugged_exception_check(error); return payload.result; }
static VALUE rb_git_index_add(VALUE self, VALUE rb_entry) { git_index *index; git_index_entry *entry; int error; Data_Get_Struct(self, git_index, index); if (rb_obj_is_kind_of(rb_entry, rb_cRuggedIndexEntry)) { Data_Get_Struct(rb_entry, git_index_entry, entry); error = git_index_insert(index, entry); } else if (TYPE(rb_entry) == T_STRING) { error = git_index_add(index, RSTRING_PTR(rb_entry), 0); } else { rb_raise(rb_eTypeError, "index_entry must be an existing IndexEntry object or a path to a file in the repository"); } rugged_exception_check(error); return Qnil; }
/* * call-seq: * branch.remote_name -> string * * Get the name of the remote the branch belongs to. * * If +branch+ is a remote branch, the name of the remote it belongs to is * returned. If +branch+ is a tracking branch, the name of the remote * of the tracked branch is returned. * * Otherwise, +nil+ is returned. */ static VALUE rb_git_branch_remote_name(VALUE self) { git_reference *branch, *remote_ref; int error = 0; Data_Get_Struct(self, git_reference, branch); if (git_reference_is_remote(branch)) { remote_ref = branch; } else { error = git_branch_upstream(&remote_ref, branch); if (error == GIT_ENOTFOUND) return Qnil; rugged_exception_check(error); } return rb_git_branch__remote_name( rugged_owner(self), git_reference_name(remote_ref)); }
/* * call-seq: * Remote.add(repository, name, url) -> remote * * Add a new remote with +name+ and +url+ to +repository+ * - +url+: a valid remote url * - +name+: a valid remote name * * Returns a new Rugged::Remote object * * Rugged::Remote.add(@repo, 'origin', 'git://github.com/libgit2/rugged.git') #=> #<Rugged::Remote:0x00000001fbfa80> */ static VALUE rb_git_remote_add(VALUE klass, VALUE rb_repo,VALUE rb_name, VALUE rb_url) { git_remote *remote; git_repository *repo; int error; Check_Type(rb_name, T_STRING); rugged_validate_remote_url(rb_url); rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); error = git_remote_create( &remote, repo, StringValueCStr(rb_name), StringValueCStr(rb_url)); rugged_exception_check(error); return rugged_remote_new(klass, rb_repo, remote); }
/* * call-seq: * Patch.from_strings(old_content = nil, new_content = nil, options = {}) -> patch * * Directly generate a Rugged::Patch from the difference between the content of * the two strings `old_content` and `new_content`. * * The following options can be passed in the +options+ Hash: * * :old_path :: * An optional string to treat +blob+ as if it had this filename. * * :new_path :: * An optional string to treat +other+ as if it had this filename. * * Additionally, `options` can also contain all other valid diff options * (see Rugged::Tree#diff for a complete list). */ VALUE rb_git_patch_from_strings(int argc, VALUE *argv, VALUE self) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_patch *patch; char * old_path = NULL, * new_path = NULL; VALUE rb_old_buffer, rb_new_buffer, rb_options; rb_scan_args(argc, argv, "02:", &rb_old_buffer, &rb_new_buffer, &rb_options); if (!NIL_P(rb_options)) { VALUE rb_value; rb_value = rb_hash_aref(rb_options, CSTR2SYM("old_path")); if (!NIL_P(rb_value)) { Check_Type(rb_value, T_STRING); old_path = StringValueCStr(rb_value); } rb_value = rb_hash_aref(rb_options, CSTR2SYM("new_path")); if (!NIL_P(rb_value)) { Check_Type(rb_value, T_STRING); new_path = StringValueCStr(rb_value); } rugged_parse_diff_options(&opts, rb_options); } rugged_exception_check(git_patch_from_buffers(&patch, NIL_P(rb_old_buffer) ? NULL : StringValuePtr(rb_old_buffer), NIL_P(rb_old_buffer) ? 0 : RSTRING_LEN(rb_old_buffer), old_path, NIL_P(rb_new_buffer) ? NULL : StringValuePtr(rb_new_buffer), NIL_P(rb_new_buffer) ? 0 : RSTRING_LEN(rb_new_buffer), new_path, &opts )); return rugged_patch_new(self, patch); }
/* * call-seq: * index.write_tree([repo]) -> oid * * Write the index to a tree, either in the index's repository, or in * the given +repo+. * * If the index contains any files in conflict, writing the tree will fail. * * Returns the OID string of the written tree object. */ static VALUE rb_git_index_writetree(int argc, VALUE *argv, VALUE self) { git_index *index; git_oid tree_oid; int error; VALUE rb_repo; Data_Get_Struct(self, git_index, index); if (rb_scan_args(argc, argv, "01", &rb_repo) == 1) { git_repository *repo = NULL; rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); error = git_index_write_tree_to(&tree_oid, index, repo); } else { error = git_index_write_tree(&tree_oid, index); } rugged_exception_check(error); return rugged_create_oid(&tree_oid); }
static VALUE rb_git_diff_index_to_workdir(VALUE self, VALUE rb_options) { git_index *index; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_repository *repo; git_diff *diff = NULL; VALUE owner; int error; rugged_parse_diff_options(&opts, rb_options); Data_Get_Struct(self, git_index, index); owner = rugged_owner(self); Data_Get_Struct(owner, git_repository, repo); error = git_diff_index_to_workdir(&diff, repo, index, &opts); xfree(opts.pathspec.strings); rugged_exception_check(error); return rugged_diff_new(rb_cRuggedDiff, owner, diff); }
/* * 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; VALUE ret_arr, owner; int error; Data_Get_Struct(self, git_commit, commit); owner = rugged_owner(self); parent_count = git_commit_parentcount(commit); ret_arr = rb_ary_new2((long)parent_count); for (n = 0; n < parent_count; n++) { error = git_commit_parent(&parent, commit, n); rugged_exception_check(error); rb_ary_push(ret_arr, rugged_object_new(owner, (git_object *)parent)); } return ret_arr; }
/* * call-seq: * remote.check_connection(direction, options = {}) -> boolean * * Try to connect to the +remote+. Useful to simulate * <tt>git fetch --dry-run</tt> and <tt>git push --dry-run</tt>. * * Returns +true+ if connection is successful, +false+ otherwise. * * +direction+ must be either +:fetch+ or +:push+. * * The following options can be passed in the +options+ Hash: * * +credentials+ :: * The credentials to use for the connection. Can be either an instance of * one of the Rugged::Credentials types, or a proc returning one of the * former. * The proc will be called with the +url+, the +username+ from the url (if * applicable) and a list of applicable credential types. * * Example: * * remote = repo.remotes["origin"] * success = remote.check_connection(:fetch) * raise Error("Unable to pull without credentials") unless success */ static VALUE rb_git_remote_check_connection(int argc, VALUE *argv, VALUE self) { git_remote *remote; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, 0 }; VALUE rb_direction, rb_options; ID id_direction; int error, direction; Data_Get_Struct(self, git_remote, remote); rb_scan_args(argc, argv, "01:", &rb_direction, &rb_options); Check_Type(rb_direction, T_SYMBOL); id_direction = SYM2ID(rb_direction); if (id_direction == rb_intern("fetch")) direction = GIT_DIRECTION_FETCH; else if (id_direction == rb_intern("push")) direction = GIT_DIRECTION_PUSH; else rb_raise(rb_eTypeError, "Invalid direction. Expected :fetch or :push"); rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload); if ((error = git_remote_set_callbacks(remote, &callbacks)) < 0) goto cleanup; if (git_remote_connect(remote, direction)) return Qfalse; else { git_remote_disconnect(remote); return Qtrue; } cleanup: if (payload.exception) rb_jump_tag(payload.exception); rugged_exception_check(error); return Qfalse; }
/* * call-seq: * Commit.create_to_s(repository, data = {}) -> str * * Create a string with the contents of the commit, created 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+. * * 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) #=> "tree some_tree\nparent 2cb831...." */ static VALUE rb_git_commit_create_to_s(VALUE self, VALUE rb_repo, VALUE rb_data) { int error = 0; struct commit_data commit_data = { Qnil }; git_repository *repo; git_buf buf = { 0 }; VALUE ret; Check_Type(rb_data, T_HASH); rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); if ((error = parse_commit_options(&commit_data, repo, rb_data)) < 0) goto cleanup; error = git_commit_create_buffer( &buf, repo, commit_data.author, commit_data.committer, NULL, commit_data.message, commit_data.tree, commit_data.parent_count, commit_data.parents); cleanup: free_commit_options(&commit_data); if (!NIL_P(commit_data.rb_err_obj)) rb_exc_raise(commit_data.rb_err_obj); rugged_exception_check(error); ret = rb_str_new_utf8(buf.ptr); git_buf_free(&buf); return ret; }