src/main.cpp

changeset 1
9bf126bc825c
parent 0
b4b281ef2d0f
child 3
c87bde92805f
equal deleted inserted replaced
0:b4b281ef2d0f 1:9bf126bc825c
20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 21 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */ 23 */
24 24
25 int main() { 25 #include "settings.h"
26
27 #include <cstdlib>
28 #include <cstdio>
29 #include <cstring>
30 #include <cerrno>
31
32 static void print_help() {
33 fputs(
34 "Usage: fallusmeter [OPTION]... [PATH]...\n\n"
35 "Options:\n"
36 " -h, --help Print this help message\n"
37 " -d, --depth <num> The search depth (default: 1, max: 255)\n"
38 " -n, --no-pull Do not pull the repositories\n"
39 " -s, --separate Output a separate heat map for each repository\n"
40 " -y, --year <year> The year for which to create the heat map\n"
41 " --hg <path> Path to hg binary (default: /usr/bin/hg)\n"
42 " --git <path> Path to git binary (default: /usr/bin/git)\n\n"
43 "Scans all specified paths recursively for Mercurial and Git repositories and\n"
44 "creates a commit heat map for the specified \033[1myear\033[22m or the current year.\n"
45 "By default, the recursion \033[1mdepth\033[22m is one, meaning that this tool assumes that\n"
46 "each \033[1mpath\033[22m is either a repository or contains repositories as subdirectories.\n"
47 "You can change the \033[1mdepth\033[22m to support other directory structures.\n\n"
48 "When you do not specify \033[1m--no-pull\033[22m, this tool will execute the pull command\n"
49 "(and for hg the update command) before retrieving the commit log, assuming\n"
50 "to be on the default branch with \033[4mno uncommitted changes\033[24m.\n\n"
51 "The default output format prints an HTML page to stdout. In all cases, a\n"
52 "separate heat map is generated for each author, but all repositories are,\n"
53 "accumulated unless the \033[1m--separate\033[22m option is specified.\n"
54 , stderr);
55 }
56
57 static bool chk_arg(const char* arg, const char* opt1, const char* opt2) {
58 return strcmp(arg, opt1) == 0 || (opt2 != nullptr && strcmp(arg, opt2) == 0);
59 }
60
61 template<typename T>
62 static bool parse_unsigned(const char *str, T *result, unsigned long max) {
63 char *endptr;
64 errno = 0;
65 unsigned long d = strtoul(str, &endptr, 10);
66 if (*endptr != '\0' || errno == ERANGE) return true;
67 if (d < max) {
68 *result = d;
69 return false;
70 } else {
71 return true;
72 }
73 }
74
75 static int parse_args(fm::settings &settings, int argc, char *argv[]) {
76 for (int i = 1; i < argc; i++) {
77 if (chk_arg(argv[i], "-h", "--help")) {
78 print_help();
79 return -1;
80 } else if (chk_arg(argv[i], "-d", "--depth")) {
81 if (i + 1 >= argc || parse_unsigned(argv[++i], &settings.depth, 256)) {
82 fputs("missing or invalid depth\n", stderr);
83 return -1;
84 }
85 } else if (chk_arg(argv[i], "-y", "--year")) {
86 if (i + 1 >= argc || parse_unsigned(argv[++i], &settings.year, 9999)) {
87 fputs("missing or invalid year\n", stderr);
88 return -1;
89 }
90 } else if (chk_arg(argv[i], "-n", "--no-pull")) {
91 settings.nopull = true;
92 } else if (chk_arg(argv[i], "-s", "--separate")) {
93 settings.separate = true;
94 } else if (chk_arg(argv[i], "--hg", nullptr)) {
95 if (i + 1 < argc) {
96 settings.hg.assign(argv[++i]);
97 } else {
98 fputs("--hg is expecting a path\n", stderr);
99 return -1;
100 }
101 } else if (chk_arg(argv[i], "--git", nullptr)) {
102 if (i + 1 < argc) {
103 settings.git.assign(argv[++i]);
104 } else {
105 fputs("--git is expecting a path\n", stderr);
106 return -1;
107 }
108 } else if (argv[i][0] == '-') {
109 fprintf(stderr, "Unknown option: %s\n", argv[i]);
110 return -1;
111 } else {
112 settings.paths.emplace_back(argv[i]);
113 }
114 }
115
116 if (settings.paths.empty()) {
117 settings.paths.emplace_back("./");
118 }
119
26 return 0; 120 return 0;
27 } 121 }
28 122
123 int main(int argc, char *argv[]) {
124 fm::settings settings;
125
126 if (parse_args(settings, argc, argv)) {
127 return EXIT_FAILURE;
128 }
129
130 return EXIT_SUCCESS;
131 }
132

mercurial