From cf66c4748c30249ac26b961a4d719b83ea42fd60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 6 May 2015 12:26:05 +0200 Subject: [PATCH 1/3] examples: show the sideband progress on clone This lets us see what the server (or libgit2 locally) is doing, rather than having to stare at a non-moving screen. --- examples/network/clone.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/network/clone.c b/examples/network/clone.c index 37e373d5a..b2d80ed01 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -46,6 +46,13 @@ static void print_progress(const progress_data *pd) } } +static int sideband_progress(const char *str, int len, void *payload) +{ + 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; @@ -86,6 +93,7 @@ int do_clone(git_repository *repo, int argc, char **argv) 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; From 8cec2b8ae9b1fdf4638cb405cbd8c17454c1c076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 6 May 2015 12:28:01 +0200 Subject: [PATCH 2/3] local: send the packbuilder progress via the sideband Set a callback for the packbuilder so we can send the sideband messages to the caller, formatting them as git would. --- src/transports/local.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/transports/local.c b/src/transports/local.c index 305c71bf0..9dd448681 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -502,6 +502,33 @@ static int foreach_cb(void *buf, size_t len, void *payload) } static const char *counting_objects_fmt = "Counting objects %d\r"; +static const char *compressing_objects_fmt = "Compressing objects: %.0f%% (%d/%d)"; + +static int local_counting(int stage, unsigned int current, unsigned int total, void *payload) +{ + git_buf progress_info = GIT_BUF_INIT; + transport_local *t = payload; + + if (!t->progress_cb) + return 0; + + if (stage == GIT_PACKBUILDER_ADDING_OBJECTS) { + git_buf_printf(&progress_info, counting_objects_fmt, current); + } else if (stage == GIT_PACKBUILDER_DELTAFICATION) { + float perc = (((float) current) / total) * 100; + git_buf_printf(&progress_info, compressing_objects_fmt, perc, current, total); + if (current == total) + git_buf_printf(&progress_info, ", done\n"); + else + git_buf_putc(&progress_info, '\r'); + + } + + if (git_buf_oom(&progress_info)) + return -1; + + return t->progress_cb(git_buf_cstr(&progress_info), git_buf_len(&progress_info), t->message_cb_payload); +} static int local_download_pack( git_transport *transport, @@ -527,6 +554,8 @@ static int local_download_pack( if ((error = git_packbuilder_new(&pack, t->repo)) < 0) goto cleanup; + git_packbuilder_set_callbacks(pack, local_counting, t); + stats->total_objects = 0; stats->indexed_objects = 0; stats->received_objects = 0; From 3c337a5d3720f524387307bf443e7d7c6380a2e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 6 May 2015 13:09:00 +0200 Subject: [PATCH 3/3] packbuilder: report progress during deltification This is useful to send to the client while we're performing the work. The reporting function has a force parameter which makes sure that we do send out the message of 100% completed, even if this comes before the next udpate window. --- src/pack-objects.c | 28 ++++++++++++++++++++++++++++ src/pack-objects.h | 1 + 2 files changed, 29 insertions(+) diff --git a/src/pack-objects.c b/src/pack-objects.c index 932764698..e287e3306 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -893,6 +893,29 @@ static unsigned long free_unpacked(struct unpacked *n) return freed_mem; } +static int report_delta_progress(git_packbuilder *pb, uint32_t count, bool force) +{ + int ret; + + if (pb->progress_cb) { + double current_time = git__timer(); + double elapsed = current_time - pb->last_progress_report_time; + + if (force || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) { + pb->last_progress_report_time = current_time; + + ret = pb->progress_cb( + GIT_PACKBUILDER_DELTAFICATION, + count, pb->nr_objects, pb->progress_cb_payload); + + if (ret) + return giterr_set_after_callback(ret); + } + } + + return 0; +} + static int find_deltas(git_packbuilder *pb, git_pobject **list, unsigned int *list_size, unsigned int window, int depth) @@ -918,6 +941,9 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list, break; } + pb->nr_deltified += 1; + report_delta_progress(pb, pb->nr_deltified, false); + po = *list++; (*list_size)--; git_packbuilder__progress_unlock(pb); @@ -1290,6 +1316,8 @@ static int prepare_pack(git_packbuilder *pb) } } + report_delta_progress(pb, pb->nr_objects, true); + pb->done = true; git__free(delta_list); return 0; diff --git a/src/pack-objects.h b/src/pack-objects.h index 9af5c0b09..82dea81f5 100644 --- a/src/pack-objects.h +++ b/src/pack-objects.h @@ -65,6 +65,7 @@ struct git_packbuilder { git_zstream zstream; uint32_t nr_objects, + nr_deltified, nr_alloc, nr_written, nr_remaining;