static int clone_into(git_repository *repo, git_remote *_remote, const git_fetch_options *opts, const git_checkout_options *co_opts, const char *branch) { int error; git_buf reflog_message = GIT_BUF_INIT; git_fetch_options fetch_opts; git_remote *remote; assert(repo && _remote); if (!git_repository_is_empty(repo)) { git_error_set(GIT_ERROR_INVALID, "the repository is not empty"); return -1; } if ((error = git_remote_dup(&remote, _remote)) < 0) return error; memcpy(&fetch_opts, opts, sizeof(git_fetch_options)); fetch_opts.update_fetchhead = 0; fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL; git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); if ((error = git_remote_fetch(remote, NULL, &fetch_opts, git_buf_cstr(&reflog_message))) != 0) goto cleanup; error = checkout_branch(repo, remote, co_opts, branch, git_buf_cstr(&reflog_message)); cleanup: git_remote_free(remote); git_buf_dispose(&reflog_message); return error; }
static int clone_into(git_repository *repo, git_remote *_remote, const git_checkout_options *co_opts, const char *branch, const git_signature *signature) { int error; git_buf reflog_message = GIT_BUF_INIT; git_remote *remote; const git_remote_callbacks *callbacks; assert(repo && _remote); if (!git_repository_is_empty(repo)) { giterr_set(GITERR_INVALID, "the repository is not empty"); return -1; } if ((error = git_remote_dup(&remote, _remote)) < 0) return error; callbacks = git_remote_get_callbacks(_remote); if (!giterr__check_version(callbacks, 1, "git_remote_callbacks") && (error = git_remote_set_callbacks(remote, callbacks)) < 0) goto cleanup; if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0) goto cleanup; git_remote_set_update_fetchhead(remote, 0); git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); if ((error = git_remote_fetch(remote, signature, git_buf_cstr(&reflog_message))) != 0) goto cleanup; error = checkout_branch(repo, remote, co_opts, branch, signature, git_buf_cstr(&reflog_message)); cleanup: git_remote_free(remote); git_buf_free(&reflog_message); return error; }
void test_network_remote_remotes__dup(void) { git_strarray array; git_remote *dup; cl_git_pass(git_remote_dup(&dup, _remote)); cl_assert_equal_s(git_remote_name(dup), git_remote_name(_remote)); cl_assert_equal_s(git_remote_url(dup), git_remote_url(_remote)); cl_assert_equal_s(git_remote_pushurl(dup), git_remote_pushurl(_remote)); cl_git_pass(git_remote_get_fetch_refspecs(&array, _remote)); cl_assert_equal_i(1, (int)array.count); cl_assert_equal_s("+refs/heads/*:refs/remotes/test/*", array.strings[0]); git_strarray_free(&array); cl_git_pass(git_remote_get_push_refspecs(&array, _remote)); cl_assert_equal_i(0, (int)array.count); git_strarray_free(&array); git_remote_free(dup); }
/* * 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. * * 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. * * :message :: * A single line log message to be appended to the reflog of each local remote-tracking * branch that gets updated. Defaults to: "fetch". * * :signature :: * The signature to be used for populating the reflog entries. * * 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, rb_val; VALUE rb_repo = rugged_owner(self); VALUE rb_exception = Qnil, rb_result = rb_hash_new(); git_repository *repo; git_remote *remote, *tmp_remote = NULL; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; git_push *push = NULL; git_signature *signature = NULL; int error = 0, i = 0; char *log_message = NULL; struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, 0 }; rb_scan_args(argc, argv, "01:", &rb_refspecs, &rb_options); if (!NIL_P(rb_refspecs)) { Check_Type(rb_refspecs, T_ARRAY); for (i = 0; i < RARRAY_LEN(rb_refspecs); ++i) { VALUE rb_refspec = rb_ary_entry(rb_refspecs, i); Check_Type(rb_refspec, T_STRING); } } rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); Data_Get_Struct(self, git_remote, remote); if (!NIL_P(rb_options)) { rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload); rb_val = rb_hash_aref(rb_options, CSTR2SYM("message")); if (!NIL_P(rb_val)) log_message = StringValueCStr(rb_val); rb_val = rb_hash_aref(rb_options, CSTR2SYM("signature")); if (!NIL_P(rb_val)) signature = rugged_signature_get(rb_val, repo); } // Create a temporary remote that we use for pushing if ((error = git_remote_dup(&tmp_remote, remote)) || (error = git_remote_set_callbacks(tmp_remote, &callbacks))) goto cleanup; if (!NIL_P(rb_refspecs)) { git_remote_clear_refspecs(tmp_remote); for (i = 0; !error && i < RARRAY_LEN(rb_refspecs); ++i) { VALUE rb_refspec = rb_ary_entry(rb_refspecs, i); if ((error = git_remote_add_push(tmp_remote, StringValueCStr(rb_refspec)))) goto cleanup; } } if ((error = git_push_new(&push, tmp_remote))) goto cleanup; // TODO: Get rid of this once git_remote_push lands in libgit2. { git_strarray push_refspecs; size_t i; if ((error = git_remote_get_push_refspecs(&push_refspecs, tmp_remote))) goto cleanup; if (push_refspecs.count == 0) { rb_exception = rb_exc_new2(rb_eRuggedError, "no pushspecs are configured for the given remote"); goto cleanup; } for (i = 0; !error && i < push_refspecs.count; ++i) { error = git_push_add_refspec(push, push_refspecs.strings[i]); } git_strarray_free(&push_refspecs); if (error) goto cleanup; } if ((error = git_push_finish(push))) goto cleanup; if (!git_push_unpack_ok(push)) { rb_exception = rb_exc_new2(rb_eRuggedError, "the remote side did not unpack successfully"); goto cleanup; } if ((error = git_push_status_foreach(push, &push_status_cb, (void *)rb_result)) || (error = git_push_update_tips(push, signature, log_message))) goto cleanup; cleanup: git_push_free(push); git_remote_free(tmp_remote); git_signature_free(signature); if (!NIL_P(rb_exception)) rb_exc_raise(rb_exception); rugged_exception_check(error); return rb_result; }
/* * call-seq: * remote.fetch(refspecs = nil, options = {}) -> hash * * Downloads new data from the remote for the given +refspecs+ and updates tips. * * You can optionally pass in an alternative list of +refspecs+ to use instead of the fetch * refspecs already configured for +remote+. * * Returns a hash containing statistics for the fetch operation. * * The following options can be passed in the +options+ Hash: * * :credentials :: * The credentials to use for the fetch 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. * * :progress :: * A callback that will be executed with the textual progress received from the remote. * This is the text send over the progress side-band (ie. the "counting objects" output). * * :transfer_progress :: * A callback that will be executed to report clone progress information. It will be passed * the amount of +total_objects+, +indexed_objects+, +received_objects+, +local_objects+, * +total_deltas+, +indexed_deltas+ and +received_bytes+. * * :update_tips :: * A callback that will be executed each time a reference is updated locally. It will be * passed the +refname+, +old_oid+ and +new_oid+. * * :message :: * The message to insert into the reflogs. Defaults to "fetch". * * :signature :: * The signature to be used for updating the reflogs. * * Example: * * remote = Rugged::Remote.lookup(@repo, 'origin') * remote.fetch({ * transfer_progress: lambda { |total_objects, indexed_objects, received_objects, local_objects, total_deltas, indexed_deltas, received_bytes| * # ... * } * }) */ static VALUE rb_git_remote_fetch(int argc, VALUE *argv, VALUE self) { git_remote *remote, *tmp_remote = NULL; git_repository *repo; git_signature *signature = NULL; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, 0 }; char *log_message = NULL; int error, i; VALUE rb_options, rb_refspecs, rb_result = Qnil, rb_repo = rugged_owner(self); rb_scan_args(argc, argv, "01:", &rb_refspecs, &rb_options); if (!NIL_P(rb_refspecs)) { Check_Type(rb_refspecs, T_ARRAY); for (i = 0; i < RARRAY_LEN(rb_refspecs); ++i) { VALUE rb_refspec = rb_ary_entry(rb_refspecs, i); Check_Type(rb_refspec, T_STRING); } } Data_Get_Struct(self, git_remote, remote); rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); if (!NIL_P(rb_options)) { VALUE rb_val = rb_hash_aref(rb_options, CSTR2SYM("signature")); if (!NIL_P(rb_val)) signature = rugged_signature_get(rb_val, repo); rb_val = rb_hash_aref(rb_options, CSTR2SYM("message")); if (!NIL_P(rb_val)) log_message = StringValueCStr(rb_val); rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload); } if ((error = git_remote_dup(&tmp_remote, remote)) || (error = git_remote_set_callbacks(tmp_remote, &callbacks))) goto cleanup; if (!NIL_P(rb_refspecs)) { git_remote_clear_refspecs(tmp_remote); for (i = 0; !error && i < RARRAY_LEN(rb_refspecs); ++i) { VALUE rb_refspec = rb_ary_entry(rb_refspecs, i); if ((error = git_remote_add_fetch(tmp_remote, StringValueCStr(rb_refspec)))) goto cleanup; } } if ((error = git_remote_fetch(tmp_remote, signature, log_message)) == GIT_OK) { const git_transfer_progress *stats = git_remote_stats(tmp_remote); rb_result = rb_hash_new(); rb_hash_aset(rb_result, CSTR2SYM("total_objects"), UINT2NUM(stats->total_objects)); rb_hash_aset(rb_result, CSTR2SYM("indexed_objects"), UINT2NUM(stats->indexed_objects)); rb_hash_aset(rb_result, CSTR2SYM("received_objects"), UINT2NUM(stats->received_objects)); rb_hash_aset(rb_result, CSTR2SYM("local_objects"), UINT2NUM(stats->local_objects)); rb_hash_aset(rb_result, CSTR2SYM("total_deltas"), UINT2NUM(stats->total_deltas)); rb_hash_aset(rb_result, CSTR2SYM("indexed_deltas"), UINT2NUM(stats->indexed_deltas)); rb_hash_aset(rb_result, CSTR2SYM("received_bytes"), INT2FIX(stats->received_bytes)); } cleanup: git_signature_free(signature); git_remote_free(tmp_remote); if (payload.exception) rb_jump_tag(payload.exception); rugged_exception_check(error); return rb_result; }