177 } |
176 } |
178 } |
177 } |
179 } |
178 } |
180 |
179 |
181 // determine our reporting range |
180 // determine our reporting range |
182 int year; |
181 year report_year{ |
183 if (settings.year == fm::settings_current_year) { |
182 settings.year == fm::settings_current_year |
184 year = static_cast<int>(chrono::year_month_day{chrono::floor<chrono::days>(chrono::system_clock::now())}.year()); |
183 ? year_month_day{floor<days>(system_clock::now())}.year() |
185 } else { |
184 : year{settings.year} |
186 year = settings.year; |
185 }; |
187 } |
186 year_month_day report_begin{report_year, January, 1d}; |
188 chrono::year_month_day report_begin{chrono::year{year}, chrono::January, 1d}; |
187 year_month_day report_end{report_year, December, 31d}; |
189 chrono::year_month_day report_end{chrono::year{year}, chrono::December, 31d}; |
|
190 |
188 |
191 // read the commit logs |
189 // read the commit logs |
192 fm::heatmap heatmap; |
190 fm::heatmap heatmap; |
193 for (auto &&repo : repos.list()) { |
191 for (auto &&repo : repos.list()) { |
194 if (settings.separate) { |
192 if (settings.separate) { |
196 } |
194 } |
197 proc.chdir(repo.path); |
195 proc.chdir(repo.path); |
198 if (repo.type == fm::HG) { |
196 if (repo.type == fm::HG) { |
199 proc.setbin(settings.hg); |
197 proc.setbin(settings.hg); |
200 if (proc.exec_log({"log", |
198 if (proc.exec_log({"log", |
201 "--date", std::format("{0}-01-01 to {0}-12-31", year), |
199 "--date", std::format("{0}-01-01 to {0}-12-31", report_year), |
202 "--template", "{author}#{date|shortdate}\n"})) { |
200 "--template", "{author}#{date|shortdate}\n"})) { |
203 fprintf(stderr, "Reading commit log for repo '%s' failed!\n", repo.path.c_str()); |
201 fprintf(stderr, "Reading commit log for repo '%s' failed!\n", repo.path.c_str()); |
204 return EXIT_FAILURE; |
202 return EXIT_FAILURE; |
205 } |
203 } |
206 heatmap.add(proc.output()); |
204 heatmap.add(proc.output()); |
207 } else { |
205 } else { |
208 proc.setbin(settings.git); |
206 proc.setbin(settings.git); |
209 if (proc.exec_log({"log", |
207 if (proc.exec_log({"log", |
210 "--since", std::format("{0}-01-01", year), |
208 "--since", std::format("{0}-01-01", report_year), |
211 "--until", std::format("{0}-12-31", year), |
209 "--until", std::format("{0}-12-31", report_year), |
212 "--format=tformat:%an <%ae>#%cs"})) { |
210 "--format=tformat:%an <%ae>#%cs"})) { |
213 fprintf(stderr, "Reading commit log for repo '%s' failed!\n", repo.path.c_str()); |
211 fprintf(stderr, "Reading commit log for repo '%s' failed!\n", repo.path.c_str()); |
214 return EXIT_FAILURE; |
212 return EXIT_FAILURE; |
215 } |
213 } |
216 heatmap.add(proc.output()); |
214 heatmap.add(proc.output()); |
220 html::open(); |
218 html::open(); |
221 for (const auto &[repo, authors] : heatmap.data()) { |
219 for (const auto &[repo, authors] : heatmap.data()) { |
222 html::h1(repo); |
220 html::h1(repo); |
223 for (const auto &[author, entries] : authors) { |
221 for (const auto &[author, entries] : authors) { |
224 html::h2(author); |
222 html::h2(author); |
225 html::table_begin(year); |
223 html::table_begin(report_year); |
226 |
224 |
227 // initialize counters |
225 // initialize counters |
228 unsigned column = 0, row = 0; |
226 unsigned column = 0, row = 0; |
229 |
227 |
230 // initialize first day (which must be a Monday, possibly the year before) |
228 // initialize first day (which must be a Monday, possibly the year before) |
231 chrono::sys_days day_to_check = chrono::January / chrono::Monday[1] / chrono::year{year}; |
229 sys_days day_to_check = January / Monday[1] / report_year; |
232 |
230 |
233 // remember the starting point |
231 // remember the starting point |
234 auto start = day_to_check; |
232 auto start = day_to_check; |
235 |
233 |
236 // now add all entries for Monday, Tuesdays, etc. always starting back in january |
234 // now add all entries for Monday, Tuesdays, etc. always starting back in january |
238 html::row_begin(row); |
236 html::row_begin(row); |
239 |
237 |
240 // check if we need to add blank cells |
238 // check if we need to add blank cells |
241 while (day_to_check < report_begin) { |
239 while (day_to_check < report_begin) { |
242 html::cell_out_of_range(); |
240 html::cell_out_of_range(); |
243 day_to_check += chrono::days{7}; |
241 day_to_check += days{7}; |
244 column++; |
242 column++; |
245 } |
243 } |
246 |
244 |
247 while (day_to_check <= report_end) { |
245 while (day_to_check <= report_end) { |
248 // get the entry from the heatmap |
246 // get the entry from the heatmap |
251 html::cell(day_to_check, 0); |
249 html::cell(day_to_check, 0); |
252 } else { |
250 } else { |
253 html::cell(day_to_check, find_result->second); |
251 html::cell(day_to_check, find_result->second); |
254 } |
252 } |
255 // advance seven days and one column |
253 // advance seven days and one column |
256 day_to_check += chrono::days{7}; |
254 day_to_check += days{7}; |
257 column++; |
255 column++; |
258 } |
256 } |
259 // fill remaining columns with blank cells |
257 // fill remaining columns with blank cells |
260 for (unsigned i = column ; i < html::columns ; i++) { |
258 for (unsigned i = column ; i < html::columns ; i++) { |
261 html::cell_out_of_range(); |
259 html::cell_out_of_range(); |
266 |
264 |
267 // if we have seen all seven weekdays, that's it |
265 // if we have seen all seven weekdays, that's it |
268 if (++row == 7) break; |
266 if (++row == 7) break; |
269 |
267 |
270 // otherwise, advance the starting point by one day, reset, and begin a new row |
268 // otherwise, advance the starting point by one day, reset, and begin a new row |
271 start += chrono::days{1}; |
269 start += days{1}; |
272 day_to_check = start; |
270 day_to_check = start; |
273 column =0; |
271 column =0; |
274 } |
272 } |
275 |
273 |
276 html::table_end(); |
274 html::table_end(); |