diff options
author | Patrick Steinhardt <ps@pks.im> | 2019-01-24 11:31:49 +0100 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2019-02-15 12:06:54 +0100 |
commit | ead10785dcd9e7599a52a0349a69c113c76e650d (patch) | |
tree | 14c30c430befd05eb160108fe49a14d72faeb3d7 /examples/clone.c | |
parent | 7562422ab9310b81142986f69964194f491948cc (diff) | |
download | libgit2-ead10785dcd9e7599a52a0349a69c113c76e650d.tar.gz |
examples: create common lg2 executable
Inside of our networking example code, we have a git2 executable
that acts as an entry point to all the different network
examples. As such, it is kind of the same like the normal git(1)
executable in that it simply arbitrates to the respective
subcommands.
Let's extend this approach and merge all examples into a single
standalone lg2 executable. Instead of building an executable
for all the existing examples we have, we now bundle them all
inside of the lg2 one and let them be callable via subcommands.
In the process, we can get rid of duplicated library
initialization, deinitialization and repository discovery code.
Instead of having each subcommand handle these on its own, we
simply do it inside of the single main function now.
Diffstat (limited to 'examples/clone.c')
-rw-r--r-- | examples/clone.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/examples/clone.c b/examples/clone.c new file mode 100644 index 000000000..fc121bc1e --- /dev/null +++ b/examples/clone.c @@ -0,0 +1,104 @@ +#include "common.h" + +typedef struct progress_data { + git_transfer_progress fetch_progress; + size_t completed_steps; + size_t total_steps; + const char *path; +} progress_data; + +static void print_progress(const progress_data *pd) +{ + int network_percent = pd->fetch_progress.total_objects > 0 ? + (100*pd->fetch_progress.received_objects) / pd->fetch_progress.total_objects : + 0; + int index_percent = pd->fetch_progress.total_objects > 0 ? + (100*pd->fetch_progress.indexed_objects) / pd->fetch_progress.total_objects : + 0; + + int checkout_percent = pd->total_steps > 0 + ? (100 * pd->completed_steps) / pd->total_steps + : 0; + int kbytes = pd->fetch_progress.received_bytes / 1024; + + if (pd->fetch_progress.total_objects && + pd->fetch_progress.received_objects == pd->fetch_progress.total_objects) { + printf("Resolving deltas %d/%d\r", + pd->fetch_progress.indexed_deltas, + pd->fetch_progress.total_deltas); + } else { + printf("net %3d%% (%4d kb, %5d/%5d) / idx %3d%% (%5d/%5d) / chk %3d%% (%4" PRIuZ "/%4" PRIuZ ") %s\n", + network_percent, kbytes, + pd->fetch_progress.received_objects, pd->fetch_progress.total_objects, + index_percent, pd->fetch_progress.indexed_objects, pd->fetch_progress.total_objects, + checkout_percent, + pd->completed_steps, pd->total_steps, + pd->path); + } +} + +static int sideband_progress(const char *str, int len, void *payload) +{ + (void)payload; /* unused */ + + printf("remote: %.*s", len, str); + fflush(stdout); + return 0; +} + +static int fetch_progress(const git_transfer_progress *stats, void *payload) +{ + progress_data *pd = (progress_data*)payload; + pd->fetch_progress = *stats; + print_progress(pd); + return 0; +} +static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload) +{ + progress_data *pd = (progress_data*)payload; + pd->completed_steps = cur; + pd->total_steps = tot; + pd->path = path; + print_progress(pd); +} + + +int lg2_clone(git_repository *repo, int argc, char **argv) +{ + progress_data pd = {{0}}; + git_repository *cloned_repo = NULL; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; + const char *url = argv[1]; + const char *path = argv[2]; + int error; + + (void)repo; /* unused */ + + /* Validate args */ + if (argc < 3) { + printf ("USAGE: %s <url> <path>\n", argv[0]); + return -1; + } + + /* Set up options */ + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + checkout_opts.progress_cb = checkout_progress; + checkout_opts.progress_payload = &pd; + clone_opts.checkout_opts = checkout_opts; + clone_opts.fetch_opts.callbacks.sideband_progress = sideband_progress; + clone_opts.fetch_opts.callbacks.transfer_progress = &fetch_progress; + clone_opts.fetch_opts.callbacks.credentials = cred_acquire_cb; + clone_opts.fetch_opts.callbacks.payload = &pd; + + /* Do the clone */ + error = git_clone(&cloned_repo, url, path, &clone_opts); + printf("\n"); + if (error != 0) { + const git_error *err = git_error_last(); + if (err) printf("ERROR %d: %s\n", err->klass, err->message); + else printf("ERROR %d: no detailed info\n", error); + } + else if (cloned_repo) git_repository_free(cloned_repo); + return error; +} |