Introduce git_etc_gitconfig() that encapsulates access of ETC_GITCONFIG.
[git/mingw.git] / progress.c
blob7a8510542fa2d51e94ad2f56eab49be5ab197ca2
1 #include "git-compat-util.h"
2 #include "progress.h"
4 static volatile sig_atomic_t progress_update;
6 #ifndef __MINGW32__
7 static void progress_interval(int signum)
9 progress_update = 1;
11 #else
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)
18 progress_update = 1;
19 return 0;
21 #endif
23 static void set_progress_signal(void)
25 #ifndef __MINGW32__
26 struct sigaction sa;
27 struct itimerval v;
29 progress_update = 0;
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);
41 #else
42 /* this is just eye candy: errors are not fatal */
43 progress_event = CreateEvent(NULL, FALSE, FALSE, NULL);
44 if (progress_event) {
45 progress_thread = (HANDLE) _beginthreadex(NULL, 0, heartbeat, NULL, 0, NULL);
46 if (!progress_thread )
47 error("cannot create progress indicator");
48 } else
49 error("cannot allocate resources for progress indicator");
50 #endif
53 static void clear_progress_signal(void)
55 #ifndef __MINGW32__
56 struct itimerval v = {{0,},};
57 setitimer(ITIMER_REAL, &v, NULL);
58 signal(SIGALRM, SIG_IGN);
59 #else
60 /* this is just eye candy: errors are not fatal */
61 if (progress_event)
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",
69 GetLastError());
70 CloseHandle(progress_thread);
72 if (progress_event)
73 CloseHandle(progress_event);
74 progress_event = NULL;
75 progress_thread = NULL;
76 #endif
78 progress_update = 0;
81 int display_progress(struct progress *progress, unsigned n)
83 if (progress->delay) {
84 char buf[80];
85 if (!progress_update || --progress->delay)
86 return 0;
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();
92 progress->delay = -1;
93 progress->total = 0;
94 return 0;
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);
107 progress_update = 0;
108 return 1;
110 } else if (progress_update) {
111 fprintf(stderr, "%s%u\r", progress->prefix, n);
112 progress_update = 0;
113 return 1;
115 return 0;
118 void start_progress(struct progress *progress, const char *title,
119 const char *prefix, unsigned total)
121 char buf[80];
122 progress->prefix = prefix;
123 progress->total = total;
124 progress->last_percent = -1;
125 progress->delay = 0;
126 if (snprintf(buf, sizeof(buf), title, total))
127 fprintf(stderr, "%s\n", buf);
128 set_progress_signal();
131 void start_progress_delay(struct progress *progress, const char *title,
132 const char *prefix, unsigned total,
133 unsigned percent_treshold, unsigned delay)
135 progress->prefix = prefix;
136 progress->total = total;
137 progress->last_percent = -1;
138 progress->delayed_percent_treshold = percent_treshold;
139 progress->delayed_title = title;
140 progress->delay = delay;
141 set_progress_signal();
144 void stop_progress(struct progress *progress)
146 clear_progress_signal();
147 if (progress->total)
148 fputc('\n', stderr);