PyObject * Remote_fetch(Remote *self, PyObject *args) { PyObject* py_stats = NULL; const git_transfer_progress *stats; int err; err = git_remote_connect(self->remote, GIT_DIRECTION_FETCH); if (err == GIT_OK) { err = git_remote_download(self->remote); if (err == GIT_OK) { stats = git_remote_stats(self->remote); py_stats = Py_BuildValue("{s:I,s:I,s:n}", "indexed_objects", stats->indexed_objects, "received_objects", stats->received_objects, "received_bytes", stats->received_bytes); err = git_remote_update_tips(self->remote); } git_remote_disconnect(self->remote); } if (err < 0) return Error_set(err); return (PyObject*) py_stats; }
/** * 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 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. * * :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; }
/* * 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; }
/** 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; }
/** * 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; }
int fetch(git_repository *repo, int argc, char **argv) { git_remote *remote = NULL; const git_transfer_progress *stats; struct dl_data data; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; #ifndef _WIN32 pthread_t worker; #endif argc = argc; // Figure out whether it's a named remote or a URL printf("Fetching %s for repo %p\n", argv[1], repo); if (git_remote_load(&remote, repo, argv[1]) < 0) { if (git_remote_create_inmemory(&remote, repo, NULL, argv[1]) < 0) return -1; } // Set up the callbacks (only update_tips for now) callbacks.update_tips = &update_cb; callbacks.progress = &progress_cb; git_remote_set_callbacks(remote, &callbacks); // Set up the information for the background worker thread data.remote = remote; data.ret = 0; data.finished = 0; stats = git_remote_stats(remote); #ifdef _WIN32 download(&data); #else pthread_create(&worker, NULL, download, &data); // Loop while the worker thread is still running. Here we show processed // and total objects in the pack and the amount of received // data. Most frontends will probably want to show a percentage and // the download rate. do { usleep(10000); if (stats->total_objects > 0) printf("Received %d/%d objects (%d) in %" PRIuZ " bytes\r", stats->received_objects, stats->total_objects, stats->indexed_objects, stats->received_bytes); } while (!data.finished); if (data.ret < 0) goto on_error; pthread_join(worker, NULL); #endif printf("\rReceived %d/%d objects in %zu bytes\n", stats->indexed_objects, stats->total_objects, stats->received_bytes); // Disconnect the underlying connection to prevent from idling. git_remote_disconnect(remote); // Update the references in the remote's namespace to point to the // right commits. This may be needed even if there was no packfile // to download, which can happen e.g. when the branches have been // changed but all the neede objects are available locally. if (git_remote_update_tips(remote) < 0) return -1; git_remote_free(remote); return 0; on_error: git_remote_free(remote); return -1; }
/** * 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_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; git2r_transfer_data payload = GIT2R_TRANSFER_DATA_INIT; 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); 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; 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, NULL, &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 (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; }
/** 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_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; #ifndef _WIN32 pthread_t worker; #endif 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], NULL) < 0) return -1; } // Set up the callbacks (only update_tips for now) callbacks.update_tips = &update_cb; callbacks.sideband_progress = &progress_cb; callbacks.credentials = cred_acquire_cb; git_remote_set_callbacks(remote, &callbacks); // Set up the information for the background worker thread data.remote = remote; data.ret = 0; data.finished = 0; stats = git_remote_stats(remote); #ifdef _WIN32 download(&data); #else pthread_create(&worker, NULL, download, &data); // Loop while the worker thread is still running. Here we show processed // and total objects in the pack and the amount of received // data. Most frontends will probably want to show a percentage and // the download rate. do { usleep(10000); if (stats->received_objects == stats->total_objects) { printf("Resolving deltas %d/%d\r", stats->indexed_deltas, stats->total_deltas); } else if (stats->total_objects > 0) { printf("Received %d/%d objects (%d) in %" PRIuZ " bytes\r", stats->received_objects, stats->total_objects, stats->indexed_objects, stats->received_bytes); } } while (!data.finished); if (data.ret < 0) goto on_error; pthread_join(worker, NULL); #endif /** * 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. */ if (stats->local_objects > 0) { printf("\rReceived %d/%d objects in %zu 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 %zu bytes\n", stats->indexed_objects, stats->total_objects, stats->received_bytes); } // Disconnect the underlying connection to prevent from idling. git_remote_disconnect(remote); // Update the references in the remote's namespace to point to the // right commits. This may be needed even if there was no packfile // to download, which can happen e.g. when the branches have been // changed but all the needed objects are available locally. if (git_remote_update_tips(remote, NULL) < 0) return -1; git_remote_free(remote); return 0; on_error: git_remote_free(remote); return -1; }
/** Entry point for this command */ int fetch(git_repository *repo, int argc, char **argv) { int err = GIT_OK; int rc = EXIT_FAILURE; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; const git_transfer_progress *stats; git_remote *remote = NULL; 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 at %s\n", argv[1], git_repository_path(repo)); if (git_remote_lookup(&remote, repo, argv[1]) < 0) { if ((err = git_remote_create_anonymous(&remote, repo, argv[1], NULL)) < 0) goto out; } // Set up the callbacks (only update_tips for now) callbacks.update_tips = &update_cb; callbacks.sideband_progress = &progress_cb; callbacks.credentials = cred_acquire_cb; callbacks.certificate_check = certificate_check; git_remote_set_callbacks(remote, &callbacks); stats = git_remote_stats(remote); if ((err = git_remote_connect(remote, GIT_DIRECTION_FETCH) < 0)) goto out; // Download the packfile and index it. This function updates the // amount of received data and the indexer stats which lets you // inform the user about progress. if ((err = git_remote_download(remote, NULL) < 0)) goto out; /** * 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. */ if (stats->local_objects > 0) { printf("\rReceived %d/%d objects in %zu 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 %zu bytes\n", stats->indexed_objects, stats->total_objects, stats->received_bytes); } // Disconnect the underlying connection to prevent from idling. git_remote_disconnect(remote); // Update the references in the remote's namespace to point to the // right commits. This may be needed even if there was no packfile // to download, which can happen e.g. when the branches have been // changed but all the needed objects are available locally. if ((err = git_remote_update_tips(remote, NULL, NULL)) < 0) goto out; rc = EXIT_SUCCESS; out: if (err != GIT_OK) libgit_error(); if (remote) git_remote_free(remote); return rc; }