702e1160660363ba727e5ad398edd1f6e13c0fde
   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->msg, percent, n, progress->total);
  44                        progress_update = 0;
  45                        return 1;
  46                }
  47        } else if (progress_update) {
  48                fprintf(stderr, "%s%u\r", progress->msg, n);
  49                progress_update = 0;
  50                return 1;
  51        }
  52        return 0;
  53}
  54
  55void start_progress(struct progress *progress, const char *msg, unsigned total)
  56{
  57        progress->msg = msg;
  58        progress->total = total;
  59        progress->last_percent = -1;
  60        set_progress_signal();
  61}
  62
  63void stop_progress(struct progress *progress)
  64{
  65        clear_progress_signal();
  66        if (progress->total)
  67                fputc('\n', stderr);
  68}