diff options
Diffstat (limited to 'examples/network/fetch.c')
-rw-r--r-- | examples/network/fetch.c | 150 |
1 files changed, 92 insertions, 58 deletions
diff --git a/examples/network/fetch.c b/examples/network/fetch.c index f4a044984..6020ec6ec 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -3,23 +3,31 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <pthread.h> +#ifndef _WIN32 +# include <pthread.h> +# include <unistd.h> +#endif struct dl_data { git_remote *remote; - git_off_t *bytes; - git_indexer_stats *stats; int ret; int finished; }; +static void progress_cb(const char *str, int len, void *data) +{ + (void)data; + printf("remote: %.*s", len, str); + fflush(stdout); /* We don't have the \n to force the flush */ +} + static void *download(void *ptr) { struct dl_data *data = (struct dl_data *)ptr; // Connect to the remote end specifying that we want to fetch // information from it. - if (git_remote_connect(data->remote, GIT_DIR_FETCH) < 0) { + if (git_remote_connect(data->remote, GIT_DIRECTION_FETCH) < 0) { data->ret = -1; goto exit; } @@ -27,7 +35,7 @@ static void *download(void *ptr) // 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 (git_remote_download(data->remote, data->bytes, data->stats) < 0) { + if (git_remote_download(data->remote, NULL, NULL) < 0) { data->ret = -1; goto exit; } @@ -36,13 +44,13 @@ static void *download(void *ptr) exit: data->finished = 1; - pthread_exit(&data->ret); + return &data->ret; } -int update_cb(const char *refname, const git_oid *a, const git_oid *b) +static int update_cb(const char *refname, const git_oid *a, const git_oid *b, void *data) { - const char *action; char a_str[GIT_OID_HEXSZ+1], b_str[GIT_OID_HEXSZ+1]; + (void)data; git_oid_fmt(b_str, b); b_str[GIT_OID_HEXSZ] = '\0'; @@ -60,54 +68,80 @@ int update_cb(const char *refname, const git_oid *a, const git_oid *b) int fetch(git_repository *repo, int argc, char **argv) { - git_remote *remote = NULL; - git_off_t bytes = 0; - git_indexer_stats stats; - pthread_t worker; - struct dl_data data; - - // Figure out whether it's a named remote or a URL - printf("Fetching %s\n", argv[1]); - if (git_remote_load(&remote, repo, argv[1]) < 0) { - if (git_remote_new(&remote, repo, NULL, argv[1], NULL) < 0) - return -1; - } - - // Set up the information for the background worker thread - data.remote = remote; - data.bytes = &bytes; - data.stats = &stats; - data.ret = 0; - data.finished = 0; - memset(&stats, 0, sizeof(stats)); - - 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); - printf("\rReceived %d/%d objects in %d bytes", stats.processed, stats.total, bytes); - } while (!data.finished); - printf("\rReceived %d/%d objects in %d bytes\n", stats.processed, stats.total, 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, update_cb) < 0) - return -1; - - git_remote_free(remote); - - return 0; - -on_error: - git_remote_free(remote); - return -1; + 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_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; } |