mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-01 08:49:57 +00:00

The user is unable to derive the number of deltas in the pack, as that would require them to capture the stats exactly in the moment between download and final processing, which is abstracted away in the fetch. Capture these numbers for the user and expose them in the progress struct. The clone and fetch examples now also present this information to the user.
98 lines
2.8 KiB
C
98 lines
2.8 KiB
C
#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
|
|
|
|
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;
|
|
|
|
if (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 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_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_cb;
|
|
|
|
// 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;
|
|
}
|