progress.con commit Use $Id$ as the ident attribute keyword rather than $ident$ to be consistent with other VCSs (af9b54b)
   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                        return 1;
  66                }
  67        } else if (progress_update) {
  68                fprintf(stderr, "%s%u\r", progress->prefix, n);
  69                progress_update = 0;
  70                return 1;
  71        }
  72        return 0;
  73}
  74
  75void start_progress(struct progress *progress, const char *title,
  76                    const char *prefix, unsigned total)
  77{
  78        char buf[80];
  79        progress->prefix = prefix;
  80        progress->total = total;
  81        progress->last_percent = -1;
  82        progress->delay = 0;
  83        if (snprintf(buf, sizeof(buf), title, total))
  84                fprintf(stderr, "%s\n", buf);
  85        set_progress_signal();
  86}
  87
  88void start_progress_delay(struct progress *progress, const char *title,
  89                          const char *prefix, unsigned total,
  90                          unsigned percent_treshold, unsigned delay)
  91{
  92        progress->prefix = prefix;
  93        progress->total = total;
  94        progress->last_percent = -1;
  95        progress->delayed_percent_treshold = percent_treshold;
  96        progress->delayed_title = title;
  97        progress->delay = delay;
  98        set_progress_signal();
  99}
 100
 101void stop_progress(struct progress *progress)
 102{
 103        clear_progress_signal();
 104        if (progress->total)
 105                fputc('\n', stderr);
 106}