38 |
38 |
39 static void print_help() { |
39 static void print_help() { |
40 fputs( |
40 fputs( |
41 "Usage: fallusmeter [OPTION]... [PATH]...\n\n" |
41 "Usage: fallusmeter [OPTION]... [PATH]...\n\n" |
42 "Options:\n" |
42 "Options:\n" |
43 " -h, --help Print this help message\n" |
43 " -a, --author <name> Only report this author\n" |
44 " -d, --depth <num> The search depth (default: 1, max: 255)\n" |
44 " (repeat option to report multiple authors)\n" |
45 " -n, --no-pull Do not pull the repositories\n" |
45 " -A, --authormap <file> Apply an author mapping file\n" |
46 " -s, --separate Output a separate heat map for each repository\n" |
46 " -h, --help Print this help message\n" |
47 " -y, --year <year> The year for which to create the heat map\n" |
47 " -d, --depth <num> The search depth (default: 1, max: 255)\n" |
48 " --hg <path> Path to hg binary (default: /usr/bin/hg)\n" |
48 " -n, --no-pull Do not pull the repositories\n" |
49 " --git <path> Path to git binary (default: /usr/bin/git)\n\n" |
49 " -s, --separate Output a separate heat map for each repository\n" |
|
50 " -y, --year <year> The year for which to create the heat map\n" |
|
51 " --hg <path> Path to hg binary (default: /usr/bin/hg)\n" |
|
52 " --git <path> Path to git binary (default: /usr/bin/git)\n\n" |
50 "Scans all specified paths recursively for Mercurial and Git repositories and\n" |
53 "Scans all specified paths recursively for Mercurial and Git repositories and\n" |
51 "creates a commit heat map for the specified \033[1myear\033[22m or the current year.\n" |
54 "creates a commit heat map for the specified \033[1myear\033[22m or the current year.\n" |
52 "By default, the recursion \033[1mdepth\033[22m is one, meaning that this tool assumes that\n" |
55 "By default, the recursion \033[1mdepth\033[22m is one, meaning that this tool assumes that\n" |
53 "each \033[1mpath\033[22m is either a repository or contains repositories as subdirectories.\n" |
56 "each \033[1mpath\033[22m is either a repository or contains repositories as subdirectories.\n" |
54 "You can change the \033[1mdepth\033[22m to support other directory structures.\n\n" |
57 "You can change the \033[1mdepth\033[22m to support other directory structures.\n\n" |
56 "(and for hg the update command) before retrieving the commit log, assuming\n" |
59 "(and for hg the update command) before retrieving the commit log, assuming\n" |
57 "to be on the default branch with \033[4mno uncommitted changes\033[24m. If pulling leads to\n" |
60 "to be on the default branch with \033[4mno uncommitted changes\033[24m. If pulling leads to\n" |
58 "an error, an error message is written to stderr and the process continues\n" |
61 "an error, an error message is written to stderr and the process continues\n" |
59 "with the repository in its current state. This is also the case when pulling\n" |
62 "with the repository in its current state. This is also the case when pulling\n" |
60 "requires authorization.\n\n" |
63 "requires authorization.\n\n" |
61 "Afterwards, this tool prints an HTML page to stdout. A separate heap map is\n" |
64 "By default, this tool reports commits from all authors. If you want to include\n" |
|
65 "only specific authors in the report, you can use the \033[1m--author\033[22m option with as\n" |
|
66 "many authors as you like. You can specify either the full author strings with\n" |
|
67 "name and mail address, just the mail address, or even just the local-part of\n" |
|
68 "the mail address. In case your repository contains commits from an author who\n" |
|
69 "used different names or mail addresses, you can use the \033[1m--authormap\033[22m option\n" |
|
70 "to specify a file that contains pairs of author strings, like in the following\n" |
|
71 "example:\n\n" |
|
72 " Full Name <full.name@example.org> = New Name <new.name@example.org>\n" |
|
73 " just.mail@example.org = new.name@example.org\n" |
|
74 " username = new.name\n\n" |
|
75 "The different variants of full string, only mail address, and only local-part\n" |
|
76 "can be combined as you like. When you use the \033[1m--author\033[22m option at the same\n" |
|
77 "time, you only need to specify the new author names.\n\n" |
|
78 "Finally, this tool prints an HTML page to stdout. A separate heap map is\n" |
62 "generated for each author showing commits across all repositories, unless the\n" |
79 "generated for each author showing commits across all repositories, unless the\n" |
63 "\033[1m--separate\033[22m option is specified in which case each repository is displayed with\n" |
80 "\033[1m--separate\033[22m option is specified in which case each repository is displayed with\n" |
64 "its own heat map.\n" |
81 "its own heat map.\n" |
65 , stderr); |
82 , stderr); |
66 } |
83 } |
96 } else if (chk_arg(argv[i], "-y", "--year")) { |
113 } else if (chk_arg(argv[i], "-y", "--year")) { |
97 if (i + 1 >= argc || parse_unsigned(argv[++i], &settings.year, 9999)) { |
114 if (i + 1 >= argc || parse_unsigned(argv[++i], &settings.year, 9999)) { |
98 fputs("missing or invalid year\n", stderr); |
115 fputs("missing or invalid year\n", stderr); |
99 return -1; |
116 return -1; |
100 } |
117 } |
|
118 } else if (chk_arg(argv[i], "-a", "--author")) { |
|
119 if (i + 1 < argc) { |
|
120 settings.authors.emplace_back(argv[++i]); |
|
121 } else { |
|
122 fputs("missing author name\n", stderr); |
|
123 return -1; |
|
124 } |
101 } else if (chk_arg(argv[i], "-n", "--no-pull")) { |
125 } else if (chk_arg(argv[i], "-n", "--no-pull")) { |
102 settings.update_repos = false; |
126 settings.update_repos = false; |
103 } else if (chk_arg(argv[i], "-s", "--separate")) { |
127 } else if (chk_arg(argv[i], "-s", "--separate")) { |
104 settings.separate = true; |
128 settings.separate = true; |
105 } else if (chk_arg(argv[i], "--hg", nullptr)) { |
129 } else if (chk_arg(argv[i], "--hg", nullptr)) { |
217 |
241 |
218 html::open(); |
242 html::open(); |
219 for (const auto &[repo, authors] : heatmap.data()) { |
243 for (const auto &[repo, authors] : heatmap.data()) { |
220 html::h1(repo); |
244 html::h1(repo); |
221 for (const auto &[author, entries] : authors) { |
245 for (const auto &[author, entries] : authors) { |
|
246 if (settings.exclude_author(author)) continue; |
|
247 |
222 html::h2(author); |
248 html::h2(author); |
223 html::table_begin(report_year); |
249 html::table_begin(report_year); |
224 |
250 |
225 // initialize counters |
251 // initialize counters |
226 unsigned column = 0, row = 0; |
252 unsigned column = 0, row = 0; |