478134bc69ea89877523c7650e264cd94419ec9b
   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        memset(&sa, 0, sizeof(sa));
  17        sa.sa_handler = progress_interval;
  18        sigemptyset(&sa.sa_mask);
  19        sa.sa_flags = SA_RESTART;
  20        sigaction(SIGALRM, &sa, NULL);
  21
  22        v.it_interval.tv_sec = 1;
  23        v.it_interval.tv_usec = 0;
  24        v.it_value = v.it_interval;
  25        setitimer(ITIMER_REAL, &v, NULL);
  26}
  27
  28static void clear_progress_signal(void)
  29{
  30        struct itimerval v = {{0,},};
  31        setitimer(ITIMER_REAL, &v, NULL);
  32        signal(SIGALRM, SIG_IGN);
  33        progress_update = 0;
  34}
  35
  36int display_progress(struct progress *progress, unsigned n)
  37{
  38        if (progress->total) {
  39                unsigned percent = n * 100 / progress->total;
  40                if (percent != progress->last_percent || progress_update) {
  41                        progress->last_percent = percent;
  42                        fprintf(stderr, "%s%4u%% (%u/%u) done\r",
  43                                progress->prefix, percent, n, progress->total);
  44                        progress_update = 0;
  45                        return 1;
  46                }
  47        } else if (progress_update) {
  48                fprintf(stderr, "%s%u\r", progress->prefix, n);
  49                progress_update = 0;
  50                return 1;
  51        }
  52        return 0;
  53}
  54
  55void start_progress(struct progress *progress, const char *title,
  56                    const char *prefix, unsigned total)
  57{
  58        char buf[80];
  59        progress->prefix = prefix;
  60        progress->total = total;
  61        progress->last_percent = -1;
  62        if (snprintf(buf, sizeof(buf), title, total))
  63                fprintf(stderr, "%s\n", buf);
  64        set_progress_signal();
  65}
  66
  67void stop_progress(struct progress *progress)
  68{
  69        clear_progress_signal();
  70        if (progress->total)
  71                fputc('\n', stderr);
  72}