Blame


1 5c860e29 2018-03-12 stsp /*
2 5c860e29 2018-03-12 stsp * Copyright (c) 2017 Martin Pieuchot
3 5c860e29 2018-03-12 stsp *
4 5c860e29 2018-03-12 stsp * Permission to use, copy, modify, and distribute this software for any
5 5c860e29 2018-03-12 stsp * purpose with or without fee is hereby granted, provided that the above
6 5c860e29 2018-03-12 stsp * copyright notice and this permission notice appear in all copies.
7 5c860e29 2018-03-12 stsp *
8 5c860e29 2018-03-12 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 5c860e29 2018-03-12 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 5c860e29 2018-03-12 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 5c860e29 2018-03-12 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 5c860e29 2018-03-12 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 5c860e29 2018-03-12 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 5c860e29 2018-03-12 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 5c860e29 2018-03-12 stsp */
16 5c860e29 2018-03-12 stsp
17 5c860e29 2018-03-12 stsp #include <err.h>
18 5c860e29 2018-03-12 stsp #include <errno.h>
19 5c860e29 2018-03-12 stsp #include <locale.h>
20 5c860e29 2018-03-12 stsp #include <stdio.h>
21 5c860e29 2018-03-12 stsp #include <stdlib.h>
22 5c860e29 2018-03-12 stsp #include <string.h>
23 5c860e29 2018-03-12 stsp #include <unistd.h>
24 5c860e29 2018-03-12 stsp
25 5c860e29 2018-03-12 stsp #include <git2.h>
26 5c860e29 2018-03-12 stsp
27 5c860e29 2018-03-12 stsp #ifndef nitems
28 5c860e29 2018-03-12 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
29 5c860e29 2018-03-12 stsp #endif
30 5c860e29 2018-03-12 stsp
31 5c860e29 2018-03-12 stsp struct cmd {
32 5c860e29 2018-03-12 stsp const char *cmd_name;
33 5c860e29 2018-03-12 stsp int (*cmd_main)(int, char *[]);
34 5c860e29 2018-03-12 stsp };
35 5c860e29 2018-03-12 stsp
36 5c860e29 2018-03-12 stsp __dead void usage(void);
37 5c860e29 2018-03-12 stsp
38 5c860e29 2018-03-12 stsp int cmd_log(int, char *[]);
39 5c860e29 2018-03-12 stsp int cmd_status(int, char *[]);
40 5c860e29 2018-03-12 stsp
41 5c860e29 2018-03-12 stsp struct cmd got_commands[] = {
42 5c860e29 2018-03-12 stsp { "log", cmd_log },
43 5c860e29 2018-03-12 stsp { "status", cmd_status },
44 5c860e29 2018-03-12 stsp };
45 5c860e29 2018-03-12 stsp
46 5c860e29 2018-03-12 stsp int
47 5c860e29 2018-03-12 stsp main(int argc, char *argv[])
48 5c860e29 2018-03-12 stsp {
49 5c860e29 2018-03-12 stsp struct cmd *cmd;
50 5c860e29 2018-03-12 stsp unsigned int i;
51 5c860e29 2018-03-12 stsp int ch;
52 5c860e29 2018-03-12 stsp
53 5c860e29 2018-03-12 stsp setlocale(LC_ALL, "");
54 5c860e29 2018-03-12 stsp
55 5c860e29 2018-03-12 stsp if (pledge("stdio rpath", NULL) == -1)
56 5c860e29 2018-03-12 stsp err(1, "pledge");
57 5c860e29 2018-03-12 stsp
58 5c860e29 2018-03-12 stsp while ((ch = getopt(argc, argv, "")) != -1) {
59 5c860e29 2018-03-12 stsp switch (ch) {
60 5c860e29 2018-03-12 stsp default:
61 5c860e29 2018-03-12 stsp usage();
62 5c860e29 2018-03-12 stsp /* NOTREACHED */
63 5c860e29 2018-03-12 stsp }
64 5c860e29 2018-03-12 stsp }
65 5c860e29 2018-03-12 stsp
66 5c860e29 2018-03-12 stsp argc -= optind;
67 5c860e29 2018-03-12 stsp argv += optind;
68 5c860e29 2018-03-12 stsp
69 5c860e29 2018-03-12 stsp if (argc <= 0)
70 5c860e29 2018-03-12 stsp usage();
71 5c860e29 2018-03-12 stsp
72 5c860e29 2018-03-12 stsp for (i = 0; i < nitems(got_commands); i++) {
73 5c860e29 2018-03-12 stsp cmd = &got_commands[i];
74 5c860e29 2018-03-12 stsp
75 5c860e29 2018-03-12 stsp if (strncmp(cmd->cmd_name, argv[0], strlen(argv[0])))
76 5c860e29 2018-03-12 stsp continue;
77 5c860e29 2018-03-12 stsp
78 5c860e29 2018-03-12 stsp return got_commands[i].cmd_main(argc, argv);
79 5c860e29 2018-03-12 stsp /* NOTREACHED */
80 5c860e29 2018-03-12 stsp }
81 5c860e29 2018-03-12 stsp
82 5c860e29 2018-03-12 stsp fprintf(stderr, "%s: unknown command -- %s\n", getprogname(), argv[0]);
83 5c860e29 2018-03-12 stsp return 1;
84 5c860e29 2018-03-12 stsp }
85 5c860e29 2018-03-12 stsp
86 5c860e29 2018-03-12 stsp __dead void
87 5c860e29 2018-03-12 stsp usage(void)
88 5c860e29 2018-03-12 stsp {
89 5c860e29 2018-03-12 stsp fprintf(stderr, "usage: %s command [arg ...]\n", getprogname());
90 5c860e29 2018-03-12 stsp exit(1);
91 5c860e29 2018-03-12 stsp }
92 5c860e29 2018-03-12 stsp
93 5c860e29 2018-03-12 stsp int
94 5c860e29 2018-03-12 stsp cmd_log(int argc __unused, char *argv[] __unused)
95 5c860e29 2018-03-12 stsp {
96 5c860e29 2018-03-12 stsp git_repository *repo = NULL;
97 5c860e29 2018-03-12 stsp git_revwalk *walker = NULL;
98 5c860e29 2018-03-12 stsp git_commit *commit = NULL;
99 5c860e29 2018-03-12 stsp git_oid oid;
100 5c860e29 2018-03-12 stsp
101 5c860e29 2018-03-12 stsp git_libgit2_init();
102 5c860e29 2018-03-12 stsp
103 5c860e29 2018-03-12 stsp if (git_repository_open_ext(&repo, ".", 0, NULL))
104 5c860e29 2018-03-12 stsp errx(1, "git_repository_open: %s", giterr_last()->message);
105 5c860e29 2018-03-12 stsp
106 5c860e29 2018-03-12 stsp if (git_revwalk_new(&walker, repo))
107 5c860e29 2018-03-12 stsp errx(1, "git_revwalk_new: %s", giterr_last()->message);
108 5c860e29 2018-03-12 stsp
109 5c860e29 2018-03-12 stsp if (git_revwalk_push_head(walker))
110 5c860e29 2018-03-12 stsp errx(1, "git_revwalk_push_head: %s", giterr_last()->message);
111 5c860e29 2018-03-12 stsp
112 5c860e29 2018-03-12 stsp while (git_revwalk_next(&oid, walker) == 0) {
113 5c860e29 2018-03-12 stsp char buf[GIT_OID_HEXSZ + 1];
114 5c860e29 2018-03-12 stsp const git_signature *sig;
115 5c860e29 2018-03-12 stsp
116 5c860e29 2018-03-12 stsp git_commit_free(commit);
117 5c860e29 2018-03-12 stsp if (git_commit_lookup(&commit, repo, &oid))
118 5c860e29 2018-03-12 stsp errx(1, "git_commit_lookup: %s", giterr_last()->message);
119 5c860e29 2018-03-12 stsp
120 5c860e29 2018-03-12 stsp printf("-----------------------------------------------\n");
121 5c860e29 2018-03-12 stsp git_oid_tostr(buf, sizeof(buf), git_commit_id(commit));
122 5c860e29 2018-03-12 stsp printf("commit %s\n", buf);
123 5c860e29 2018-03-12 stsp
124 5c860e29 2018-03-12 stsp if ((sig = git_commit_author(commit)) != NULL) {
125 5c860e29 2018-03-12 stsp printf("Author: %s <%s>\n", sig->name, sig->email);
126 5c860e29 2018-03-12 stsp }
127 5c860e29 2018-03-12 stsp printf("\n%s\n", git_commit_message_raw(commit));
128 5c860e29 2018-03-12 stsp }
129 5c860e29 2018-03-12 stsp git_commit_free(commit);
130 5c860e29 2018-03-12 stsp
131 5c860e29 2018-03-12 stsp git_repository_free(repo);
132 5c860e29 2018-03-12 stsp git_libgit2_shutdown();
133 5c860e29 2018-03-12 stsp
134 5c860e29 2018-03-12 stsp return 0;
135 5c860e29 2018-03-12 stsp }
136 5c860e29 2018-03-12 stsp
137 5c860e29 2018-03-12 stsp int
138 5c860e29 2018-03-12 stsp cmd_status(int argc __unused, char *argv[] __unused)
139 5c860e29 2018-03-12 stsp {
140 5c860e29 2018-03-12 stsp git_repository *repo = NULL;
141 5c860e29 2018-03-12 stsp git_status_list *status;
142 5c860e29 2018-03-12 stsp git_status_options statusopts;
143 5c860e29 2018-03-12 stsp size_t i;
144 5c860e29 2018-03-12 stsp
145 5c860e29 2018-03-12 stsp git_libgit2_init();
146 5c860e29 2018-03-12 stsp
147 5c860e29 2018-03-12 stsp if (git_repository_open_ext(&repo, ".", 0, NULL))
148 5c860e29 2018-03-12 stsp errx(1, "git_repository_open: %s", giterr_last()->message);
149 5c860e29 2018-03-12 stsp
150 5c860e29 2018-03-12 stsp if (git_repository_is_bare(repo))
151 5c860e29 2018-03-12 stsp errx(1, "bar repository");
152 5c860e29 2018-03-12 stsp
153 5c860e29 2018-03-12 stsp if (git_status_init_options(&statusopts, GIT_STATUS_OPTIONS_VERSION))
154 5c860e29 2018-03-12 stsp errx(1, "git_status_init_options: %s", giterr_last()->message);
155 5c860e29 2018-03-12 stsp
156 5c860e29 2018-03-12 stsp statusopts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
157 5c860e29 2018-03-12 stsp statusopts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
158 5c860e29 2018-03-12 stsp GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX |
159 5c860e29 2018-03-12 stsp GIT_STATUS_OPT_SORT_CASE_SENSITIVELY;
160 5c860e29 2018-03-12 stsp
161 5c860e29 2018-03-12 stsp if (git_status_list_new(&status, repo, &statusopts))
162 5c860e29 2018-03-12 stsp errx(1, "git_status_list_new: %s", giterr_last()->message);
163 5c860e29 2018-03-12 stsp
164 5c860e29 2018-03-12 stsp for (i = 0; i < git_status_list_entrycount(status); i++) {
165 5c860e29 2018-03-12 stsp const git_status_entry *se;
166 5c860e29 2018-03-12 stsp
167 5c860e29 2018-03-12 stsp se = git_status_byindex(status, i);
168 5c860e29 2018-03-12 stsp switch (se->status) {
169 5c860e29 2018-03-12 stsp case GIT_STATUS_WT_NEW:
170 5c860e29 2018-03-12 stsp printf("? %s\n", se->index_to_workdir->new_file.path);
171 5c860e29 2018-03-12 stsp break;
172 5c860e29 2018-03-12 stsp case GIT_STATUS_WT_MODIFIED:
173 5c860e29 2018-03-12 stsp printf("M %s\n", se->index_to_workdir->new_file.path);
174 5c860e29 2018-03-12 stsp break;
175 5c860e29 2018-03-12 stsp case GIT_STATUS_WT_DELETED:
176 5c860e29 2018-03-12 stsp printf("R %s\n", se->index_to_workdir->new_file.path);
177 5c860e29 2018-03-12 stsp break;
178 5c860e29 2018-03-12 stsp case GIT_STATUS_WT_RENAMED:
179 5c860e29 2018-03-12 stsp printf("m %s -> %s\n",
180 5c860e29 2018-03-12 stsp se->index_to_workdir->old_file.path,
181 5c860e29 2018-03-12 stsp se->index_to_workdir->new_file.path);
182 5c860e29 2018-03-12 stsp break;
183 5c860e29 2018-03-12 stsp case GIT_STATUS_WT_TYPECHANGE:
184 5c860e29 2018-03-12 stsp printf("t %s\n", se->index_to_workdir->new_file.path);
185 5c860e29 2018-03-12 stsp break;
186 5c860e29 2018-03-12 stsp case GIT_STATUS_INDEX_NEW:
187 5c860e29 2018-03-12 stsp printf("A %s\n", se->head_to_index->new_file.path);
188 5c860e29 2018-03-12 stsp break;
189 5c860e29 2018-03-12 stsp case GIT_STATUS_INDEX_MODIFIED:
190 5c860e29 2018-03-12 stsp printf("M %s\n", se->head_to_index->old_file.path);
191 5c860e29 2018-03-12 stsp break;
192 5c860e29 2018-03-12 stsp case GIT_STATUS_INDEX_DELETED:
193 5c860e29 2018-03-12 stsp printf("R %s\n", se->head_to_index->old_file.path);
194 5c860e29 2018-03-12 stsp break;
195 5c860e29 2018-03-12 stsp case GIT_STATUS_INDEX_RENAMED:
196 5c860e29 2018-03-12 stsp printf("m %s -> %s\n",
197 5c860e29 2018-03-12 stsp se->head_to_index->old_file.path,
198 5c860e29 2018-03-12 stsp se->head_to_index->new_file.path);
199 5c860e29 2018-03-12 stsp break;
200 5c860e29 2018-03-12 stsp case GIT_STATUS_INDEX_TYPECHANGE:
201 5c860e29 2018-03-12 stsp printf("t %s\n", se->head_to_index->old_file.path);
202 5c860e29 2018-03-12 stsp break;
203 5c860e29 2018-03-12 stsp case GIT_STATUS_CURRENT:
204 5c860e29 2018-03-12 stsp default:
205 5c860e29 2018-03-12 stsp break;
206 5c860e29 2018-03-12 stsp }
207 5c860e29 2018-03-12 stsp }
208 5c860e29 2018-03-12 stsp
209 5c860e29 2018-03-12 stsp git_status_list_free(status);
210 5c860e29 2018-03-12 stsp git_repository_free(repo);
211 5c860e29 2018-03-12 stsp git_libgit2_shutdown();
212 5c860e29 2018-03-12 stsp
213 5c860e29 2018-03-12 stsp return 0;
214 5c860e29 2018-03-12 stsp }