Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
0
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);
}
Пример #4
0
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;
}
Пример #5
0
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);
}
Пример #6
0
/**
 * 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;
}
Пример #7
0
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);
}
Пример #8
0
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);
}
Пример #9
0
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;
}
Пример #10
0
Файл: fetch.c Проект: bxio/.atom
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;
}
Пример #11
0
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;
}
Пример #12
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);
  }
Пример #13
0
/** 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;
}
Пример #14
0
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);
}
Пример #15
0
/** 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;
}