src/main.cpp

Sat, 01 Feb 2025 16:40:24 +0100

author
Mike Becker <universe@uap-core.de>
date
Sat, 01 Feb 2025 16:40:24 +0100
changeset 17
bb4e34e77974
parent 16
730a5638c4ad
child 19
2c128952f198
permissions
-rw-r--r--

remove -s flag which is unknown to clang

0
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1 /* Copyright 2025 Mike Becker. All rights reserved.
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
2 *
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
3 * Redistribution and use in source and binary forms, with or without
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
4 * modification, are permitted provided that the following conditions are met:
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
5 *
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
6 * 1. Redistributions of source code must retain the above copyright
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
7 * notice, this list of conditions and the following disclaimer.
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
8 *
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
9 * 2. Redistributions in binary form must reproduce the above copyright
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
10 * notice, this list of conditions and the following disclaimer in the
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
11 * documentation and/or other materials provided with the distribution.
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
12 *
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
16 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
21 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
23 */
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
24
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
25 #include "settings.h"
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
26 #include "repositories.h"
4
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
27 #include "process.h"
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
28 #include "heatmap.h"
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
29 #include "html.h"
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
30
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
31 #include <chrono>
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
32 #include <cstdlib>
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
33 #include <cstdio>
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
34 #include <cstring>
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
35 #include <cerrno>
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
36
13
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
37 using namespace std::chrono;
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
38
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
39 static void print_help() {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
40 fputs(
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
41 "Usage: fallusmeter [OPTION]... [PATH]...\n\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
42 "Options:\n"
14
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
43 " -a, --author <name> Only report this author\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
44 " (repeat option to report multiple authors)\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
45 " -A, --authormap <file> Apply an author mapping file\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
46 " -h, --help Print this help message\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
47 " -d, --depth <num> The search depth (default: 1, max: 255)\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
48 " -n, --no-pull Do not pull the repositories\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
49 " -s, --separate Output a separate heat map for each repository\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
50 " -y, --year <year> The year for which to create the heat map\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
51 " --hg <path> Path to hg binary (default: /usr/bin/hg)\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
52 " --git <path> Path to git binary (default: /usr/bin/git)\n\n"
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
53 "Scans all specified paths recursively for Mercurial and Git repositories and\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
54 "creates a commit heat map for the specified \033[1myear\033[22m or the current year.\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
55 "By default, the recursion \033[1mdepth\033[22m is one, meaning that this tool assumes that\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
56 "each \033[1mpath\033[22m is either a repository or contains repositories as subdirectories.\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
57 "You can change the \033[1mdepth\033[22m to support other directory structures.\n\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
58 "When you do not specify \033[1m--no-pull\033[22m, this tool will execute the pull command\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
59 "(and for hg the update command) before retrieving the commit log, assuming\n"
9
98312f94dbdd skip authorization requests when pulling
Mike Becker <universe@uap-core.de>
parents: 8
diff changeset
60 "to be on the default branch with \033[4mno uncommitted changes\033[24m. If pulling leads to\n"
98312f94dbdd skip authorization requests when pulling
Mike Becker <universe@uap-core.de>
parents: 8
diff changeset
61 "an error, an error message is written to stderr and the process continues\n"
98312f94dbdd skip authorization requests when pulling
Mike Becker <universe@uap-core.de>
parents: 8
diff changeset
62 "with the repository in its current state. This is also the case when pulling\n"
98312f94dbdd skip authorization requests when pulling
Mike Becker <universe@uap-core.de>
parents: 8
diff changeset
63 "requires authorization.\n\n"
14
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
64 "By default, this tool reports commits from all authors. If you want to include\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
65 "only specific authors in the report, you can use the \033[1m--author\033[22m option with as\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
66 "many authors as you like. You can specify either the full author strings with\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
67 "name and mail address, just the mail address, or even just the local-part of\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
68 "the mail address. In case your repository contains commits from an author who\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
69 "used different names or mail addresses, you can use the \033[1m--authormap\033[22m option\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
70 "to specify a file that contains pairs of author strings, like in the following\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
71 "example:\n\n"
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
72 " Full Name <full.name@example.org> = New Name <new.name@example.org>\n"
16
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
73 " just.mail@example.org = Jus Mail <just.mail@example.org>\n"
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
74 " jane = Jane Doe <jane.doe@example.org>\n\n"
14
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
75 "The different variants of full string, only mail address, and only local-part\n"
16
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
76 "should \033[4monly\033[24m be used on the left-hand side. When you use the \033[1m--author\033[22m option at\n"
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
77 "the same time, you only need to specify the new author names.\n\n"
14
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
78 "Finally, this tool prints an HTML page to stdout. A separate heap map is\n"
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
79 "generated for each author showing commits across all repositories, unless the\n"
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
80 "\033[1m--separate\033[22m option is specified in which case each repository is displayed with\n"
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
81 "its own heat map.\n"
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
82 , stderr);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
83 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
84
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
85 static bool chk_arg(const char *arg, const char *opt1, const char *opt2) {
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
86 return strcmp(arg, opt1) == 0 || (opt2 != nullptr && strcmp(arg, opt2) == 0);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
87 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
88
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
89 template<typename T>
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
90 static bool parse_unsigned(const char *str, T *result, unsigned long max) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
91 char *endptr;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
92 errno = 0;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
93 unsigned long d = strtoul(str, &endptr, 10);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
94 if (*endptr != '\0' || errno == ERANGE) return true;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
95 if (d < max) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
96 *result = d;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
97 return false;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
98 } else {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
99 return true;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
100 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
101 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
102
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
103 static int parse_args(fm::settings &settings, int argc, char *argv[]) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
104 for (int i = 1; i < argc; i++) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
105 if (chk_arg(argv[i], "-h", "--help")) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
106 print_help();
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
107 return -1;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
108 } else if (chk_arg(argv[i], "-d", "--depth")) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
109 if (i + 1 >= argc || parse_unsigned(argv[++i], &settings.depth, 256)) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
110 fputs("missing or invalid depth\n", stderr);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
111 return -1;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
112 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
113 } else if (chk_arg(argv[i], "-y", "--year")) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
114 if (i + 1 >= argc || parse_unsigned(argv[++i], &settings.year, 9999)) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
115 fputs("missing or invalid year\n", stderr);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
116 return -1;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
117 }
14
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
118 } else if (chk_arg(argv[i], "-a", "--author")) {
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
119 if (i + 1 < argc) {
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
120 settings.authors.emplace_back(argv[++i]);
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
121 } else {
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
122 fputs("missing author name\n", stderr);
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
123 return -1;
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
124 }
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
125 } else if (chk_arg(argv[i], "-n", "--no-pull")) {
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
126 settings.update_repos = false;
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
127 } else if (chk_arg(argv[i], "-s", "--separate")) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
128 settings.separate = true;
16
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
129 } else if (chk_arg(argv[i], "-A", "--authormap")) {
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
130 if (i + 1 < argc) {
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
131 if (settings.parse_authormap(argv[++i])) {
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
132 fputs("parsing authormap failed\n", stderr);
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
133 return -1;
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
134 }
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
135 } else {
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
136 fputs("missing filename for authormap\n", stderr);
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
137 return -1;
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
138 }
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
139 } else if (chk_arg(argv[i], "--hg", nullptr)) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
140 if (i + 1 < argc) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
141 settings.hg.assign(argv[++i]);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
142 } else {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
143 fputs("--hg is expecting a path\n", stderr);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
144 return -1;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
145 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
146 } else if (chk_arg(argv[i], "--git", nullptr)) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
147 if (i + 1 < argc) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
148 settings.git.assign(argv[++i]);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
149 } else {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
150 fputs("--git is expecting a path\n", stderr);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
151 return -1;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
152 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
153 } else if (argv[i][0] == '-') {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
154 fprintf(stderr, "Unknown option: %s\n", argv[i]);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
155 return -1;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
156 } else {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
157 settings.paths.emplace_back(argv[i]);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
158 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
159 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
160
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
161 if (settings.paths.empty()) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
162 settings.paths.emplace_back("./");
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
163 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
164
0
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
165 return 0;
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
166 }
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
167
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
168 int main(int argc, char *argv[]) {
4
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
169 // parse settings
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
170 fm::settings settings;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
171 if (parse_args(settings, argc, argv)) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
172 return EXIT_FAILURE;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
173 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
174
4
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
175 // check hg and git
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
176 fm::process proc;
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
177 proc.setbin(settings.hg);
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
178 if (proc.exec({"--version"})) {
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
179 fprintf(stderr, "Testing hg binary '%s' failed!\n", settings.hg.c_str());
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
180 return EXIT_FAILURE;
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
181 }
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
182 proc.setbin(settings.git);
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
183 if (proc.exec({"--version"})) {
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
184 fprintf(stderr, "Testing git binary '%s' failed!\n", settings.git.c_str());
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
185 return EXIT_FAILURE;
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
186 }
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
187
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
188 // scan for repos
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
189 fm::repositories repos;
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
190 for (auto &&path: settings.paths) {
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
191 repos.scan(path, settings.depth);
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
192 }
4
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
193
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
194 // update repos, if not disabled
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
195 if (settings.update_repos) {
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
196 for (auto &&repo : repos.list()) {
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
197 proc.chdir(repo.path);
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
198 if (repo.type == fm::HG) {
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
199 proc.setbin(settings.hg);
9
98312f94dbdd skip authorization requests when pulling
Mike Becker <universe@uap-core.de>
parents: 8
diff changeset
200 if (proc.exec({"pull", "-y"})) {
4
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
201 fprintf(stderr, "Pulling repo '%s' failed!\nMaybe there is no remote?\n", repo.path.c_str());
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
202 } else if (proc.exec({"update"})) {
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
203 fprintf(stderr, "Updating repo '%s' failed!\nMaybe there are local changes?\n", repo.path.c_str());
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
204 }
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
205 } else {
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
206 proc.setbin(settings.git);
9
98312f94dbdd skip authorization requests when pulling
Mike Becker <universe@uap-core.de>
parents: 8
diff changeset
207 if (proc.exec({"pull", "-q"})) {
4
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
208 fprintf(stderr, "Pulling repo '%s' failed!\nMaybe there is no remote or there are local changes?\n", repo.path.c_str());
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
209 }
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
210 }
82680ce258d6 add automatic pull/udate of repositories
Mike Becker <universe@uap-core.de>
parents: 3
diff changeset
211 }
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
212 }
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
213
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
214 // determine our reporting range
13
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
215 year report_year{
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
216 settings.year == fm::settings_current_year
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
217 ? year_month_day{floor<days>(system_clock::now())}.year()
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
218 : year{settings.year}
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
219 };
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
220 year_month_day report_begin{report_year, January, 1d};
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
221 year_month_day report_end{report_year, December, 31d};
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
222
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
223 // read the commit logs
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
224 fm::heatmap heatmap;
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
225 for (auto &&repo : repos.list()) {
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
226 if (settings.separate) {
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
227 heatmap.set_repo(repo.path);
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
228 }
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
229 proc.chdir(repo.path);
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
230 if (repo.type == fm::HG) {
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
231 proc.setbin(settings.hg);
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
232 if (proc.exec_log({"log",
13
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
233 "--date", std::format("{0}-01-01 to {0}-12-31", report_year),
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
234 "--template", "{author}#{date|shortdate}\n"})) {
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
235 fprintf(stderr, "Reading commit log for repo '%s' failed!\n", repo.path.c_str());
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
236 return EXIT_FAILURE;
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
237 }
16
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
238 heatmap.add(settings, proc.output());
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
239 } else {
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
240 proc.setbin(settings.git);
8
6a2e20a4a8ff fix log not being captured from git
Mike Becker <universe@uap-core.de>
parents: 7
diff changeset
241 if (proc.exec_log({"log",
13
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
242 "--since", std::format("{0}-01-01", report_year),
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
243 "--until", std::format("{0}-12-31", report_year),
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
244 "--format=tformat:%an <%ae>#%cs"})) {
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
245 fprintf(stderr, "Reading commit log for repo '%s' failed!\n", repo.path.c_str());
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
246 return EXIT_FAILURE;
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
247 }
16
730a5638c4ad implement authormap
Mike Becker <universe@uap-core.de>
parents: 14
diff changeset
248 heatmap.add(settings, proc.output());
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
249 }
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
250 }
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
251
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
252 html::open();
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
253 for (const auto &[repo, authors] : heatmap.data()) {
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
254 html::h1(repo);
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
255 for (const auto &[author, entries] : authors) {
14
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
256 if (settings.exclude_author(author)) continue;
f0ae064c5b9c implement author filter
Mike Becker <universe@uap-core.de>
parents: 13
diff changeset
257
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
258 html::h2(author);
13
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
259 html::table_begin(report_year);
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
260
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
261 // initialize counters
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
262 unsigned column = 0, row = 0;
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
263
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
264 // initialize first day (which must be a Monday, possibly the year before)
13
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
265 sys_days day_to_check = January / Monday[1] / report_year;
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
266
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
267 // remember the starting point
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
268 auto start = day_to_check;
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
269
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
270 // now add all entries for Monday, Tuesdays, etc. always starting back in january
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
271 while (true) {
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
272 html::row_begin(row);
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
273
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
274 // check if we need to add blank cells
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
275 while (day_to_check < report_begin) {
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
276 html::cell_out_of_range();
13
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
277 day_to_check += days{7};
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
278 column++;
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
279 }
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
280
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
281 while (day_to_check <= report_end) {
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
282 // get the entry from the heatmap
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
283 auto find_result = entries.find(day_to_check);
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
284 if (find_result == entries.end()) {
7
d0f77dd2da42 add color coding
Mike Becker <universe@uap-core.de>
parents: 6
diff changeset
285 html::cell(day_to_check, 0);
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
286 } else {
7
d0f77dd2da42 add color coding
Mike Becker <universe@uap-core.de>
parents: 6
diff changeset
287 html::cell(day_to_check, find_result->second);
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
288 }
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
289 // advance seven days and one column
13
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
290 day_to_check += days{7};
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
291 column++;
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
292 }
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
293 // fill remaining columns with blank cells
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
294 for (unsigned i = column ; i < html::columns ; i++) {
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
295 html::cell_out_of_range();
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
296 }
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
297
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
298 // terminate the row
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
299 html::row_end();
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
300
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
301 // if we have seen all seven weekdays, that's it
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
302 if (++row == 7) break;
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
303
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
304 // otherwise, advance the starting point by one day, reset, and begin a new row
13
e714005f3e9d improve readability
Mike Becker <universe@uap-core.de>
parents: 12
diff changeset
305 start += days{1};
5
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
306 day_to_check = start;
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
307 column =0;
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
308 }
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
309
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
310 html::table_end();
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
311 }
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
312 }
60c2588b4455 finish MVP
Mike Becker <universe@uap-core.de>
parents: 4
diff changeset
313 html::close();
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
314
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
315 return EXIT_SUCCESS;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
316 }

mercurial