Blob


1 /*
2 * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #include <curses.h>
18 #include <panel.h>
19 #include <locale.h>
20 #include <stdlib.h>
21 #include <getopt.h>
22 #include <string.h>
23 #include <err.h>
25 #include "got_error.h"
27 #ifndef nitems
28 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
29 #endif
31 enum tog_view_id {
32 TOG_VIEW_LOG,
33 TOG_VIEW_DIFF,
34 TOG_VIEW_BLAME,
35 };
37 struct tog_cmd {
38 const char *cmd_name;
39 const struct got_error *(*cmd_main)(int, char *[]);
40 void (*cmd_usage)(void);
41 enum tog_view_id view;
42 const char *cmd_descr;
43 };
45 __dead void usage(void);
46 __dead void usage_log(void);
47 __dead void usage_diff(void);
48 __dead void usage_blame(void);
50 const struct got_error* cmd_log(int, char *[]);
51 const struct got_error* cmd_diff(int, char *[]);
52 const struct got_error* cmd_blame(int, char *[]);
54 struct tog_cmd tog_commands[] = {
55 { "log", cmd_log, usage_log, TOG_VIEW_LOG,
56 "show repository history" },
57 { "diff", cmd_diff, usage_diff, TOG_VIEW_DIFF,
58 "compare files and directories" },
59 { "blame", cmd_blame, usage_blame, TOG_VIEW_BLAME,
60 "show line-by-line file history" },
61 };
63 /* globals */
64 enum tog_view_id tog_view_id;
65 WINDOW *tog_main_win;
66 PANEL *tog_main_panel;
68 __dead void
69 usage_log(void)
70 {
71 fprintf(stderr, "usage: %s log [repository-path]\n",
72 getprogname());
73 exit(1);
74 }
76 const struct got_error *
77 cmd_log(int argc, char *argv[])
78 {
79 return got_error(GOT_ERR_NOT_IMPL);
80 }
82 __dead void
83 usage_diff(void)
84 {
85 fprintf(stderr, "usage: %s diff [repository-path] object1 object2\n",
86 getprogname());
87 exit(1);
88 }
90 const struct got_error *
91 cmd_diff(int argc, char *argv[])
92 {
93 return got_error(GOT_ERR_NOT_IMPL);
94 }
96 __dead void
97 usage_blame(void)
98 {
99 fprintf(stderr, "usage: %s blame [repository-path] blob-object\n",
100 getprogname());
101 exit(1);
104 const struct got_error *
105 cmd_blame(int argc, char *argv[])
107 return got_error(GOT_ERR_NOT_IMPL);
110 static const struct got_error *
111 init_curses(void)
113 initscr();
114 cbreak();
115 noecho();
116 nonl();
117 intrflush(stdscr, FALSE);
118 keypad(stdscr, TRUE);
120 tog_main_win = newwin(0, 0, 0, 0);
121 if (tog_main_win == NULL)
122 return got_error_from_errno();
123 tog_main_panel = new_panel(tog_main_win);
124 if (tog_main_panel == NULL)
125 return got_error_from_errno();
127 return NULL;
130 __dead void
131 usage(void)
133 int i;
135 fprintf(stderr, "usage: %s [-h] command [arg ...]\n\n"
136 "Available commands:\n", getprogname());
137 for (i = 0; i < nitems(tog_commands); i++) {
138 struct tog_cmd *cmd = &tog_commands[i];
139 fprintf(stderr, " %s: %s\n", cmd->cmd_name, cmd->cmd_descr);
141 exit(1);
144 int
145 main(int argc, char *argv[])
147 const struct got_error *error = NULL;
148 struct tog_cmd *cmd = NULL;
149 int ch, hflag = 0;
151 setlocale(LC_ALL, "");
153 while ((ch = getopt(argc, argv, "h")) != -1) {
154 switch (ch) {
155 case 'h':
156 hflag = 1;
157 break;
158 default:
159 usage();
160 /* NOTREACHED */
164 argc -= optind;
165 argv += optind;
166 optind = 0;
168 if (argc == 0)
169 cmd = &tog_commands[0];
170 else {
171 int i;
173 for (i = 0; i < nitems(tog_commands); i++) {
174 if (strncmp(tog_commands[i].cmd_name, argv[0],
175 strlen(argv[0])) == 0) {
176 cmd = &tog_commands[i];
177 if (hflag)
178 tog_commands[i].cmd_usage();
179 break;
182 if (cmd == NULL) {
183 fprintf(stderr, "%s: unknown command '%s'\n",
184 getprogname(), argv[0]);
185 return 1;
189 error = init_curses();
190 if (error) {
191 fprintf(stderr, "Cannot initialize ncurses: %s\n", error->msg);
192 return 1;
195 error = cmd->cmd_main(argc, argv);
196 if (error)
197 goto done;
198 done:
199 endwin();
200 if (error)
201 fprintf(stderr, "%s: %s\n", getprogname(), error->msg);
202 return 0;