Hash :
5c46937b
Author :
Date :
2013-02-26T09:00:37
Give props to Martin Pool Martin Pool was the original author of the code referenced in the clone example. Make note that he's given his permission and also give him the proper credit.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
#include "common.h"
#include <git2.h>
#include <git2/clone.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
# include <pthread.h>
# include <unistd.h>
#endif
/* Shamelessly borrowed from http://stackoverflow.com/questions/3417837/
* with permission of the original author, Martin Pool.
* http://sourcefrog.net/weblog/software/languages/C/unused.html
*/
#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#elif defined(__LCLINT__)
# define UNUSED(x) /*@unused@*/ x
#else
# define UNUSED(x) x
#endif
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 = (100*pd->fetch_progress.received_objects) / pd->fetch_progress.total_objects;
int index_percent = (100*pd->fetch_progress.indexed_objects) / pd->fetch_progress.total_objects;
int checkout_percent = pd->total_steps > 0
? (100 * pd->completed_steps) / pd->total_steps
: 0.f;
int kbytes = pd->fetch_progress.received_bytes / 1024;
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 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);
}
static int cred_acquire(git_cred **out,
const char * UNUSED(url),
const char * UNUSED(username_from_url),
unsigned int UNUSED(allowed_types),
void * UNUSED(payload))
{
char username[128] = {0};
char password[128] = {0};
printf("Username: ");
scanf("%s", username);
/* Yup. Right there on your terminal. Careful where you copy/paste output. */
printf("Password: ");
scanf("%s", password);
return git_cred_userpass_plaintext_new(out, username, password);
}
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_opts checkout_opts = GIT_CHECKOUT_OPTS_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_CREATE;
checkout_opts.progress_cb = checkout_progress;
checkout_opts.progress_payload = &pd;
clone_opts.checkout_opts = checkout_opts;
clone_opts.fetch_progress_cb = &fetch_progress;
clone_opts.fetch_progress_payload = &pd;
clone_opts.cred_acquire_cb = cred_acquire;
// Do the clone
error = git_clone(&cloned_repo, url, path, &clone_opts);
printf("\n");
if (error != 0) {
const git_error *err = giterr_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;
}