Hash :
b9e7e2b4
Author :
Date :
2012-12-14T13:46:45
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
#include "common.h"
#include <git2.h>
#include <git2/clone.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.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 = (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 void fetch_progress(const git_transfer_progress *stats, void *payload)
{
progress_data *pd = (progress_data*)payload;
pd->fetch_progress = *stats;
print_progress(pd);
}
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 *url, unsigned int allowed_types, void *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;
git_repository *cloned_repo = NULL;
git_remote *origin;
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;
checkout_opts.progress_cb = checkout_progress;
memset(&pd, 0, sizeof(pd));
checkout_opts.progress_payload = &pd;
// Create the origin remote, and set up for auth
error = git_remote_new(&origin, NULL, "origin", url, GIT_REMOTE_DEFAULT_FETCH);
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);
return error;
}
git_remote_set_cred_acquire_cb(origin, cred_acquire, NULL);
// Do the clone
clone_opts.checkout_opts = &checkout_opts;
clone_opts.fetch_progress_cb = &fetch_progress;
clone_opts.fetch_progress_payload = &pd;
error = git_clone(&cloned_repo, origin, path, &clone_opts);
git_remote_free(origin);
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;
}