2 5c860e29 2018-03-12 stsp * Copyright (c) 2017 Martin Pieuchot
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.
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.
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>
25 5c860e29 2018-03-12 stsp #include <git2.h>
27 5c860e29 2018-03-12 stsp #ifndef nitems
28 5c860e29 2018-03-12 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
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 *[]);
36 5c860e29 2018-03-12 stsp __dead void usage(void);
38 5c860e29 2018-03-12 stsp int cmd_log(int, char *[]);
39 5c860e29 2018-03-12 stsp int cmd_status(int, char *[]);
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 },
47 5c860e29 2018-03-12 stsp main(int argc, char *argv[])
49 5c860e29 2018-03-12 stsp struct cmd *cmd;
50 5c860e29 2018-03-12 stsp unsigned int i;
53 5c860e29 2018-03-12 stsp setlocale(LC_ALL, "");
55 5c860e29 2018-03-12 stsp if (pledge("stdio rpath", NULL) == -1)
56 5c860e29 2018-03-12 stsp err(1, "pledge");
58 5c860e29 2018-03-12 stsp while ((ch = getopt(argc, argv, "")) != -1) {
59 5c860e29 2018-03-12 stsp switch (ch) {
62 5c860e29 2018-03-12 stsp /* NOTREACHED */
66 5c860e29 2018-03-12 stsp argc -= optind;
67 5c860e29 2018-03-12 stsp argv += optind;
69 5c860e29 2018-03-12 stsp if (argc <= 0)
72 5c860e29 2018-03-12 stsp for (i = 0; i < nitems(got_commands); i++) {
73 5c860e29 2018-03-12 stsp cmd = &got_commands[i];
75 5c860e29 2018-03-12 stsp if (strncmp(cmd->cmd_name, argv[0], strlen(argv[0])))
78 5c860e29 2018-03-12 stsp return got_commands[i].cmd_main(argc, argv);
79 5c860e29 2018-03-12 stsp /* NOTREACHED */
82 5c860e29 2018-03-12 stsp fprintf(stderr, "%s: unknown command -- %s\n", getprogname(), argv[0]);
89 5c860e29 2018-03-12 stsp fprintf(stderr, "usage: %s command [arg ...]\n", getprogname());
94 5c860e29 2018-03-12 stsp cmd_log(int argc __unused, char *argv[] __unused)
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;
101 5c860e29 2018-03-12 stsp git_libgit2_init();
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);
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);
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);
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;
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);
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);
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);
127 5c860e29 2018-03-12 stsp printf("\n%s\n", git_commit_message_raw(commit));
129 5c860e29 2018-03-12 stsp git_commit_free(commit);
131 5c860e29 2018-03-12 stsp git_repository_free(repo);
132 5c860e29 2018-03-12 stsp git_libgit2_shutdown();
138 5c860e29 2018-03-12 stsp cmd_status(int argc __unused, char *argv[] __unused)
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;
145 5c860e29 2018-03-12 stsp git_libgit2_init();
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);
150 5c860e29 2018-03-12 stsp if (git_repository_is_bare(repo))
151 5c860e29 2018-03-12 stsp errx(1, "bar repository");
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);
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;
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);
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;
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
203 5c860e29 2018-03-12 stsp case GIT_STATUS_CURRENT:
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();