Merge branch 'jk/unused-params-even-more'
[gitweb.git] / progress.c
index 289678d43d801411dbe56b8090a2e1a18a158499..212d00e524819aafe17b55f1b2f54a5bcf40dd7e 100644 (file)
@@ -30,11 +30,11 @@ struct throughput {
 
 struct progress {
        const char *title;
-       int last_value;
-       unsigned total;
+       uint64_t last_value;
+       uint64_t total;
        unsigned last_percent;
        unsigned delay;
-       unsigned delayed_percent_threshold;
+       unsigned sparse;
        struct throughput *throughput;
        uint64_t start_ns;
 };
@@ -79,24 +79,12 @@ static int is_foreground_fd(int fd)
        return tpgrp < 0 || tpgrp == getpgid(0);
 }
 
-static int display(struct progress *progress, unsigned n, const char *done)
+static int display(struct progress *progress, uint64_t n, const char *done)
 {
        const char *eol, *tp;
 
-       if (progress->delay) {
-               if (!progress_update || --progress->delay)
-                       return 0;
-               if (progress->total) {
-                       unsigned percent = n * 100 / progress->total;
-                       if (percent > progress->delayed_percent_threshold) {
-                               /* inhibit this progress report entirely */
-                               clear_progress_signal();
-                               progress->delay = -1;
-                               progress->total = 0;
-                               return 0;
-                       }
-               }
-       }
+       if (progress->delay && (!progress_update || --progress->delay))
+               return 0;
 
        progress->last_value = n;
        tp = (progress->throughput) ? progress->throughput->display.buf : "";
@@ -106,9 +94,10 @@ static int display(struct progress *progress, unsigned n, const char *done)
                if (percent != progress->last_percent || progress_update) {
                        progress->last_percent = percent;
                        if (is_foreground_fd(fileno(stderr)) || done) {
-                               fprintf(stderr, "%s: %3u%% (%u/%u)%s%s",
-                                       progress->title, percent, n,
-                                       progress->total, tp, eol);
+                               fprintf(stderr, "%s: %3u%% (%"PRIuMAX"/%"PRIuMAX")%s%s",
+                                       progress->title, percent,
+                                       (uintmax_t)n, (uintmax_t)progress->total,
+                                       tp, eol);
                                fflush(stderr);
                        }
                        progress_update = 0;
@@ -116,8 +105,8 @@ static int display(struct progress *progress, unsigned n, const char *done)
                }
        } else if (progress_update) {
                if (is_foreground_fd(fileno(stderr)) || done) {
-                       fprintf(stderr, "%s: %u%s%s",
-                               progress->title, n, tp, eol);
+                       fprintf(stderr, "%s: %"PRIuMAX"%s%s",
+                               progress->title, (uintmax_t)n, tp, eol);
                        fflush(stderr);
                }
                progress_update = 0;
@@ -127,7 +116,7 @@ static int display(struct progress *progress, unsigned n, const char *done)
        return 0;
 }
 
-static void throughput_string(struct strbuf *buf, off_t total,
+static void throughput_string(struct strbuf *buf, uint64_t total,
                              unsigned int rate)
 {
        strbuf_reset(buf);
@@ -138,7 +127,7 @@ static void throughput_string(struct strbuf *buf, off_t total,
        strbuf_addstr(buf, "/s");
 }
 
-void display_throughput(struct progress *progress, off_t total)
+void display_throughput(struct progress *progress, uint64_t total)
 {
        struct throughput *tp;
        uint64_t now_ns;
@@ -200,13 +189,13 @@ void display_throughput(struct progress *progress, off_t total)
                display(progress, progress->last_value, NULL);
 }
 
-int display_progress(struct progress *progress, unsigned n)
+int display_progress(struct progress *progress, uint64_t n)
 {
        return progress ? display(progress, n, NULL) : 0;
 }
 
-static struct progress *start_progress_delay(const char *title, unsigned total,
-                                            unsigned percent_threshold, unsigned delay)
+static struct progress *start_progress_delay(const char *title, uint64_t total,
+                                            unsigned delay, unsigned sparse)
 {
        struct progress *progress = malloc(sizeof(*progress));
        if (!progress) {
@@ -219,26 +208,56 @@ static struct progress *start_progress_delay(const char *title, unsigned total,
        progress->total = total;
        progress->last_value = -1;
        progress->last_percent = -1;
-       progress->delayed_percent_threshold = percent_threshold;
        progress->delay = delay;
+       progress->sparse = sparse;
        progress->throughput = NULL;
        progress->start_ns = getnanotime();
        set_progress_signal();
        return progress;
 }
 
-struct progress *start_delayed_progress(const char *title, unsigned total)
+struct progress *start_delayed_progress(const char *title, uint64_t total)
 {
-       return start_progress_delay(title, total, 0, 2);
+       return start_progress_delay(title, total, 2, 0);
 }
 
-struct progress *start_progress(const char *title, unsigned total)
+struct progress *start_progress(const char *title, uint64_t total)
 {
        return start_progress_delay(title, total, 0, 0);
 }
 
+/*
+ * Here "sparse" means that the caller might use some sampling criteria to
+ * decide when to call display_progress() rather than calling it for every
+ * integer value in[0 .. total).  In particular, the caller might not call
+ * display_progress() for the last value in the range.
+ *
+ * When "sparse" is set, stop_progress() will automatically force the done
+ * message to show 100%.
+ */
+struct progress *start_sparse_progress(const char *title, uint64_t total)
+{
+       return start_progress_delay(title, total, 0, 1);
+}
+
+struct progress *start_delayed_sparse_progress(const char *title,
+                                              uint64_t total)
+{
+       return start_progress_delay(title, total, 2, 1);
+}
+
+static void finish_if_sparse(struct progress *progress)
+{
+       if (progress &&
+           progress->sparse &&
+           progress->last_value != progress->total)
+               display_progress(progress, progress->total);
+}
+
 void stop_progress(struct progress **p_progress)
 {
+       finish_if_sparse(*p_progress);
+
        stop_progress_msg(p_progress, _("done"));
 }