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/network | |
| 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/network')
| -rw-r--r-- | examples/network/.gitignore | 1 | ||||
| -rw-r--r-- | examples/network/clone.c | 104 | ||||
| -rw-r--r-- | examples/network/fetch.c | 109 | ||||
| -rw-r--r-- | examples/network/git2.c | 87 | ||||
| -rw-r--r-- | examples/network/index-pack.c | 87 | ||||
| -rw-r--r-- | examples/network/ls-remote.c | 60 |
6 files changed, 0 insertions, 448 deletions
diff --git a/examples/network/.gitignore b/examples/network/.gitignore deleted file mode 100644 index 1b48e66ed..000000000 --- a/examples/network/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/git2 diff --git a/examples/network/clone.c b/examples/network/clone.c deleted file mode 100644 index 970e84ff9..000000000 --- a/examples/network/clone.c +++ /dev/null @@ -1,104 +0,0 @@ -#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 do_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; -} diff --git a/examples/network/fetch.c b/examples/network/fetch.c deleted file mode 100644 index bb5f1b189..000000000 --- a/examples/network/fetch.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "../common.h" - -static int 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 */ - return 0; -} - -/** - * This function gets called for each remote-tracking branch that gets - * updated. The message we output depends on whether it's a new one or - * an update. - */ -static int update_cb(const char *refname, const git_oid *a, const git_oid *b, void *data) -{ - 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'; - - if (git_oid_iszero(a)) { - printf("[new] %.20s %s\n", b_str, refname); - } else { - git_oid_fmt(a_str, a); - a_str[GIT_OID_HEXSZ] = '\0'; - printf("[updated] %.10s..%.10s %s\n", a_str, b_str, refname); - } - - return 0; -} - -/** - * This gets called during the download and indexing. 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. - */ -static int transfer_progress_cb(const git_transfer_progress *stats, void *payload) -{ - (void)payload; - - 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); - } - return 0; -} - -/** Entry point for this command */ -int fetch(git_repository *repo, int argc, char **argv) -{ - git_remote *remote = NULL; - const git_transfer_progress *stats; - 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) - goto on_error; - - /* 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) - goto on_error; - - /** - * 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; -} diff --git a/examples/network/git2.c b/examples/network/git2.c deleted file mode 100644 index 4fa28390c..000000000 --- a/examples/network/git2.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "../common.h" - -/* This part is not strictly libgit2-dependent, but you can use this - * as a starting point for a git-like tool */ - -typedef int (*git_cb)(git_repository *, int , char **); - -struct { - char *name; - git_cb fn; -} commands[] = { - {"ls-remote", ls_remote}, - {"fetch", fetch}, - {"clone", do_clone}, - {"index-pack", index_pack}, - { NULL, NULL} -}; - -static int run_command(git_cb fn, git_repository *repo, struct args_info args) -{ - int error; - - /* Run the command. If something goes wrong, print the error message to stderr */ - error = fn(repo, args.argc - args.pos, &args.argv[args.pos]); - if (error < 0) { - if (git_error_last() == NULL) - fprintf(stderr, "Error without message"); - else - fprintf(stderr, "Bad news:\n %s\n", git_error_last()->message); - } - - return !!error; -} - -int main(int argc, char **argv) -{ - int i; - int return_code = 1; - int error; - git_repository *repo; - struct args_info args = ARGS_INFO_INIT; - const char *git_dir = NULL; - - if (argc < 2) { - fprintf(stderr, "usage: %s <cmd> [repo]\n", argv[0]); - exit(EXIT_FAILURE); - } - - git_libgit2_init(); - - for (args.pos = 1; args.pos < args.argc; ++args.pos) { - char *a = args.argv[args.pos]; - - if (a[0] != '-') { - /* non-arg */ - break; - } else if (optional_str_arg(&git_dir, &args, "--git-dir", ".git")) { - continue; - } else if (!strcmp(a, "--")) { - /* arg separator */ - break; - } - } - - /* Before running the actual command, create an instance of the local - * repository and pass it to the function. */ - - error = git_repository_open(&repo, git_dir); - if (error < 0) - repo = NULL; - - for (i = 0; commands[i].name != NULL; ++i) { - if (!strcmp(args.argv[args.pos], commands[i].name)) { - return_code = run_command(commands[i].fn, repo, args); - goto shutdown; - } - } - - fprintf(stderr, "Command not found: %s\n", argv[1]); - -shutdown: - git_repository_free(repo); - - git_libgit2_shutdown(); - - return return_code; -} diff --git a/examples/network/index-pack.c b/examples/network/index-pack.c deleted file mode 100644 index 87445e439..000000000 --- a/examples/network/index-pack.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "../common.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#ifdef _WIN32 -# include <io.h> -# include <Windows.h> - -# define open _open -# define read _read -# define close _close - -#define ssize_t unsigned int -#else -# include <unistd.h> -#endif - -/* - * This could be run in the main loop whilst the application waits for - * the indexing to finish in a worker thread - */ -static int index_cb(const git_transfer_progress *stats, void *data) -{ - (void)data; - printf("\rProcessing %d of %d", stats->indexed_objects, stats->total_objects); - - return 0; -} - -int index_pack(git_repository *repo, int argc, char **argv) -{ - git_indexer *idx; - git_transfer_progress stats = {0, 0}; - int error; - char hash[GIT_OID_HEXSZ + 1] = {0}; - int fd; - ssize_t read_bytes; - char buf[512]; - - (void)repo; - - if (argc < 2) { - fprintf(stderr, "usage: %s index-pack <packfile>\n", argv[-1]); - return EXIT_FAILURE; - } - - if (git_indexer_new(&idx, ".", 0, NULL, NULL) < 0) { - puts("bad idx"); - return -1; - } - - if ((fd = open(argv[1], 0)) < 0) { - perror("open"); - return -1; - } - - do { - read_bytes = read(fd, buf, sizeof(buf)); - if (read_bytes < 0) - break; - - if ((error = git_indexer_append(idx, buf, read_bytes, &stats)) < 0) - goto cleanup; - - index_cb(&stats, NULL); - } while (read_bytes > 0); - - if (read_bytes < 0) { - error = -1; - perror("failed reading"); - goto cleanup; - } - - if ((error = git_indexer_commit(idx, &stats)) < 0) - goto cleanup; - - printf("\rIndexing %d of %d\n", stats.indexed_objects, stats.total_objects); - - git_oid_fmt(hash, git_indexer_hash(idx)); - puts(hash); - - cleanup: - close(fd); - git_indexer_free(idx); - return error; -} diff --git a/examples/network/ls-remote.c b/examples/network/ls-remote.c deleted file mode 100644 index 8181629b9..000000000 --- a/examples/network/ls-remote.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "../common.h" - -static int use_remote(git_repository *repo, char *name) -{ - git_remote *remote = NULL; - int error; - const git_remote_head **refs; - size_t refs_len, i; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - - /* Find the remote by name */ - error = git_remote_lookup(&remote, repo, name); - if (error < 0) { - error = git_remote_create_anonymous(&remote, repo, name); - if (error < 0) - goto cleanup; - } - - /** - * Connect to the remote and call the printing function for - * each of the remote references. - */ - callbacks.credentials = cred_acquire_cb; - - error = git_remote_connect(remote, GIT_DIRECTION_FETCH, &callbacks, NULL, NULL); - if (error < 0) - goto cleanup; - - /** - * Get the list of references on the remote and print out - * their name next to what they point to. - */ - if (git_remote_ls(&refs, &refs_len, remote) < 0) - goto cleanup; - - for (i = 0; i < refs_len; i++) { - char oid[GIT_OID_HEXSZ + 1] = {0}; - git_oid_fmt(oid, &refs[i]->oid); - printf("%s\t%s\n", oid, refs[i]->name); - } - -cleanup: - git_remote_free(remote); - return error; -} - -/** Entry point for this command */ -int ls_remote(git_repository *repo, int argc, char **argv) -{ - int error; - - if (argc < 2) { - fprintf(stderr, "usage: %s ls-remote <remote>\n", argv[-1]); - return EXIT_FAILURE; - } - - error = use_remote(repo, argv[1]); - - return error; -} |
