src/main.cpp

Tue, 21 Jan 2025 20:24:45 +0100

author
Mike Becker <universe@uap-core.de>
date
Tue, 21 Jan 2025 20:24:45 +0100
changeset 3
c87bde92805f
parent 1
9bf126bc825c
child 4
82680ce258d6
permissions
-rw-r--r--

add repository scanner

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"
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
27
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
28 #include <cstdlib>
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
29 #include <cstdio>
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
30 #include <cstring>
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
31 #include <cerrno>
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
32
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
33 static void print_help() {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
34 fputs(
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
35 "Usage: fallusmeter [OPTION]... [PATH]...\n\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
36 "Options:\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
37 " -h, --help Print this help message\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
38 " -d, --depth <num> The search depth (default: 1, max: 255)\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
39 " -n, --no-pull Do not pull the repositories\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
40 " -s, --separate Output a separate heat map for each repository\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
41 " -y, --year <year> The year for which to create the heat map\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
42 " --hg <path> Path to hg binary (default: /usr/bin/hg)\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
43 " --git <path> Path to git binary (default: /usr/bin/git)\n\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
44 "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
45 "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
46 "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
47 "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
48 "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
49 "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
50 "(and for hg the update command) before retrieving the commit log, assuming\n"
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
51 "to be on the default branch with \033[4mno uncommitted changes\033[24m.\n\n"
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
52 "Afterwards, this tool prints an HTML page to stdout. A separate heap map is\n"
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
53 "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
54 "\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
55 "its own heat map.\n"
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
56 , stderr);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
57 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
58
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
59 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
60 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
61 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
62
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
63 template<typename T>
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
64 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
65 char *endptr;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
66 errno = 0;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
67 unsigned long d = strtoul(str, &endptr, 10);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
68 if (*endptr != '\0' || errno == ERANGE) return true;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
69 if (d < max) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
70 *result = d;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
71 return false;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
72 } else {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
73 return true;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
74 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
75 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
76
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
77 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
78 for (int i = 1; i < argc; i++) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
79 if (chk_arg(argv[i], "-h", "--help")) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
80 print_help();
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
81 return -1;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
82 } else if (chk_arg(argv[i], "-d", "--depth")) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
83 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
84 fputs("missing or invalid depth\n", stderr);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
85 return -1;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
86 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
87 } else if (chk_arg(argv[i], "-y", "--year")) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
88 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
89 fputs("missing or invalid year\n", stderr);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
90 return -1;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
91 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
92 } else if (chk_arg(argv[i], "-n", "--no-pull")) {
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
93 settings.update_repos = false;
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
94 } else if (chk_arg(argv[i], "-s", "--separate")) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
95 settings.separate = true;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
96 } else if (chk_arg(argv[i], "--hg", nullptr)) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
97 if (i + 1 < argc) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
98 settings.hg.assign(argv[++i]);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
99 } else {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
100 fputs("--hg is expecting a path\n", stderr);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
101 return -1;
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 } else if (chk_arg(argv[i], "--git", nullptr)) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
104 if (i + 1 < argc) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
105 settings.git.assign(argv[++i]);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
106 } else {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
107 fputs("--git is expecting a path\n", stderr);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
108 return -1;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
109 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
110 } else if (argv[i][0] == '-') {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
111 fprintf(stderr, "Unknown option: %s\n", argv[i]);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
112 return -1;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
113 } else {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
114 settings.paths.emplace_back(argv[i]);
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
115 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
116 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
117
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
118 if (settings.paths.empty()) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
119 settings.paths.emplace_back("./");
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
120 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
121
0
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
122 return 0;
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
123 }
b4b281ef2d0f project init
Mike Becker <universe@uap-core.de>
parents:
diff changeset
124
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
125 static void print_html_header() {
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
126 puts("<html>\n\t<body>");
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
127 }
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
128
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
129 static void print_html_footer() {
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
130 puts("\t</body>\n</html>");
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
131 }
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
132
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
133 int main(int argc, char *argv[]) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
134 fm::settings settings;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
135
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
136 if (parse_args(settings, argc, argv)) {
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
137 return EXIT_FAILURE;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
138 }
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
139
3
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
140 fm::repositories repos;
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
141 for (auto &&path: settings.paths) {
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
142 repos.scan(path, settings.depth);
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
143 }
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
144 if (!settings.update_repos) {
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
145 // TODO: update repositories
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
146 }
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
147 // TODO: calculate the heat maps
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
148
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
149 print_html_header();
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
150 // TODO: output the heat maps here
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
151 print_html_footer();
c87bde92805f add repository scanner
Mike Becker <universe@uap-core.de>
parents: 1
diff changeset
152
1
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
153 return EXIT_SUCCESS;
9bf126bc825c add settings and CLI
Mike Becker <universe@uap-core.de>
parents: 0
diff changeset
154 }

mercurial