common progress display support
[git/dscho.git] / progress.c
blob702e1160660363ba727e5ad398edd1f6e13c0fde
1 #include "git-compat-util.h"
2 #include "progress.h"
4 static volatile sig_atomic_t progress_update;
6 static void progress_interval(int signum)
8 progress_update = 1;
11 static void set_progress_signal(void)
13 struct sigaction sa;
14 struct itimerval v;
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);
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);
28 static void clear_progress_signal(void)
30 struct itimerval v = {{0,},};
31 setitimer(ITIMER_REAL, &v, NULL);
32 signal(SIGALRM, SIG_IGN);
33 progress_update = 0;
36 int display_progress(struct progress *progress, unsigned n)
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;
47 } else if (progress_update) {
48 fprintf(stderr, "%s%u\r", progress->msg, n);
49 progress_update = 0;
50 return 1;
52 return 0;
55 void start_progress(struct progress *progress, const char *msg, unsigned total)
57 progress->msg = msg;
58 progress->total = total;
59 progress->last_percent = -1;
60 set_progress_signal();
63 void stop_progress(struct progress *progress)
65 clear_progress_signal();
66 if (progress->total)
67 fputc('\n', stderr);