progress.con commit Merge branch 'master' of git://git.kernel.org/pub/scm/gitk/gitk (f8db788)
   1#include "git-compat-util.h"
   2#include "progress.h"
   3
   4static volatile sig_atomic_t progress_update;
   5
   6static void progress_interval(int signum)
   7{
   8        progress_update = 1;
   9}
  10
  11static void set_progress_signal(void)
  12{
  13        struct sigaction sa;
  14        struct itimerval v;
  15
  16        progress_update = 0;
  17
  18        memset(&sa, 0, sizeof(sa));
  19        sa.sa_handler = progress_interval;
  20        sigemptyset(&sa.sa_mask);
  21        sa.sa_flags = SA_RESTART;
  22        sigaction(SIGALRM, &sa, NULL);
  23
  24        v.it_interval.tv_sec = 1;
  25        v.it_interval.tv_usec = 0;
  26        v.it_value = v.it_interval;
  27        setitimer(ITIMER_REAL, &v, NULL);
  28}
  29
  30static void clear_progress_signal(void)
  31{
  32        struct itimerval v = {{0,},};
  33        setitimer(ITIMER_REAL, &v, NULL);
  34        signal(SIGALRM, SIG_IGN);
  35        progress_update = 0;
  36}
  37
  38int display_progress(struct progress *progress, unsigned n)
  39{
  40        if (progress->delay) {
  41                char buf[80];
  42                if (!progress_update || --progress->delay)
  43                        return 0;
  44                if (progress->total) {
  45                        unsigned percent = n * 100 / progress->total;
  46                        if (percent > progress->delayed_percent_treshold) {
  47                                /* inhibit this progress report entirely */
  48                                clear_progress_signal();
  49                                progress->delay = -1;
  50                                progress->total = 0;
  51                                return 0;
  52                        }
  53                }
  54                if (snprintf(buf, sizeof(buf),
  55                             progress->delayed_title, progress->total))
  56                        fprintf(stderr, "%s\n", buf);
  57        }
  58        if (progress->total) {
  59                unsigned percent = n * 100 / progress->total;
  60                if (percent != progress->last_percent || progress_update) {
  61                        progress->last_percent = percent;
  62                        fprintf(stderr, "%s%4u%% (%u/%u) done\r",
  63                                progress->prefix, percent, n, progress->total);
  64                        progress_update = 0;
  65                        progress->need_lf = 1;
  66                        return 1;
  67                }
  68        } else if (progress_update) {
  69                fprintf(stderr, "%s%u\r", progress->prefix, n);
  70                progress_update = 0;
  71                progress->need_lf = 1;
  72                return 1;
  73        }
  74        return 0;
  75}
  76
  77void start_progress(struct progress *progress, const char *title,
  78                    const char *prefix, unsigned total)
  79{
  80        char buf[80];
  81        progress->prefix = prefix;
  82        progress->total = total;
  83        progress->last_percent = -1;
  84        progress->delay = 0;
  85        progress->need_lf = 0;
  86        if (snprintf(buf, sizeof(buf), title, total))
  87                fprintf(stderr, "%s\n", buf);
  88        set_progress_signal();
  89}
  90
  91void start_progress_delay(struct progress *progress, const char *title,
  92                          const char *prefix, unsigned total,
  93                          unsigned percent_treshold, unsigned delay)
  94{
  95        progress->prefix = prefix;
  96        progress->total = total;
  97        progress->last_percent = -1;
  98        progress->delayed_percent_treshold = percent_treshold;
  99        progress->delayed_title = title;
 100        progress->delay = delay;
 101        progress->need_lf = 0;
 102        set_progress_signal();
 103}
 104
 105void stop_progress(struct progress *progress)
 106{
 107        clear_progress_signal();
 108        if (progress->need_lf)
 109                fputc('\n', stderr);
 110}