Blame


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