1 #include "git-compat-util.h"
4 static volatile sig_atomic_t progress_update
;
7 static void progress_interval(int signum
)
12 static HANDLE progress_event
;
13 static HANDLE progress_thread
;
15 static __stdcall
unsigned heartbeat(void *dummy
)
17 while (WaitForSingleObject(progress_event
, 1000) == WAIT_TIMEOUT
)
23 static void set_progress_signal(void)
31 memset(&sa
, 0, sizeof(sa
));
32 sa
.sa_handler
= progress_interval
;
33 sigemptyset(&sa
.sa_mask
);
34 sa
.sa_flags
= SA_RESTART
;
35 sigaction(SIGALRM
, &sa
, NULL
);
37 v
.it_interval
.tv_sec
= 1;
38 v
.it_interval
.tv_usec
= 0;
39 v
.it_value
= v
.it_interval
;
40 setitimer(ITIMER_REAL
, &v
, NULL
);
42 /* this is just eye candy: errors are not fatal */
43 progress_event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
45 progress_thread
= (HANDLE
) _beginthreadex(NULL
, 0, heartbeat
, NULL
, 0, NULL
);
46 if (!progress_thread
)
47 error("cannot create progress indicator");
49 error("cannot allocate resources for progress indicator");
53 static void clear_progress_signal(void)
56 struct itimerval v
= {{0,},};
57 setitimer(ITIMER_REAL
, &v
, NULL
);
58 signal(SIGALRM
, SIG_IGN
);
60 /* this is just eye candy: errors are not fatal */
62 SetEvent(progress_event
); /* tells thread to terminate */
63 if (progress_thread
) {
64 int rc
= WaitForSingleObject(progress_thread
, 1000);
65 if (rc
== WAIT_TIMEOUT
)
66 error("progress thread did not terminate timely");
67 else if (rc
!= WAIT_OBJECT_0
)
68 error("waiting for progress thread failed: %lu",
70 CloseHandle(progress_thread
);
73 CloseHandle(progress_event
);
74 progress_event
= NULL
;
75 progress_thread
= NULL
;
81 int display_progress(struct progress
*progress
, unsigned n
)
83 if (progress
->delay
) {
85 if (!progress_update
|| --progress
->delay
)
87 if (progress
->total
) {
88 unsigned percent
= n
* 100 / progress
->total
;
89 if (percent
> progress
->delayed_percent_treshold
) {
90 /* inhibit this progress report entirely */
91 clear_progress_signal();
97 if (snprintf(buf
, sizeof(buf
),
98 progress
->delayed_title
, progress
->total
))
99 fprintf(stderr
, "%s\n", buf
);
101 if (progress
->total
) {
102 unsigned percent
= n
* 100 / progress
->total
;
103 if (percent
!= progress
->last_percent
|| progress_update
) {
104 progress
->last_percent
= percent
;
105 fprintf(stderr
, "%s%4u%% (%u/%u) done\r",
106 progress
->prefix
, percent
, n
, progress
->total
);
108 progress
->need_lf
= 1;
111 } else if (progress_update
) {
112 fprintf(stderr
, "%s%u\r", progress
->prefix
, n
);
114 progress
->need_lf
= 1;
120 void start_progress(struct progress
*progress
, const char *title
,
121 const char *prefix
, unsigned total
)
124 progress
->prefix
= prefix
;
125 progress
->total
= total
;
126 progress
->last_percent
= -1;
128 progress
->need_lf
= 0;
129 if (snprintf(buf
, sizeof(buf
), title
, total
))
130 fprintf(stderr
, "%s\n", buf
);
131 set_progress_signal();
134 void start_progress_delay(struct progress
*progress
, const char *title
,
135 const char *prefix
, unsigned total
,
136 unsigned percent_treshold
, unsigned delay
)
138 progress
->prefix
= prefix
;
139 progress
->total
= total
;
140 progress
->last_percent
= -1;
141 progress
->delayed_percent_treshold
= percent_treshold
;
142 progress
->delayed_title
= title
;
143 progress
->delay
= delay
;
144 progress
->need_lf
= 0;
145 set_progress_signal();
148 void stop_progress(struct progress
*progress
)
150 clear_progress_signal();
151 if (progress
->need_lf
)