1 #include "git-compat-util.h"
4 static volatile sig_atomic_t progress_update
;
6 static void progress_interval(int signum
)
11 static void set_progress_signal(void)
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
);
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
);
30 static void clear_progress_signal(void)
32 struct itimerval v
= {{0,},};
33 setitimer(ITIMER_REAL
, &v
, NULL
);
34 signal(SIGALRM
, SIG_IGN
);
38 static int display(struct progress
*progress
, unsigned n
, int done
)
42 if (progress
->delay
) {
43 if (!progress_update
|| --progress
->delay
)
45 if (progress
->total
) {
46 unsigned percent
= n
* 100 / progress
->total
;
47 if (percent
> progress
->delayed_percent_treshold
) {
48 /* inhibit this progress report entirely */
49 clear_progress_signal();
57 progress
->last_value
= n
;
58 eol
= done
? ", done. \n" : " \r";
59 if (progress
->total
) {
60 unsigned percent
= n
* 100 / progress
->total
;
61 if (percent
!= progress
->last_percent
|| progress_update
) {
62 progress
->last_percent
= percent
;
63 fprintf(stderr
, "%s: %3u%% (%u/%u)%s", progress
->title
,
64 percent
, n
, progress
->total
, eol
);
68 } else if (progress_update
) {
69 fprintf(stderr
, "%s: %u%s", progress
->title
, n
, eol
);
77 int display_progress(struct progress
*progress
, unsigned n
)
79 return display(progress
, n
, 0);
82 void start_progress_delay(struct progress
*progress
, const char *title
,
83 unsigned total
, unsigned percent_treshold
, unsigned delay
)
85 progress
->title
= title
;
86 progress
->total
= total
;
87 progress
->last_value
= -1;
88 progress
->last_percent
= -1;
89 progress
->delayed_percent_treshold
= percent_treshold
;
90 progress
->delay
= delay
;
91 set_progress_signal();
94 void start_progress(struct progress
*progress
, const char *title
, unsigned total
)
96 start_progress_delay(progress
, title
, total
, 0, 0);
99 void stop_progress(struct progress
*progress
)
101 if (progress
->last_value
!= -1) {
102 /* Force the last update */
104 display(progress
, progress
->last_value
, 1);
106 clear_progress_signal();