Blame examples/network/clone.c

Packit ae9e2a
#include "common.h"
Packit ae9e2a
#include <git2.h>
Packit ae9e2a
#include <git2/clone.h>
Packit ae9e2a
#include <stdio.h>
Packit ae9e2a
#include <stdlib.h>
Packit ae9e2a
#include <string.h>
Packit ae9e2a
#ifndef _WIN32
Packit ae9e2a
# include <pthread.h>
Packit ae9e2a
# include <unistd.h>
Packit ae9e2a
#endif
Packit ae9e2a
Packit ae9e2a
typedef struct progress_data {
Packit ae9e2a
	git_transfer_progress fetch_progress;
Packit ae9e2a
	size_t completed_steps;
Packit ae9e2a
	size_t total_steps;
Packit ae9e2a
	const char *path;
Packit ae9e2a
} progress_data;
Packit ae9e2a
Packit ae9e2a
static void print_progress(const progress_data *pd)
Packit ae9e2a
{
Packit ae9e2a
	int network_percent = pd->fetch_progress.total_objects > 0 ?
Packit ae9e2a
		(100*pd->fetch_progress.received_objects) / pd->fetch_progress.total_objects :
Packit ae9e2a
		0;
Packit ae9e2a
	int index_percent = pd->fetch_progress.total_objects > 0 ?
Packit ae9e2a
		(100*pd->fetch_progress.indexed_objects) / pd->fetch_progress.total_objects :
Packit ae9e2a
		0;
Packit ae9e2a
Packit ae9e2a
	int checkout_percent = pd->total_steps > 0
Packit ae9e2a
		? (100 * pd->completed_steps) / pd->total_steps
Packit ae9e2a
		: 0;
Packit ae9e2a
	int kbytes = pd->fetch_progress.received_bytes / 1024;
Packit ae9e2a
Packit ae9e2a
	if (pd->fetch_progress.total_objects &&
Packit ae9e2a
		pd->fetch_progress.received_objects == pd->fetch_progress.total_objects) {
Packit ae9e2a
		printf("Resolving deltas %d/%d\r",
Packit ae9e2a
		       pd->fetch_progress.indexed_deltas,
Packit ae9e2a
		       pd->fetch_progress.total_deltas);
Packit ae9e2a
	} else {
Packit ae9e2a
		printf("net %3d%% (%4d kb, %5d/%5d)  /  idx %3d%% (%5d/%5d)  /  chk %3d%% (%4" PRIuZ "/%4" PRIuZ ") %s\n",
Packit ae9e2a
		   network_percent, kbytes,
Packit ae9e2a
		   pd->fetch_progress.received_objects, pd->fetch_progress.total_objects,
Packit ae9e2a
		   index_percent, pd->fetch_progress.indexed_objects, pd->fetch_progress.total_objects,
Packit ae9e2a
		   checkout_percent,
Packit ae9e2a
		   pd->completed_steps, pd->total_steps,
Packit ae9e2a
		   pd->path);
Packit ae9e2a
	}
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
static int sideband_progress(const char *str, int len, void *payload)
Packit ae9e2a
{
Packit ae9e2a
	(void)payload; // unused
Packit ae9e2a
Packit ae9e2a
	printf("remote: %.*s", len, str);
Packit ae9e2a
	fflush(stdout);
Packit ae9e2a
	return 0;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
static int fetch_progress(const git_transfer_progress *stats, void *payload)
Packit ae9e2a
{
Packit ae9e2a
	progress_data *pd = (progress_data*)payload;
Packit ae9e2a
	pd->fetch_progress = *stats;
Packit ae9e2a
	print_progress(pd);
Packit ae9e2a
	return 0;
Packit ae9e2a
}
Packit ae9e2a
static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload)
Packit ae9e2a
{
Packit ae9e2a
	progress_data *pd = (progress_data*)payload;
Packit ae9e2a
	pd->completed_steps = cur;
Packit ae9e2a
	pd->total_steps = tot;
Packit ae9e2a
	pd->path = path;
Packit ae9e2a
	print_progress(pd);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
Packit ae9e2a
int do_clone(git_repository *repo, int argc, char **argv)
Packit ae9e2a
{
Packit ae9e2a
	progress_data pd = {{0}};
Packit ae9e2a
	git_repository *cloned_repo = NULL;
Packit ae9e2a
	git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
Packit ae9e2a
	git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
Packit ae9e2a
	const char *url = argv[1];
Packit ae9e2a
	const char *path = argv[2];
Packit ae9e2a
	int error;
Packit ae9e2a
Packit ae9e2a
	(void)repo; // unused
Packit ae9e2a
Packit ae9e2a
	// Validate args
Packit ae9e2a
	if (argc < 3) {
Packit ae9e2a
		printf ("USAGE: %s <url> <path>\n", argv[0]);
Packit ae9e2a
		return -1;
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	// Set up options
Packit ae9e2a
	checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
Packit ae9e2a
	checkout_opts.progress_cb = checkout_progress;
Packit ae9e2a
	checkout_opts.progress_payload = &pd;
Packit ae9e2a
	clone_opts.checkout_opts = checkout_opts;
Packit ae9e2a
	clone_opts.fetch_opts.callbacks.sideband_progress = sideband_progress;
Packit ae9e2a
	clone_opts.fetch_opts.callbacks.transfer_progress = &fetch_progress;
Packit ae9e2a
	clone_opts.fetch_opts.callbacks.credentials = cred_acquire_cb;
Packit ae9e2a
	clone_opts.fetch_opts.callbacks.payload = &pd;
Packit ae9e2a
Packit ae9e2a
	// Do the clone
Packit ae9e2a
	error = git_clone(&cloned_repo, url, path, &clone_opts);
Packit ae9e2a
	printf("\n");
Packit ae9e2a
	if (error != 0) {
Packit ae9e2a
		const git_error *err = giterr_last();
Packit ae9e2a
		if (err) printf("ERROR %d: %s\n", err->klass, err->message);
Packit ae9e2a
		else printf("ERROR %d: no detailed info\n", error);
Packit ae9e2a
	}
Packit ae9e2a
	else if (cloned_repo) git_repository_free(cloned_repo);
Packit ae9e2a
	return error;
Packit ae9e2a
}