From ebe8fa738dcf6911fe520adce0cfa0cb26dee5e2 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 4 Nov 2007 00:22:42 -0400 Subject: fix display overlap between remote and local progress It is possible for the remote summary line to be displayed over the local progress display line, and therefore that local progress gets bumped to the next line. However, if the progress line is long enough, it might not be entirely overwritten by the remote summary line. This creates a messed up display such as: remote: Total 310 (delta 160), reused 178 (delta 112)iB/s Receiving objects: 100% (310/310), 379.98 KiB | 136 KiB/s, done. So we have to clear the screen line before displaying the remote message to make sure the local progress is not visible anymore on the first line. Yet some Git versions on the remote side might be sending updates to the same line and terminate it with \r, and a separate packet with a single \n might be sent later when the progress display is done. This means the screen line must *not* be cleared in that case. Since the sideband code already has to figure out line breaks in the received packet to properly prepend the "remote:" prefix, we can easily determine if the remote line about to be displayed is empty. Only when it is not then a proper suffix is inserted before the \r or \n to clear the end of the screen line. Also some magic constants related to the prefix length have been replaced with a variable, making it similar to the suffix length handling. Since gcc is smart enough to detect that the variable is constant there is no impact on the generated code. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- sideband.c | 51 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/sideband.c b/sideband.c index ab8a1e990..58edea68e 100644 --- a/sideband.c +++ b/sideband.c @@ -11,13 +11,19 @@ * stream, aka "verbose"). A message over band #3 is a signal that * the remote died unexpectedly. A flush() concludes the stream. */ + +#define PREFIX "remote:" +#define SUFFIX "\e[K" /* change to " " if ANSI sequences don't work */ + int recv_sideband(const char *me, int in_stream, int out, int err) { - char buf[7 + LARGE_PACKET_MAX + 1]; - strcpy(buf, "remote:"); + unsigned pf = strlen(PREFIX); + unsigned sf = strlen(SUFFIX); + char buf[pf + LARGE_PACKET_MAX + sf + 1]; + memcpy(buf, PREFIX, pf); while (1) { int band, len; - len = packet_read_line(in_stream, buf+7, LARGE_PACKET_MAX); + len = packet_read_line(in_stream, buf + pf, LARGE_PACKET_MAX); if (len == 0) break; if (len < 1) { @@ -25,35 +31,52 @@ int recv_sideband(const char *me, int in_stream, int out, int err) safe_write(err, buf, len); return SIDEBAND_PROTOCOL_ERROR; } - band = buf[7] & 0xff; + band = buf[pf] & 0xff; len--; switch (band) { case 3: - buf[7] = ' '; - buf[8+len] = '\n'; - safe_write(err, buf, 8+len+1); + buf[pf] = ' '; + buf[pf+1+len] = '\n'; + safe_write(err, buf, pf+1+len+1); return SIDEBAND_REMOTE_ERROR; case 2: - buf[7] = ' '; - len += 8; + buf[pf] = ' '; + len += pf+1; while (1) { - int brk = 8; + int brk = pf+1; + + /* Break the buffer into separate lines. */ while (brk < len) { brk++; if (buf[brk-1] == '\n' || buf[brk-1] == '\r') break; } - safe_write(err, buf, brk); + + /* + * Let's insert a suffix to clear the end + * of the screen line, but only if current + * line data actually contains something. + */ + if (brk > pf+1 + 1) { + char save[sf]; + memcpy(save, buf + brk, sf); + buf[brk + sf - 1] = buf[brk - 1]; + memcpy(buf + brk - 1, SUFFIX, sf); + safe_write(err, buf, brk + sf); + memcpy(buf + brk, save, sf); + } else + safe_write(err, buf, brk); + if (brk < len) { - memmove(buf + 8, buf + brk, len - brk); - len = len - brk + 8; + memmove(buf + pf+1, buf + brk, len - brk); + len = len - brk + pf+1; } else break; } continue; case 1: - safe_write(out, buf+8, len); + safe_write(out, buf + pf+1, len); continue; default: len = sprintf(buf, -- cgit v1.2.1 From 0d8aafd25271c8d1cf185019437e21362edc1bc7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 4 Nov 2007 20:07:29 -0500 Subject: sideband.c: ESC is spelled '\033' not '\e' for portability. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- sideband.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sideband.c b/sideband.c index 58edea68e..756bbc28d 100644 --- a/sideband.c +++ b/sideband.c @@ -13,7 +13,7 @@ */ #define PREFIX "remote:" -#define SUFFIX "\e[K" /* change to " " if ANSI sequences don't work */ +#define SUFFIX "\033[K" /* change to " " if ANSI sequences don't work */ int recv_sideband(const char *me, int in_stream, int out, int err) { -- cgit v1.2.1 From 218558af599c01e5dec17a7399d9188a76c50203 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 4 Nov 2007 22:15:41 -0500 Subject: make display of total transferred more accurate The throughput display needs a delay period before accounting and displaying anything. Yet it might be called after some amount of data has already been transferred. The display of total data is therefore accounted late and therefore smaller than the reality. Let's call display_throughput() with an absolute amount of transferred data instead of a relative number, and let the throughput code find the relative amount of data by itself as needed. This way the displayed total is always exact. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- csum-file.c | 4 +++- csum-file.h | 1 + index-pack.c | 4 ++-- progress.c | 46 ++++++++++++++++++++++------------------------ progress.h | 2 +- 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/csum-file.c b/csum-file.c index 3729e73e1..b445e6a2e 100644 --- a/csum-file.c +++ b/csum-file.c @@ -18,7 +18,8 @@ static void sha1flush(struct sha1file *f, unsigned int count) for (;;) { int ret = xwrite(f->fd, buf, count); if (ret > 0) { - display_throughput(f->tp, ret); + f->total += ret; + display_throughput(f->tp, f->total); buf = (char *) buf + ret; count -= ret; if (count) @@ -101,6 +102,7 @@ struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp f->fd = fd; f->error = 0; f->offset = 0; + f->total = 0; f->tp = tp; f->do_crc = 0; SHA1_Init(&f->ctx); diff --git a/csum-file.h b/csum-file.h index 4d1b23129..a38cc3a2d 100644 --- a/csum-file.h +++ b/csum-file.h @@ -8,6 +8,7 @@ struct sha1file { int fd, error; unsigned int offset, namelen; SHA_CTX ctx; + off_t total; struct progress *tp; char name[PATH_MAX]; int do_crc; diff --git a/index-pack.c b/index-pack.c index 715a5bb7a..581a7f565 100644 --- a/index-pack.c +++ b/index-pack.c @@ -87,9 +87,9 @@ static void *fill(int min) die("early EOF"); die("read error on input: %s", strerror(errno)); } - if (from_stdin) - display_throughput(progress, ret); input_len += ret; + if (from_stdin) + display_throughput(progress, consumed_bytes + input_len); } while (input_len < min); return input_buffer; } diff --git a/progress.c b/progress.c index 3f6a602a5..a963bd8bf 100644 --- a/progress.c +++ b/progress.c @@ -14,11 +14,10 @@ #define TP_IDX_MAX 8 struct throughput { + off_t prev_total; struct timeval prev_tv; - off_t total; - unsigned long count; - unsigned long avg_bytes; - unsigned long last_bytes[TP_IDX_MAX]; + unsigned int avg_bytes; + unsigned int last_bytes[TP_IDX_MAX]; unsigned int avg_misecs; unsigned int last_misecs[TP_IDX_MAX]; unsigned int idx; @@ -110,7 +109,7 @@ static int display(struct progress *progress, unsigned n, int done) return 0; } -void display_throughput(struct progress *progress, unsigned long n) +void display_throughput(struct progress *progress, off_t total) { struct throughput *tp; struct timeval tv; @@ -124,14 +123,13 @@ void display_throughput(struct progress *progress, unsigned long n) if (!tp) { progress->throughput = tp = calloc(1, sizeof(*tp)); - if (tp) + if (tp) { + tp->prev_total = total; tp->prev_tv = tv; + } return; } - tp->total += n; - tp->count += n; - /* * We have x = bytes and y = microsecs. We want z = KiB/s: * @@ -152,37 +150,37 @@ void display_throughput(struct progress *progress, unsigned long n) if (misecs > 512) { int l = sizeof(tp->display); + unsigned int count = total - tp->prev_total; + tp->prev_total = total; tp->prev_tv = tv; - tp->avg_bytes += tp->count; + tp->avg_bytes += count; tp->avg_misecs += misecs; - if (tp->total > 1 << 30) { + if (total > 1 << 30) { l -= snprintf(tp->display, l, ", %u.%2.2u GiB", - (int)(tp->total >> 30), - (int)(tp->total & ((1 << 30) - 1)) / 10737419); - } else if (tp->total > 1 << 20) { + (int)(total >> 30), + (int)(total & ((1 << 30) - 1)) / 10737419); + } else if (total > 1 << 20) { l -= snprintf(tp->display, l, ", %u.%2.2u MiB", - (int)(tp->total >> 20), - ((int)(tp->total & ((1 << 20) - 1)) + (int)(total >> 20), + ((int)(total & ((1 << 20) - 1)) * 100) >> 20); - } else if (tp->total > 1 << 10) { + } else if (total > 1 << 10) { l -= snprintf(tp->display, l, ", %u.%2.2u KiB", - (int)(tp->total >> 10), - ((int)(tp->total & ((1 << 10) - 1)) + (int)(total >> 10), + ((int)(total & ((1 << 10) - 1)) * 100) >> 10); } else { - l -= snprintf(tp->display, l, ", %u bytes", - (int)tp->total); + l -= snprintf(tp->display, l, ", %u bytes", (int)total); } snprintf(tp->display + sizeof(tp->display) - l, l, - " | %lu KiB/s", tp->avg_bytes / tp->avg_misecs); + " | %u KiB/s", tp->avg_bytes / tp->avg_misecs); tp->avg_bytes -= tp->last_bytes[tp->idx]; tp->avg_misecs -= tp->last_misecs[tp->idx]; - tp->last_bytes[tp->idx] = tp->count; + tp->last_bytes[tp->idx] = count; tp->last_misecs[tp->idx] = misecs; tp->idx = (tp->idx + 1) % TP_IDX_MAX; - tp->count = 0; if (progress->last_value != -1 && progress_update) display(progress, progress->last_value, 0); diff --git a/progress.h b/progress.h index 61cb68dfa..3912969e6 100644 --- a/progress.h +++ b/progress.h @@ -3,7 +3,7 @@ struct progress; -void display_throughput(struct progress *progress, unsigned long n); +void display_throughput(struct progress *progress, off_t total); int display_progress(struct progress *progress, unsigned n); struct progress *start_progress(const char *title, unsigned total); struct progress *start_progress_delay(const char *title, unsigned total, -- cgit v1.2.1 From 9ef4272bea94b022aa84372c06e211bccd5f8a54 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 4 Nov 2007 15:05:45 -0800 Subject: git-fetch: be even quieter. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- builtin-fetch.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 5f5b59bfd..e65690f25 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -152,6 +152,7 @@ static int s_update_ref(const char *action, } #define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) +#define REFCOL_WIDTH 10 static int update_local_ref(struct ref *ref, const char *remote, @@ -181,8 +182,9 @@ static int update_local_ref(struct ref *ref, if (!hashcmp(ref->old_sha1, ref->new_sha1)) { if (verbose) - sprintf(display, "= %-*s %s -> %s", SUMMARY_WIDTH, - "[up to date]", remote, pretty_ref); + sprintf(display, "= %-*s %-*s -> %s", SUMMARY_WIDTH, + "[up to date]", REFCOL_WIDTH, remote, + pretty_ref); return 0; } @@ -194,15 +196,17 @@ static int update_local_ref(struct ref *ref, * If this is the head, and it's not okay to update * the head, and the old value of the head isn't empty... */ - sprintf(display, "! %-*s %s -> %s (can't fetch in current branch)", - SUMMARY_WIDTH, "[rejected]", remote, pretty_ref); + sprintf(display, "! %-*s %-*s -> %s (can't fetch in current branch)", + SUMMARY_WIDTH, "[rejected]", REFCOL_WIDTH, remote, + pretty_ref); return 1; } if (!is_null_sha1(ref->old_sha1) && !prefixcmp(ref->name, "refs/tags/")) { - sprintf(display, "- %-*s %s -> %s", - SUMMARY_WIDTH, "[tag update]", remote, pretty_ref); + sprintf(display, "- %-*s %-*s -> %s", + SUMMARY_WIDTH, "[tag update]", REFCOL_WIDTH, remote, + pretty_ref); return s_update_ref("updating tag", ref, 0); } @@ -220,8 +224,8 @@ static int update_local_ref(struct ref *ref, what = "[new branch]"; } - sprintf(display, "* %-*s %s -> %s", - SUMMARY_WIDTH, what, remote, pretty_ref); + sprintf(display, "* %-*s %-*s -> %s", SUMMARY_WIDTH, what, + REFCOL_WIDTH, remote, pretty_ref); return s_update_ref(msg, ref, 0); } @@ -230,20 +234,21 @@ static int update_local_ref(struct ref *ref, strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV)); strcat(quickref, ".."); strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV)); - sprintf(display, " %-*s %s -> %s (fast forward)", - SUMMARY_WIDTH, quickref, remote, pretty_ref); + sprintf(display, " %-*s %-*s -> %s", SUMMARY_WIDTH, quickref, + REFCOL_WIDTH, remote, pretty_ref); return s_update_ref("fast forward", ref, 1); } else if (force || ref->force) { char quickref[84]; strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV)); strcat(quickref, "..."); strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV)); - sprintf(display, "+ %-*s %s -> %s (forced update)", - SUMMARY_WIDTH, quickref, remote, pretty_ref); + sprintf(display, "+ %-*s %-*s -> %s (forced update)", + SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote, pretty_ref); return s_update_ref("forced-update", ref, 1); } else { - sprintf(display, "! %-*s %s -> %s (non fast forward)", - SUMMARY_WIDTH, "[rejected]", remote, pretty_ref); + sprintf(display, "! %-*s %-*s -> %s (non fast forward)", + SUMMARY_WIDTH, "[rejected]", REFCOL_WIDTH, remote, + pretty_ref); return 1; } } -- cgit v1.2.1 From ec640ed1cf1d62730555705ec18b785c43e81f62 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 4 Nov 2007 22:54:50 -0500 Subject: remove dead code from the csum-file interface The provided name argument is always constant and valid in every caller's context, so no need to have an array of PATH_MAX chars to copy it into when a simple pointer will do. Unfortunately that means getting rid of wascally wabbits too. The 'error' field is also unused. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- csum-file.c | 14 ++------------ csum-file.h | 6 +++--- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/csum-file.c b/csum-file.c index b445e6a2e..9728a9954 100644 --- a/csum-file.c +++ b/csum-file.c @@ -88,22 +88,12 @@ struct sha1file *sha1fd(int fd, const char *name) struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp) { - struct sha1file *f; - unsigned len; - - f = xmalloc(sizeof(*f)); - - len = strlen(name); - if (len >= PATH_MAX) - die("you wascally wabbit, you"); - f->namelen = len; - memcpy(f->name, name, len+1); - + struct sha1file *f = xmalloc(sizeof(*f)); f->fd = fd; - f->error = 0; f->offset = 0; f->total = 0; f->tp = tp; + f->name = name; f->do_crc = 0; SHA1_Init(&f->ctx); return f; diff --git a/csum-file.h b/csum-file.h index a38cc3a2d..1af76562f 100644 --- a/csum-file.h +++ b/csum-file.h @@ -5,12 +5,12 @@ struct progress; /* A SHA1-protected file */ struct sha1file { - int fd, error; - unsigned int offset, namelen; + int fd; + unsigned int offset; SHA_CTX ctx; off_t total; struct progress *tp; - char name[PATH_MAX]; + const char *name; int do_crc; uint32_t crc32; unsigned char buffer[8192]; -- cgit v1.2.1 From 53ed7b5a5d7a0ad2ffafd4a4ba4a7861f5db624e Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 6 Nov 2007 16:30:28 -0500 Subject: make display of total transferred fully accurate The minimum delay of 1/2 sec between successive throughput updates might not have been elapsed when display_throughput() is called for the last time, potentially making the display of total transferred bytes not right when progress is said to be done. Let's force an update of the throughput display as well when the progress is complete. As a side effect, the total transferred will always be displayed even if the actual transfer rate doesn't have time to kickin. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- progress.c | 64 ++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/progress.c b/progress.c index a963bd8bf..0700dcf24 100644 --- a/progress.c +++ b/progress.c @@ -14,11 +14,12 @@ #define TP_IDX_MAX 8 struct throughput { + off_t curr_total; off_t prev_total; struct timeval prev_tv; unsigned int avg_bytes; - unsigned int last_bytes[TP_IDX_MAX]; unsigned int avg_misecs; + unsigned int last_bytes[TP_IDX_MAX]; unsigned int last_misecs[TP_IDX_MAX]; unsigned int idx; char display[32]; @@ -109,6 +110,30 @@ static int display(struct progress *progress, unsigned n, int done) return 0; } +static void throughput_string(struct throughput *tp, off_t total, + unsigned int rate) +{ + int l = sizeof(tp->display); + if (total > 1 << 30) { + l -= snprintf(tp->display, l, ", %u.%2.2u GiB", + (int)(total >> 30), + (int)(total & ((1 << 30) - 1)) / 10737419); + } else if (total > 1 << 20) { + l -= snprintf(tp->display, l, ", %u.%2.2u MiB", + (int)(total >> 20), + ((int)(total & ((1 << 20) - 1)) * 100) >> 20); + } else if (total > 1 << 10) { + l -= snprintf(tp->display, l, ", %u.%2.2u KiB", + (int)(total >> 10), + ((int)(total & ((1 << 10) - 1)) * 100) >> 10); + } else { + l -= snprintf(tp->display, l, ", %u bytes", (int)total); + } + if (rate) + snprintf(tp->display + sizeof(tp->display) - l, l, + " | %u KiB/s", rate); +} + void display_throughput(struct progress *progress, off_t total) { struct throughput *tp; @@ -124,11 +149,12 @@ void display_throughput(struct progress *progress, off_t total) if (!tp) { progress->throughput = tp = calloc(1, sizeof(*tp)); if (tp) { - tp->prev_total = total; + tp->prev_total = tp->curr_total = total; tp->prev_tv = tv; } return; } + tp->curr_total = total; /* * We have x = bytes and y = microsecs. We want z = KiB/s: @@ -149,39 +175,21 @@ void display_throughput(struct progress *progress, off_t total) misecs += (int)(tv.tv_usec - tp->prev_tv.tv_usec) / 977; if (misecs > 512) { - int l = sizeof(tp->display); - unsigned int count = total - tp->prev_total; + unsigned int count, rate; + + count = total - tp->prev_total; tp->prev_total = total; tp->prev_tv = tv; tp->avg_bytes += count; tp->avg_misecs += misecs; - - if (total > 1 << 30) { - l -= snprintf(tp->display, l, ", %u.%2.2u GiB", - (int)(total >> 30), - (int)(total & ((1 << 30) - 1)) / 10737419); - } else if (total > 1 << 20) { - l -= snprintf(tp->display, l, ", %u.%2.2u MiB", - (int)(total >> 20), - ((int)(total & ((1 << 20) - 1)) - * 100) >> 20); - } else if (total > 1 << 10) { - l -= snprintf(tp->display, l, ", %u.%2.2u KiB", - (int)(total >> 10), - ((int)(total & ((1 << 10) - 1)) - * 100) >> 10); - } else { - l -= snprintf(tp->display, l, ", %u bytes", (int)total); - } - snprintf(tp->display + sizeof(tp->display) - l, l, - " | %u KiB/s", tp->avg_bytes / tp->avg_misecs); - + rate = tp->avg_bytes / tp->avg_misecs; tp->avg_bytes -= tp->last_bytes[tp->idx]; tp->avg_misecs -= tp->last_misecs[tp->idx]; tp->last_bytes[tp->idx] = count; tp->last_misecs[tp->idx] = misecs; tp->idx = (tp->idx + 1) % TP_IDX_MAX; + throughput_string(tp, total, rate); if (progress->last_value != -1 && progress_update) display(progress, progress->last_value, 0); } @@ -225,6 +233,12 @@ void stop_progress(struct progress **p_progress) *p_progress = NULL; if (progress->last_value != -1) { /* Force the last update */ + struct throughput *tp = progress->throughput; + if (tp) { + unsigned int rate = !tp->avg_misecs ? 0 : + tp->avg_bytes / tp->avg_misecs; + throughput_string(tp, tp->curr_total, rate); + } progress_update = 1; display(progress, progress->last_value, 1); } -- cgit v1.2.1 From a984a06a07cdd0a843eb6107ad56e346d99ac840 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 8 Nov 2007 15:45:41 -0500 Subject: nicer display of thin pack completion In the same spirit of prettifying Git's output display for mere mortals, here's a simple extension to the progress API allowing for a final message to be provided when terminating a progress line, and use it for the display of the number of objects needed to complete a thin pack, saving yet one more line of screen display. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- index-pack.c | 10 +++++----- progress.c | 19 +++++++++++++------ progress.h | 1 + 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/index-pack.c b/index-pack.c index 581a7f565..469a3307d 100644 --- a/index-pack.c +++ b/index-pack.c @@ -792,6 +792,7 @@ int main(int argc, char **argv) flush(); } else { if (fix_thin_pack) { + char msg[48]; int nr_unresolved = nr_deltas - nr_resolved_deltas; int nr_objects_initial = nr_objects; if (nr_unresolved <= 0) @@ -800,12 +801,11 @@ int main(int argc, char **argv) (nr_objects + nr_unresolved + 1) * sizeof(*objects)); fix_unresolved_deltas(nr_unresolved); - stop_progress(&progress); - if (verbose) - fprintf(stderr, "%d objects were added to complete this thin pack.\n", - nr_objects - nr_objects_initial); + sprintf(msg, "completed with %d local objects", + nr_objects - nr_objects_initial); + stop_progress_msg(&progress, msg); fixup_pack_header_footer(output_fd, sha1, - curr_pack, nr_objects); + curr_pack, nr_objects); } if (nr_deltas != nr_resolved_deltas) die("pack has %d unresolved deltas", diff --git a/progress.c b/progress.c index 0700dcf24..4bd650f9b 100644 --- a/progress.c +++ b/progress.c @@ -69,9 +69,9 @@ static void clear_progress_signal(void) progress_update = 0; } -static int display(struct progress *progress, unsigned n, int done) +static int display(struct progress *progress, unsigned n, const char *done) { - char *eol, *tp; + const char *eol, *tp; if (progress->delay) { if (!progress_update || --progress->delay) @@ -90,7 +90,7 @@ static int display(struct progress *progress, unsigned n, int done) progress->last_value = n; tp = (progress->throughput) ? progress->throughput->display : ""; - eol = done ? ", done. \n" : " \r"; + eol = done ? done : " \r"; if (progress->total) { unsigned percent = n * 100 / progress->total; if (percent != progress->last_percent || progress_update) { @@ -191,13 +191,13 @@ void display_throughput(struct progress *progress, off_t total) throughput_string(tp, total, rate); if (progress->last_value != -1 && progress_update) - display(progress, progress->last_value, 0); + display(progress, progress->last_value, NULL); } } int display_progress(struct progress *progress, unsigned n) { - return progress ? display(progress, n, 0) : 0; + return progress ? display(progress, n, NULL) : 0; } struct progress *start_progress_delay(const char *title, unsigned total, @@ -226,6 +226,11 @@ struct progress *start_progress(const char *title, unsigned total) } void stop_progress(struct progress **p_progress) +{ + stop_progress_msg(p_progress, "done"); +} + +void stop_progress_msg(struct progress **p_progress, const char *msg) { struct progress *progress = *p_progress; if (!progress) @@ -233,6 +238,7 @@ void stop_progress(struct progress **p_progress) *p_progress = NULL; if (progress->last_value != -1) { /* Force the last update */ + char buf[strlen(msg) + 5]; struct throughput *tp = progress->throughput; if (tp) { unsigned int rate = !tp->avg_misecs ? 0 : @@ -240,7 +246,8 @@ void stop_progress(struct progress **p_progress) throughput_string(tp, tp->curr_total, rate); } progress_update = 1; - display(progress, progress->last_value, 1); + sprintf(buf, ", %s.\n", msg); + display(progress, progress->last_value, buf); } clear_progress_signal(); free(progress->throughput); diff --git a/progress.h b/progress.h index 3912969e6..611e4c4d4 100644 --- a/progress.h +++ b/progress.h @@ -9,5 +9,6 @@ struct progress *start_progress(const char *title, unsigned total); struct progress *start_progress_delay(const char *title, unsigned total, unsigned percent_treshold, unsigned delay); void stop_progress(struct progress **progress); +void stop_progress_msg(struct progress **progress, const char *msg); #endif -- cgit v1.2.1