static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fetchhead) { git_remote *remote; git_buf fetchhead_buf = GIT_BUF_INIT; int equals = 0; cl_git_pass(git_remote_load(&remote, g_repo, "origin")); git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); if(fetchspec != NULL) { git_remote_clear_refspecs(remote); git_remote_add_fetch(remote, fetchspec); } cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote, NULL, NULL)); git_remote_disconnect(remote); 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_free(&fetchhead_buf); cl_assert(equals); }
static int setup_remotes_and_fetch( git_repository *repo, const char *origin_url, git_transfer_progress_callback progress_cb, void *progress_payload) { int retcode = GIT_ERROR; git_remote *origin = NULL; /* Create the "origin" remote */ if (!git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, origin_url)) { /* Connect and download everything */ if (!git_remote_connect(origin, GIT_DIR_FETCH)) { if (!git_remote_download(origin, progress_cb, progress_payload)) { /* Create "origin/foo" branches for all remote branches */ if (!git_remote_update_tips(origin)) { /* Point HEAD to the same ref as the remote's head */ if (!update_head_to_remote(repo, origin)) { retcode = 0; } } } git_remote_disconnect(origin); } git_remote_free(origin); } return retcode; }
void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date(void) { git_repository *_repository; bool invoked = false; git_remote *remote; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; git_clone_options opts = GIT_CLONE_OPTIONS_INIT; opts.bare = true; cl_git_pass(git_clone(&_repository, "https://github.com/libgit2/TestGitRepository.git", "./fetch/lg2", &opts)); git_repository_free(_repository); cl_git_pass(git_repository_open(&_repository, "./fetch/lg2")); cl_git_pass(git_remote_load(&remote, _repository, "origin")); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_assert_equal_i(false, invoked); callbacks.transfer_progress = &transferProgressCallback; callbacks.payload = &invoked; git_remote_set_callbacks(remote, &callbacks); cl_git_pass(git_remote_download(remote)); cl_assert_equal_i(false, invoked); cl_git_pass(git_remote_update_tips(remote, NULL, NULL)); git_remote_disconnect(remote); git_remote_free(remote); git_repository_free(_repository); }
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; }
void test_network_fetchlocal__partial(void) { git_repository *repo = cl_git_sandbox_init("partial-testrepo"); git_remote *origin; int callcount = 0; git_strarray refnames = {0}; const char *url; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; callbacks.transfer_progress = transfer_cb; callbacks.payload = &callcount; cl_set_cleanup(&cleanup_sandbox, NULL); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(1, (int)refnames.count); url = cl_git_fixture_url("testrepo.git"); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(origin)); cl_git_pass(git_remote_update_tips(origin, NULL, NULL)); git_strarray_free(&refnames); cl_git_pass(git_reference_list(&refnames, repo)); cl_assert_equal_i(20, (int)refnames.count); /* 18 remote + 1 local */ cl_assert(callcount > 0); git_strarray_free(&refnames); git_remote_free(origin); }
/** * ggit_remote_update_tips: * @remote: a #GgitRemote. * @callbacks: a #GgitRemoteCallbacks. * @update_fetch_head: whether to write to FETCH_HEAD. %TRUE to behave like git. * @tags_type: what the behaviour for downloading tags is for this fetch. This is * ignored for push. This must be the same value passed to * ggit_remote_download(). * @message: (allow-none): reflog_message The message to insert into the reflogs. If * %NULL and fetching, the default is "fetch <name>", * where <name> is the name of the remote (or its url, * for in-memory remotes). This parameter is ignored when pushing. * @error: a #GError for error reporting, or %NULL. * * Update tips to the new state. * * Returns: %TRUE if successful, %FALSE otherwise. */ gboolean ggit_remote_update_tips (GgitRemote *remote, GgitRemoteCallbacks *callbacks, gboolean update_fetch_head, GgitRemoteDownloadTagsType tags_type, const gchar *message, GError **error) { gint ret; g_return_val_if_fail (GGIT_IS_REMOTE (remote), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); ret = git_remote_update_tips (_ggit_native_get (remote), _ggit_remote_callbacks_get_native (callbacks), update_fetch_head, (git_remote_autotag_option_t)tags_type, message); if (ret != GIT_OK) { _ggit_error_set (error, ret); return FALSE; } return TRUE; }
static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fetchhead) { git_remote *remote; 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")); git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); if(fetchspec != NULL) { array.count = 1; array.strings = (char **) &fetchspec; active_refs = &array; } cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(remote, active_refs)); cl_git_pass(git_remote_update_tips(remote, NULL)); git_remote_disconnect(remote); 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_free(&fetchhead_buf); cl_assert(equals); }
static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) { git_remote *remote; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; size_t bytes_received = 0; callbacks.transfer_progress = progress; callbacks.update_tips = update_tips; callbacks.payload = &bytes_received; counter = 0; cl_git_pass(git_remote_create(&remote, _repo, "test", url)); git_remote_set_callbacks(remote, &callbacks); git_remote_set_autotag(remote, flag); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote, NULL, NULL)); git_remote_disconnect(remote); cl_assert_equal_i(counter, n); cl_assert(bytes_received > 0); git_remote_free(remote); }
static int setup_remotes_and_fetch( git_repository *repo, const char *url, const git_clone_options *options) { int retcode = GIT_ERROR; git_remote *origin; /* Construct an origin remote */ if (!create_and_configure_origin(&origin, repo, url, options)) { git_remote_set_update_fetchhead(origin, 0); /* Connect and download everything */ if (!git_remote_connect(origin, GIT_DIRECTION_FETCH)) { if (!(retcode = git_remote_download(origin, options->fetch_progress_cb, options->fetch_progress_payload))) { /* Create "origin/foo" branches for all remote branches */ if (!git_remote_update_tips(origin)) { /* Point HEAD to the requested branch */ if (options->checkout_branch) { if (!update_head_to_branch(repo, options)) retcode = 0; } /* Point HEAD to the same ref as the remote's head */ else if (!update_head_to_remote(repo, origin)) { retcode = 0; } } } git_remote_disconnect(origin); } git_remote_free(origin); } return retcode; }
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; }
static int handle(KDriver const *driver, KImplementation const *impl, int requested) { char const *url = k_dictionary_get(k_implementation_get_values(impl), "href"); char const *tag = k_dictionary_get(k_implementation_get_values(impl), "tag"); char const *path = k_dictionary_get(k_implementation_get_meta(impl), "name"); git_repository* repo = NULL; git_remote* origin = NULL; if (git_repository_open(&repo, path) == GIT_OK) { if (git_remote_load(&origin, repo, "origin") != GIT_OK) { git_repository_free(repo); return -1; } if (strcmp(url, git_remote_url(origin)) != 0) { giterr_set_str(GITERR_INVALID, "different origin"); git_repository_free(repo); return -1; } } else { if (git_repository_init(&repo, path, 0) != GIT_OK) { return -1; } if (git_remote_create(&origin, repo, "origin", url) != GIT_OK) { git_repository_free(repo); return -1; } } git_remote_set_update_fetchhead(origin, 0); git_remote_set_cred_acquire_cb(origin, cred_acquire, NULL); if (git_remote_connect(origin, GIT_DIRECTION_FETCH) != GIT_OK) { git_remote_free(origin); git_repository_free(repo); return -1; } if (git_remote_download(origin, transfer_progress, NULL) != GIT_OK) { git_remote_free(origin); git_repository_free(repo); return -1; } if (git_remote_update_tips(origin) != GIT_OK) { git_remote_free(origin); git_repository_free(repo); return -1; } git_object* object = NULL; if (git_revparse_single(&object, repo, tag) != GIT_OK) { git_remote_free(origin); git_repository_free(repo); return -1; } if (git_repository_set_head_detached(repo, git_object_id(object)) != GIT_OK) { git_object_free(object); git_remote_free(origin); git_repository_free(repo); return -1; } git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; checkout_opts.version = GIT_CHECKOUT_OPTS_VERSION; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; checkout_opts.progress_cb = checkout_progress; checkout_opts.progress_payload = NULL; if (git_checkout_tree(repo, object, &checkout_opts) != GIT_OK) { git_object_free(object); git_remote_free(origin); git_repository_free(repo); return -1; } git_object_free(object); git_remote_free(origin); git_repository_free(repo); return 0; }
void download(KImplementation const *impl, int requested, KError *error, void *ctx) { KDictionary const *values = k_implementation_get_values(impl); char const *href = k_dictionary_lookup(values, "href"); char const *tag = k_dictionary_lookup(values, "tag"); char const *path = k_implementation_get_name(impl); git_repository *repo = NULL; git_remote *origin = NULL; git_object *object = NULL; struct progress_data progress_data = {{0}}; git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; checkout_opts.version = GIT_CHECKOUT_OPTS_VERSION; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; checkout_opts.progress_cb = checkout_progress; checkout_opts.progress_payload = &progress_data; if (git_repository_open(&repo, path) == GIT_OK) { if (git_remote_load(&origin, repo, "origin") != GIT_OK) { k_error_set(error, giterr_last()->message); goto repository_free; } if (strcmp(git_remote_url(origin), href) != 0) { k_error_set(error, "different origin"); goto remote_free; } } else { if (git_repository_init(&repo, path, 0) != GIT_OK) { k_error_set(error, giterr_last()->message); return; } if (git_remote_create(&origin, repo, "origin", href) != GIT_OK) { k_error_set(error, giterr_last()->message); goto repository_free; } } git_remote_set_update_fetchhead(origin, 0); git_remote_set_cred_acquire_cb(origin, cred_acquire, NULL); if (git_remote_connect(origin, GIT_DIRECTION_FETCH) != GIT_OK) { k_error_set(error, giterr_last()->message); goto remote_free; } if (git_remote_download(origin, fetch_progress, &progress_data) != GIT_OK) { k_error_set(error, giterr_last()->message); goto remote_disconnect; } if (git_remote_update_tips(origin) != GIT_OK) { k_error_set(error, giterr_last()->message); goto remote_disconnect; } if (git_revparse_single(&object, repo, tag) != GIT_OK) { k_error_set(error, giterr_last()->message); goto remote_disconnect; } if (git_repository_set_head_detached(repo, git_object_id(object)) != GIT_OK) { k_error_set(error, giterr_last()->message); goto remote_disconnect; } if (git_checkout_tree(repo, object, &checkout_opts) != GIT_OK) { k_error_set(error, giterr_last()->message); } remote_disconnect: git_remote_disconnect(origin); remote_free: git_remote_free(origin); repository_free: git_repository_free(repo); }
/** 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; }
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_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; callbacks.transfer_progress = transfer_cb; 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)); git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_fetch(origin, NULL, NULL, 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)); git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(origin, NULL)); cl_git_pass(git_remote_prune(origin)); cl_git_pass(git_remote_update_tips(origin, NULL, NULL)); 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)); git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(origin, NULL)); cl_git_pass(git_remote_prune(origin)); cl_git_pass(git_remote_update_tips(origin, NULL, NULL)); 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); }
/** 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; }