1 #include "git-compat-util.h"
10 unsigned delayed_percent_treshold
;
13 static volatile sig_atomic_t progress_update
;
15 static void progress_interval(int signum
)
20 static void set_progress_signal(void)
27 memset(&sa
, 0, sizeof(sa
));
28 sa
.sa_handler
= progress_interval
;
29 sigemptyset(&sa
.sa_mask
);
30 sa
.sa_flags
= SA_RESTART
;
31 sigaction(SIGALRM
, &sa
, NULL
);
33 v
.it_interval
.tv_sec
= 1;
34 v
.it_interval
.tv_usec
= 0;
35 v
.it_value
= v
.it_interval
;
36 setitimer(ITIMER_REAL
, &v
, NULL
);
39 static void clear_progress_signal(void)
41 struct itimerval v
= {{0,},};
42 setitimer(ITIMER_REAL
, &v
, NULL
);
43 signal(SIGALRM
, SIG_IGN
);
47 static int display(struct progress
*progress
, unsigned n
, int done
)
51 if (progress
->delay
) {
52 if (!progress_update
|| --progress
->delay
)
54 if (progress
->total
) {
55 unsigned percent
= n
* 100 / progress
->total
;
56 if (percent
> progress
->delayed_percent_treshold
) {
57 /* inhibit this progress report entirely */
58 clear_progress_signal();
66 progress
->last_value
= n
;
67 eol
= done
? ", done. \n" : " \r";
68 if (progress
->total
) {
69 unsigned percent
= n
* 100 / progress
->total
;
70 if (percent
!= progress
->last_percent
|| progress_update
) {
71 progress
->last_percent
= percent
;
72 fprintf(stderr
, "%s: %3u%% (%u/%u)%s", progress
->title
,
73 percent
, n
, progress
->total
, eol
);
77 } else if (progress_update
) {
78 fprintf(stderr
, "%s: %u%s", progress
->title
, n
, eol
);
86 int display_progress(struct progress
*progress
, unsigned n
)
88 return progress
? display(progress
, n
, 0) : 0;
91 struct progress
*start_progress_delay(const char *title
, unsigned total
,
92 unsigned percent_treshold
, unsigned delay
)
94 struct progress
*progress
= malloc(sizeof(*progress
));
96 /* unlikely, but here's a good fallback */
97 fprintf(stderr
, "%s...\n", title
);
100 progress
->title
= title
;
101 progress
->total
= total
;
102 progress
->last_value
= -1;
103 progress
->last_percent
= -1;
104 progress
->delayed_percent_treshold
= percent_treshold
;
105 progress
->delay
= delay
;
106 set_progress_signal();
110 struct progress
*start_progress(const char *title
, unsigned total
)
112 return start_progress_delay(title
, total
, 0, 0);
115 void stop_progress(struct progress
**p_progress
)
117 struct progress
*progress
= *p_progress
;
121 if (progress
->last_value
!= -1) {
122 /* Force the last update */
124 display(progress
, progress
->last_value
, 1);
126 clear_progress_signal();