int sync_with_remote(git_repository *repo, const char *remote, const char *branch, enum remote_transport rt) { int error; git_remote *origin; char *proxy_string; git_config *conf; if (verbose) fprintf(stderr, "sync with remote %s[%s]\n", remote, branch); git_repository_config(&conf, repo); if (rt == RT_HTTPS && getProxyString(&proxy_string)) { git_config_set_string(conf, "http.proxy", proxy_string); free(proxy_string); } else { git_config_set_string(conf, "http.proxy", ""); } /* * NOTE! Remote errors are reported, but are nonfatal: * we still successfully return the local repository. */ error = git_remote_lookup(&origin, repo, "origin"); if (error) { report_error("Repository '%s' origin lookup failed (%s)", remote, giterr_last()->message); return 0; } if (rt == RT_HTTPS && !canReachCloudServer()) { // this is not an error, just a warning message, so return 0 report_error("Cannot connect to cloud server, working with local copy"); return 0; } #if USE_LIBGIT23_API git_fetch_options opts = GIT_FETCH_OPTIONS_INIT; opts.callbacks.transfer_progress = &transfer_progress_cb; if (rt == RT_SSH) opts.callbacks.credentials = credential_ssh_cb; else if (rt == RT_HTTPS) opts.callbacks.credentials = credential_https_cb; opts.callbacks.certificate_check = certificate_check_cb; error = git_remote_fetch(origin, NULL, &opts, NULL); #else error = git_remote_fetch(origin, NULL, NULL, NULL); #endif // NOTE! A fetch error is not fatal, we just report it if (error) { report_error("Unable to fetch remote '%s'", remote); error = 0; } else { error = check_remote_status(repo, origin, branch, rt); } git_remote_free(origin); return error; }
void test_network_fetchlocal__prune(void) { git_repository *repo; git_remote *origin; int callcount = 0; git_strarray refnames = {0}; git_reference *ref; git_repository *remote_repo = cl_git_sandbox_init("testrepo.git"); const char *url = cl_git_path_url(git_repository_path(remote_repo)); git_fetch_options options = GIT_FETCH_OPTIONS_INIT; options.callbacks.transfer_progress = transfer_cb; options.callbacks.payload = &callcount; cl_set_cleanup(&cleanup_local_repo, "foo"); cl_git_pass(git_repository_init(&repo, "foo", true)); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(19, (int)refnames.count); cl_assert(callcount > 0); git_strarray_free(&refnames); git_remote_free(origin); cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/br2")); cl_git_pass(git_reference_delete(ref)); git_reference_free(ref); cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN)); cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); cl_git_pass(git_remote_prune(origin, &options.callbacks)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(18, (int)refnames.count); git_strarray_free(&refnames); git_remote_free(origin); cl_git_pass(git_reference_lookup(&ref, remote_repo, "refs/heads/packed")); cl_git_pass(git_reference_delete(ref)); git_reference_free(ref); cl_git_pass(git_remote_lookup(&origin, repo, GIT_REMOTE_ORIGIN)); cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); cl_git_pass(git_remote_prune(origin, &options.callbacks)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(17, (int)refnames.count); git_strarray_free(&refnames); git_remote_free(origin); git_repository_free(repo); }
/** * Fetch new data and update tips * * @param repo S4 class git_repository * @param name The name of the remote to fetch from * @param credentials The credentials for remote repository access. * @param msg The one line long message to be appended to the reflog * @return R_NilValue */ SEXP git2r_remote_fetch( SEXP repo, SEXP name, SEXP credentials, SEXP msg) { int err; SEXP result = R_NilValue; const git_transfer_progress *stats; git_remote *remote = NULL; git_repository *repository = NULL; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; if (git2r_arg_check_string(name)) git2r_error(git2r_err_string_arg, __func__, "name"); if (git2r_arg_check_credentials(credentials)) git2r_error(git2r_err_credentials_arg, __func__, "credentials"); if (git2r_arg_check_string(msg)) git2r_error(git2r_err_string_arg, __func__, "msg"); repository = git2r_repository_open(repo); if (!repository) git2r_error(git2r_err_invalid_repository, __func__, NULL); err = git_remote_lookup(&remote, repository, CHAR(STRING_ELT(name, 0))); if (GIT_OK != err) goto cleanup; callbacks.credentials = &git2r_cred_acquire_cb; callbacks.payload = credentials; err = git_remote_set_callbacks(remote, &callbacks); if (GIT_OK != err) goto cleanup; err = git_remote_fetch(remote, NULL, CHAR(STRING_ELT(msg, 0))); if (GIT_OK != err) goto cleanup; stats = git_remote_stats(remote); PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_transfer_progress"))); git2r_transfer_progress_init(stats, result); cleanup: if (remote) { if (git_remote_connected(remote)) git_remote_disconnect(remote); git_remote_free(remote); } if (repository) git_repository_free(repository); if (R_NilValue != result) UNPROTECT(1); if (GIT_OK != err) git2r_error(git2r_err_from_libgit2, __func__, giterr_last()->message); return result; }
void test_network_remote_local__fetch(void) { char *refspec_strings[] = { "master:remotes/sloppy/master", }; git_strarray array = { refspec_strings, 1, }; git_reflog *log; const git_reflog_entry *entry; git_reference *ref; connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_fetch(remote, &array, NULL, "UPDAAAAAATE!!")); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master")); git_reference_free(ref); cl_git_pass(git_reflog_read(&log, repo, "refs/remotes/sloppy/master")); cl_assert_equal_i(1, git_reflog_entrycount(log)); entry = git_reflog_entry_byindex(log, 0); cl_assert_equal_s("*****@*****.**", git_reflog_entry_committer(entry)->email); cl_assert_equal_s("UPDAAAAAATE!!", git_reflog_entry_message(entry)); git_reflog_free(log); }
void test_network_remote_remotes__nonmatch_upstream_refspec(void) { git_config *config; git_remote *remote; char *specstr[] = { "refs/tags/*:refs/tags/*", }; git_strarray specs = { specstr, 1, }; cl_git_pass(git_remote_create(&remote, _repo, "taggy", git_repository_path(_repo))); /* * Set the current branch's upstream remote to a dummy ref so we call into the code * which tries to check for the current branch's upstream in the refspecs */ cl_git_pass(git_repository_config(&config, _repo)); cl_git_pass(git_config_set_string(config, "branch.master.remote", "taggy")); cl_git_pass(git_config_set_string(config, "branch.master.merge", "refs/heads/foo")); cl_git_pass(git_remote_fetch(remote, &specs, NULL, NULL)); git_remote_free(remote); }
void test_network_fetchlocal__complete(void) { git_repository *repo; git_remote *origin; int callcount = 0; git_strarray refnames = {0}; const char *url = cl_git_fixture_url("testrepo.git"); git_fetch_options options = GIT_FETCH_OPTIONS_INIT; options.callbacks.transfer_progress = transfer_cb; options.callbacks.payload = &callcount; cl_set_cleanup(&cleanup_local_repo, "foo"); cl_git_pass(git_repository_init(&repo, "foo", true)); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); cl_git_pass(git_remote_fetch(origin, NULL, &options, NULL)); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(19, (int)refnames.count); cl_assert(callcount > 0); git_strarray_free(&refnames); git_remote_free(origin); git_repository_free(repo); }
emacs_value egit_remote_fetch( emacs_env *env, emacs_value _remote, emacs_value _refspecs, emacs_value opts, emacs_value _msg) { EGIT_ASSERT_REMOTE(_remote); EM_ASSERT_STRING_OR_NIL(_msg); git_strarray refspecs; if (!egit_strarray_from_list(&refspecs, env, _refspecs)) return em_nil; git_fetch_options options; egit_fetch_options_parse(env, opts, &options); if (env->non_local_exit_check(env)) { egit_strarray_dispose(&refspecs); return em_nil; } git_remote *remote = EGIT_EXTRACT(_remote); char *msg = EM_EXTRACT_STRING_OR_NULL(_msg); int retval = git_remote_fetch(remote, &refspecs, &options, msg); free(msg); egit_strarray_dispose(&refspecs); egit_fetch_options_release(&options); EGIT_CHECK_ERROR(retval); return em_nil; }
static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fetchhead) { git_remote *remote; git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; git_buf fetchhead_buf = GIT_BUF_INIT; int equals = 0; git_strarray array, *active_refs = NULL; cl_git_pass(git_remote_lookup(&remote, g_repo, "origin")); fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO; if(fetchspec != NULL) { array.count = 1; array.strings = (char **) &fetchspec; active_refs = &array; } cl_git_pass(git_remote_fetch(remote, active_refs, &fetch_opts, NULL)); git_remote_free(remote); cl_git_pass(git_futils_readbuffer(&fetchhead_buf, "./foo/.git/FETCH_HEAD")); equals = (strcmp(fetchhead_buf.ptr, expected_fetchhead) == 0); git_buf_dispose(&fetchhead_buf); cl_assert(equals); }
void test_network_remote_local__push_to_bare_remote(void) { char *refspec_strings[] = { "master:master", }; git_strarray array = { refspec_strings, 1, }; /* Should be able to push to a bare remote */ git_remote *localremote; /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); /* Set up an empty bare repo to push into */ { git_repository *localbarerepo; cl_git_pass(git_repository_init(&localbarerepo, "./localbare.git", 1)); git_repository_free(localbarerepo); } /* Connect to the bare repo */ cl_git_pass(git_remote_create_anonymous(&localremote, repo, "./localbare.git")); cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL, NULL, NULL)); /* Try to push */ cl_git_pass(git_remote_upload(localremote, &push_array, NULL)); /* Clean up */ git_remote_free(localremote); cl_fixture_cleanup("localbare.git"); }
void test_network_remote_local__push_to_non_bare_remote(void) { char *refspec_strings[] = { "master:master", }; git_strarray array = { refspec_strings, 1, }; /* Shouldn't be able to push to a non-bare remote */ git_remote *localremote; git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_fetch(remote, &array, &fetch_opts, NULL)); /* Set up an empty non-bare repo to push into */ { git_repository *remoterepo = NULL; cl_git_pass(git_repository_init(&remoterepo, "localnonbare", 0)); git_repository_free(remoterepo); } /* Connect to the bare repo */ cl_git_pass(git_remote_create_anonymous(&localremote, repo, "./localnonbare")); cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL, NULL, NULL)); /* Try to push */ cl_git_fail_with(GIT_EBAREREPO, git_remote_upload(localremote, &push_array, NULL)); /* Clean up */ git_remote_free(localremote); cl_fixture_cleanup("localbare.git"); }
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; }
void test_network_remote_local__fetch_default_reflog_message(void) { char *refspec_strings[] = { "master:remotes/sloppy/master", }; git_strarray array = { refspec_strings, 1, }; git_reflog *log; const git_reflog_entry *entry; char expected_reflog_msg[1024]; connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); cl_git_pass(git_reflog_read(&log, repo, "refs/remotes/sloppy/master")); cl_assert_equal_i(1, git_reflog_entrycount(log)); entry = git_reflog_entry_byindex(log, 0); cl_assert_equal_s("*****@*****.**", git_reflog_entry_committer(entry)->email); sprintf(expected_reflog_msg, "fetch %s", git_remote_url(remote)); cl_assert_equal_s(expected_reflog_msg, git_reflog_entry_message(entry)); git_reflog_free(log); }
static int clone_local_into(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, int link, const git_signature *signature) { int error, flags; git_repository *src; git_buf src_odb = GIT_BUF_INIT, dst_odb = GIT_BUF_INIT, src_path = GIT_BUF_INIT; git_buf reflog_message = GIT_BUF_INIT; assert(repo && remote); if (!git_repository_is_empty(repo)) { giterr_set(GITERR_INVALID, "the repository is not empty"); return -1; } /* * Let's figure out what path we should use for the source * repo, if it's not rooted, the path should be relative to * the repository's worktree/gitdir. */ if ((error = git_path_from_url_or_path(&src_path, git_remote_url(remote))) < 0) return error; /* Copy .git/objects/ from the source to the target */ if ((error = git_repository_open(&src, git_buf_cstr(&src_path))) < 0) { git_buf_free(&src_path); return error; } git_buf_joinpath(&src_odb, git_repository_path(src), GIT_OBJECTS_DIR); git_buf_joinpath(&dst_odb, git_repository_path(repo), GIT_OBJECTS_DIR); if (git_buf_oom(&src_odb) || git_buf_oom(&dst_odb)) { error = -1; goto cleanup; } flags = 0; if (can_link(git_repository_path(src), git_repository_path(repo), link)) flags |= GIT_CPDIR_LINK_FILES; if ((error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb), flags, GIT_OBJECT_DIR_MODE)) < 0) goto cleanup; 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_buf_free(&reflog_message); git_buf_free(&src_path); git_buf_free(&src_odb); git_buf_free(&dst_odb); git_repository_free(src); return error; }
void do_update_repo(char *url, char *path) { git_repository *repo; git_remote *remote = NULL; git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; const git_transfer_progress *stats; char textfield_final_string[MAXLINE]; memset(textfield_final_string, 0, sizeof(textfield_final_string)); int error = git_repository_open(&repo, path); if (error != 0) git_error_handling(); if (git_remote_lookup(&remote, repo, url) != 0) { error = git_remote_create_anonymous(&remote, repo, url); if (error != 0) git_error_handling(); } fetch_opts.callbacks.update_tips = &update_tips; fetch_opts.callbacks.sideband_progress = sideband_progress; fetch_opts.callbacks.transfer_progress = fetch_progress; error = git_remote_fetch(remote, NULL, &fetch_opts, "fetch"); if (error != 0) git_error_handling(); stats = git_remote_stats(remote); int receive_kbyte = stats->received_bytes / 1024; if (stats->local_objects > 0) { snprintf(textfield_final_string, sizeof(textfield_final_string), _("Fetched: (%d/%d) %d kB (used %d local objects)"), stats->indexed_objects, stats->total_objects, receive_kbyte, stats->local_objects); write_info_msg(textfield_final_string); } else { snprintf(textfield_final_string, sizeof(textfield_final_string), _("Fetched: (%d/%d) %d kB"), stats->indexed_objects, stats->total_objects, receive_kbyte); write_info_msg(textfield_final_string); } out: if (remote) git_remote_free(remote); if (repo) git_repository_free(repo); }
/* * 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 a single or multiple alternative +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. * * :headers :: * Extra HTTP headers to include with the request (only applies to http:// or https:// remotes) * * :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+. * * :certificate_check :: * A callback that will be executed each time we validate a certificate using https. It * will be passed the +valid+, +host_name+ and the callback should return a true/false to * indicate if the certificate has been validated. * * :message :: * The message to insert into the reflogs. Defaults to "fetch". * * :prune :: * Specifies the prune mode for the fetch. +true+ remove any remote-tracking references that * no longer exist, +false+ do not prune, +nil+ use configured settings Defaults to "nil". * * 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; git_strarray refspecs; git_fetch_options opts = GIT_FETCH_OPTIONS_INIT; const git_transfer_progress *stats; struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, 0 }; char *log_message = NULL; int error; VALUE rb_options, rb_refspecs, rb_result = Qnil; rb_scan_args(argc, argv, "01:", &rb_refspecs, &rb_options); rugged_rb_ary_to_strarray(rb_refspecs, &refspecs); Data_Get_Struct(self, git_remote, remote); rugged_remote_init_callbacks_and_payload_from_options(rb_options, &opts.callbacks, &payload); init_custom_headers(rb_options, &opts.custom_headers); if (!NIL_P(rb_options)) { VALUE rb_prune_type; VALUE rb_val = rb_hash_aref(rb_options, CSTR2SYM("message")); if (!NIL_P(rb_val)) log_message = StringValueCStr(rb_val); rb_prune_type = rb_hash_aref(rb_options, CSTR2SYM("prune")); opts.prune = parse_prune_type(rb_prune_type); } error = git_remote_fetch(remote, &refspecs, &opts, log_message); xfree(refspecs.strings); git_strarray_free(&opts.custom_headers); if (payload.exception) rb_jump_tag(payload.exception); rugged_exception_check(error); stats = git_remote_stats(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)); 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 a single or multiple alternative +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". * * 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; git_repository *repo; git_strarray refspecs; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; struct rugged_remote_cb_payload payload = { Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, 0 }; char *log_message = NULL; int error; VALUE rb_options, rb_refspecs, rb_result = Qnil, rb_repo = rugged_owner(self); rb_scan_args(argc, argv, "01:", &rb_refspecs, &rb_options); rugged_rb_ary_to_strarray(rb_refspecs, &refspecs); Data_Get_Struct(self, git_remote, remote); rugged_check_repo(rb_repo); Data_Get_Struct(rb_repo, git_repository, repo); rugged_remote_init_callbacks_and_payload_from_options(rb_options, &callbacks, &payload); if (!NIL_P(rb_options)) { VALUE rb_val = rb_hash_aref(rb_options, CSTR2SYM("message")); if (!NIL_P(rb_val)) log_message = StringValueCStr(rb_val); } if ((error = git_remote_set_callbacks(remote, &callbacks))) goto cleanup; if ((error = git_remote_fetch(remote, &refspecs, log_message)) == GIT_OK) { const git_transfer_progress *stats = git_remote_stats(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: xfree(refspecs.strings); if (payload.exception) rb_jump_tag(payload.exception); rugged_exception_check(error); return rb_result; }
void test_network_remote_local__tagopt(void) { git_reference *ref; git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; cl_git_pass(git_remote_create(&remote, repo, "tagopt", cl_git_path_url(cl_fixture("testrepo.git")))); fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL; cl_git_pass(git_remote_fetch(remote, NULL, &fetch_opts, NULL)); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/tagopt/master")); git_reference_free(ref); cl_git_pass(git_reference_lookup(&ref, repo, "refs/tags/hard_tag")); git_reference_free(ref); fetch_opts.download_tags = GIT_REMOTE_DOWNLOAD_TAGS_AUTO; cl_git_pass(git_remote_fetch(remote, NULL, &fetch_opts, NULL)); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/tagopt/master")); git_reference_free(ref); }
void GitRepository::fetch() { git_repository* repo = repository(); const char* remote_name = "origin"; git_auto<git_remote> remote; git_eval(git_remote_lookup(&remote, repo, remote_name)); git_eval(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL)); git_eval(git_remote_fetch(remote, NULL, NULL, NULL)); }
/** Entry point for this command */ int fetch(git_repository *repo, int argc, char **argv) { git_remote *remote = NULL; const git_transfer_progress *stats; struct dl_data data; git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; if (argc < 2) { fprintf(stderr, "usage: %s fetch <repo>\n", argv[-1]); return EXIT_FAILURE; } // Figure out whether it's a named remote or a URL printf("Fetching %s for repo %p\n", argv[1], repo); if (git_remote_lookup(&remote, repo, argv[1]) < 0) { if (git_remote_create_anonymous(&remote, repo, argv[1]) < 0) return -1; } // Set up the callbacks (only update_tips for now) fetch_opts.callbacks.update_tips = &update_cb; fetch_opts.callbacks.sideband_progress = &progress_cb; fetch_opts.callbacks.transfer_progress = transfer_progress_cb; fetch_opts.callbacks.credentials = cred_acquire_cb; /** * Perform the fetch with the configured refspecs from the * config. Update the reflog for the updated references with * "fetch". */ if (git_remote_fetch(remote, NULL, &fetch_opts, "fetch") < 0) return -1; /** * If there are local objects (we got a thin pack), then tell * the user how many objects we saved from having to cross the * network. */ stats = git_remote_stats(remote); if (stats->local_objects > 0) { printf("\rReceived %d/%d objects in %" PRIuZ " bytes (used %d local objects)\n", stats->indexed_objects, stats->total_objects, stats->received_bytes, stats->local_objects); } else{ printf("\rReceived %d/%d objects in %" PRIuZ "bytes\n", stats->indexed_objects, stats->total_objects, stats->received_bytes); } git_remote_free(remote); return 0; on_error: git_remote_free(remote); return -1; }
Future<void> GitRepo::fetch() const { return async([this](Notifier notifier) { auto remote = GitResource<git_remote>::create(&git_remote_lookup, &git_remote_free, m_repo, "origin"); GitPayload payload{notifier}; git_fetch_options opts = GIT_FETCH_OPTIONS_INIT; opts.callbacks.transfer_progress = &gitFetchNotifier; opts.callbacks.payload = &payload; opts.callbacks.credentials = &credentialsCallback; GitException::checkAndThrow(git_remote_fetch(remote, nullptr, &opts, nullptr)); }); }
/** * Fetches the contents of the server into the "incoming" branch. */ int sync_fetch(git_repository *repo, const char *server) { int e = 0; git_remote *remote = NULL; git_fetch_options options= GIT_FETCH_OPTIONS_INIT; char *refspec[] = {SYNC_FETCH_REFSPEC}; git_strarray refspecs = {refspec, 1}; git_check(git_remote_create_anonymous(&remote, repo, server)); git_check(git_remote_fetch(remote, &refspecs, &options, "fetch")); exit: if (remote) git_remote_free(remote); return e; }
void QGit::fetch() { git_repository *repo = nullptr; git_remote *remote = nullptr; int res = 0; QGitError error; try { res = git_repository_open(&repo, m_path.absolutePath().toUtf8().constData()); if (res) { throw QGitError("git_repository_open", res); } res = git_remote_lookup(&remote, repo, "origin"); if (res) { throw QGitError("git_remote_lookup", res); } res = git_remote_fetch(remote, nullptr, nullptr, "fetch"); if (res) { throw QGitError("git_remote_fetch", res); } } catch(const QGitError &ex) { error = ex; } emit fetchReply(error); if (remote) { git_remote_free(remote); remote = nullptr; } if (repo) { git_repository_free(repo); repo = nullptr; } }
void test_checkout_index__honor_coresymlinks_default(void) { git_repository *repo; git_remote *origin; git_object *target; char cwd[GIT_PATH_MAX]; const char *url = git_repository_path(g_repo); cl_assert(getcwd(cwd, sizeof(cwd)) != NULL); cl_assert_equal_i(0, p_mkdir("readonly", 0555)); // Read-only directory cl_assert_equal_i(0, chdir("readonly")); cl_git_pass(git_repository_init(&repo, "../symlink.git", true)); cl_assert_equal_i(0, chdir(cwd)); cl_assert_equal_i(0, p_mkdir("symlink", 0777)); cl_git_pass(git_repository_set_workdir(repo, "symlink", 1)); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); cl_git_pass(git_remote_fetch(origin, NULL, NULL, NULL)); git_remote_free(origin); cl_git_pass(git_revparse_single(&target, repo, "remotes/origin/master")); cl_git_pass(git_reset(repo, target, GIT_RESET_HARD, NULL)); git_object_free(target); git_repository_free(repo); #ifdef GIT_WIN32 check_file_contents("./symlink/link_to_new.txt", "new.txt"); #else { char link_data[1024]; size_t link_size = 1024; link_size = p_readlink("./symlink/link_to_new.txt", link_data, link_size); link_data[link_size] = '\0'; cl_assert_equal_i(link_size, strlen("new.txt")); cl_assert_equal_s(link_data, "new.txt"); check_file_contents("./symlink/link_to_new.txt", "my new file\n"); } #endif cl_fixture_cleanup("symlink"); }
void test_network_remote_local__shorthand_fetch_refspec1(void) { char *refspec_strings[] = { "master", "hard_tag", }; git_strarray array = { refspec_strings, 2, }; git_reference *ref; connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/origin/master")); cl_git_fail(git_reference_lookup(&ref, repo, "refs/tags/hard_tag")); }
void test_network_remote_local__opportunistic_update(void) { git_reference *ref; char *refspec_strings[] = { "master", }; git_strarray array = { refspec_strings, 1, }; /* this remote has a passive refspec of "refs/heads/<star>:refs/remotes/origin/<star>" */ cl_git_pass(git_remote_create(&remote, repo, "origin", cl_git_fixture_url("testrepo.git"))); /* and we pass the active refspec "master" */ cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); /* and we expect that to update our copy of origin's master */ cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/origin/master")); git_reference_free(ref); }
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; }
int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch) { int error = 0, old_fetchhead; size_t nspecs; assert(repo && remote); if (!git_repository_is_empty(repo)) { giterr_set(GITERR_INVALID, "the repository is not empty"); return -1; } if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0) return error; old_fetchhead = git_remote_update_fetchhead(remote); git_remote_set_update_fetchhead(remote, 0); if ((error = git_remote_fetch(remote)) < 0) goto cleanup; if (branch) error = update_head_to_branch(repo, git_remote_name(remote), branch); /* Point HEAD to the same ref as the remote's head */ else error = update_head_to_remote(repo, remote); if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts)) error = git_checkout_head(repo, co_opts); cleanup: git_remote_set_update_fetchhead(remote, old_fetchhead); /* Remove the tags refspec */ nspecs = git_remote_refspec_count(remote); git_remote_remove_refspec(remote, nspecs); return error; }
void test_network_remote_local__shorthand_fetch_refspec0(void) { char *refspec_strings[] = { "master:remotes/sloppy/master", "master:boh/sloppy/master", }; git_strarray array = { refspec_strings, 2, }; git_reference *ref; connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_fetch(remote, &array, NULL, NULL)); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master")); git_reference_free(ref); cl_git_pass(git_reference_lookup(&ref, repo, "refs/heads/boh/sloppy/master")); git_reference_free(ref); }
/** * Fetch new data and update tips * * @param repo S4 class git_repository * @param name The name of the remote to fetch from * @param credentials The credentials for remote repository access. * @param msg The one line long message to be appended to the reflog * @param verbose Print information each time a reference is updated locally. * @param refspecs The refspecs to use for this fetch. Pass R_NilValue * to use the base refspecs. * @return R_NilValue */ SEXP git2r_remote_fetch( SEXP repo, SEXP name, SEXP credentials, SEXP msg, SEXP verbose, SEXP refspecs) { int err; SEXP result = R_NilValue; const git_transfer_progress *stats; git_remote *remote = NULL; git_repository *repository = NULL; git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; git2r_transfer_data payload = GIT2R_TRANSFER_DATA_INIT; git_strarray refs = {0}; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); if (git2r_arg_check_credentials(credentials)) git2r_error(__func__, NULL, "'credentials'", git2r_err_credentials_arg); if (git2r_arg_check_string(msg)) git2r_error(__func__, NULL, "'msg'", git2r_err_string_arg); if (git2r_arg_check_logical(verbose)) git2r_error(__func__, NULL, "'verbose'", git2r_err_logical_arg); if (refspecs != R_NilValue && git2r_arg_check_string_vec(refspecs)) git2r_error(__func__, NULL, "'refspecs'", git2r_err_string_vec_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); err = git_remote_lookup(&remote, repository, CHAR(STRING_ELT(name, 0))); if (err) goto cleanup; if (refspecs != R_NilValue) { size_t i, len; /* Count number of non NA values */ len = length(refspecs); for (i = 0; i < len; i++) if (NA_STRING != STRING_ELT(refspecs, i)) refs.count++; if (refs.count) { /* Allocate the strings in refs */ refs.strings = malloc(refs.count * sizeof(char*)); if (!refs.strings) { giterr_set_str(GITERR_NONE, git2r_err_alloc_memory_buffer); err = GIT_ERROR; goto cleanup; } /* Populate the strings in refs */ for (i = 0; i < refs.count; i++) if (NA_STRING != STRING_ELT(refspecs, i)) refs.strings[i] = (char *)CHAR(STRING_ELT(refspecs, i)); } } if (LOGICAL(verbose)[0]) payload.verbose = 1; payload.credentials = credentials; fetch_opts.callbacks.payload = &payload; fetch_opts.callbacks.credentials = &git2r_cred_acquire_cb; fetch_opts.callbacks.update_tips = &git2r_update_tips_cb; err = git_remote_fetch(remote, &refs, &fetch_opts, CHAR(STRING_ELT(msg, 0))); if (err) goto cleanup; stats = git_remote_stats(remote); PROTECT(result = NEW_OBJECT(MAKE_CLASS("git_transfer_progress"))); git2r_transfer_progress_init(stats, result); cleanup: if (refs.strings) free(refs.strings); if (remote) { if (git_remote_connected(remote)) git_remote_disconnect(remote); git_remote_free(remote); } if (repository) git_repository_free(repository); if (R_NilValue != result) UNPROTECT(1); if (err) git2r_error( __func__, giterr_last(), git2r_err_unable_to_authenticate, NULL); return 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; }