Introduction
Introduction Statistics Contact Development Disclaimer Help
tstagit-index.c - stagit - [fork] customized build of stagit, the static git pa…
git clone git://src.adamsgaard.dk/stagit
Log
Files
Refs
README
LICENSE
---
tstagit-index.c (5961B)
---
1 #include <err.h>
2 #include <limits.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <time.h>
7 #include <unistd.h>
8
9 #include <git2.h>
10
11 static git_repository *repo;
12
13 static const char *relpath = "";
14
15 static char description[255] = "Anders' Repositories";
16 static char releaselink[255] = "<a href=\"https://src.adamsgaard.dk/rele…
17 static char homelink[255] = "<a href=\"https://adamsgaard.dk\">Back to a…
18 static char *name = "";
19 static char owner[255];
20
21 void
22 joinpath(char *buf, size_t bufsiz, const char *path, const char *path2)
23 {
24 int r;
25
26 r = snprintf(buf, bufsiz, "%s%s%s",
27 path, path[0] && path[strlen(path) - 1] != '/' ? "/" : "…
28 if (r < 0 || (size_t)r >= bufsiz)
29 errx(1, "path truncated: '%s%s%s'",
30 path, path[0] && path[strlen(path) - 1] != '/' ?…
31 }
32
33 /* Percent-encode, see RFC3986 section 2.1. */
34 void
35 percentencode(FILE *fp, const char *s, size_t len)
36 {
37 static char tab[] = "0123456789ABCDEF";
38 unsigned char uc;
39 size_t i;
40
41 for (i = 0; *s && i < len; s++, i++) {
42 uc = *s;
43 /* NOTE: do not encode '/' for paths */
44 if (uc < '/' || uc >= 127 || (uc >= ':' && uc <= '@') ||
45 uc == '[' || uc == ']') {
46 putc('%', fp);
47 putc(tab[(uc >> 4) & 0x0f], fp);
48 putc(tab[uc & 0x0f], fp);
49 } else {
50 putc(uc, fp);
51 }
52 }
53 }
54
55 /* Escape characters below as HTML 2.0 / XML 1.0. */
56 void
57 xmlencode(FILE *fp, const char *s, size_t len)
58 {
59 size_t i;
60
61 for (i = 0; *s && i < len; s++, i++) {
62 switch(*s) {
63 case '<': fputs("&lt;", fp); break;
64 case '>': fputs("&gt;", fp); break;
65 case '\'': fputs("&#39;" , fp); break;
66 case '&': fputs("&amp;", fp); break;
67 case '"': fputs("&quot;", fp); break;
68 default: putc(*s, fp);
69 }
70 }
71 }
72
73 void
74 printtimeshort(FILE *fp, const git_time *intime)
75 {
76 struct tm *intm;
77 time_t t;
78 char out[32];
79
80 t = (time_t)intime->time;
81 if (!(intm = gmtime(&t)))
82 return;
83 strftime(out, sizeof(out), "%Y-%m-%d %H:%M", intm);
84 fputs(out, fp);
85 }
86
87 void
88 writeheader(FILE *fp)
89 {
90 fputs("<!DOCTYPE html>\n"
91 "<html>\n<head>\n"
92 "<meta http-equiv=\"Content-Type\" content=\"text/html; …
93 "<meta name=\"viewport\" content=\"width=device-width, i…
94 "<title>", fp);
95 xmlencode(fp, description, strlen(description));
96 fprintf(fp, "</title>\n<link rel=\"icon\" type=\"image/png\" hre…
97 fprintf(fp, "<link rel=\"stylesheet\" type=\"text/css\" href=\"%…
98 fputs("</head>\n<body>\n", fp);
99 fprintf(fp, "<table style=\"width:100%%\">\n<tr><td style=\"whit…
100 "<td style=\"width:99%%\"><span class=\"desc\">", relpat…
101 xmlencode(fp, description, strlen(description));
102 fprintf(fp, "<br />\n%s", releaselink);
103 fputs("</span></td>", fp);
104 fprintf(fp, "<td style=\"text-align:right;white-space:nowrap\">%…
105 fputs("</tr><tr><td></td><td>\n"
106 "</td></tr>\n</table>\n<hr/>\n<div id=\"content\">\n"
107 "<table id=\"index\"><thead>\n"
108 "<tr><td><b>Name</b></td><td><b>Description</b></td><td>…
109 "<td><b>Last commit (UTC)</b></td></tr>"
110 "</thead><tbody>\n", fp);
111 }
112
113 void
114 writefooter(FILE *fp)
115 {
116 fputs("</tbody>\n</table>\n</div>\n</body>\n</html>\n", fp);
117 }
118
119 int
120 writelog(FILE *fp)
121 {
122 git_commit *commit = NULL;
123 const git_signature *author;
124 git_revwalk *w = NULL;
125 git_oid id;
126 char *stripped_name = NULL, *p;
127 int ret = 0;
128
129 git_revwalk_new(&w, repo);
130 git_revwalk_push_head(w);
131
132 if (git_revwalk_next(&id, w) ||
133 git_commit_lookup(&commit, repo, &id)) {
134 ret = -1;
135 goto err;
136 }
137
138 author = git_commit_author(commit);
139
140 /* strip .git suffix */
141 if (!(stripped_name = strdup(name)))
142 err(1, "strdup");
143 if ((p = strrchr(stripped_name, '.')))
144 if (!strcmp(p, ".git"))
145 *p = '\0';
146
147 fputs("<tr><td><a href=\"", fp);
148 percentencode(fp, stripped_name, strlen(stripped_name));
149 fputs("/log.html\">", fp);
150 xmlencode(fp, stripped_name, strlen(stripped_name));
151 fputs("</a></td><td>", fp);
152 xmlencode(fp, description, strlen(description));
153 fputs("</td><td>", fp);
154 xmlencode(fp, owner, strlen(owner));
155 fputs("</td><td>", fp);
156 if (author)
157 printtimeshort(fp, &(author->when));
158 fputs("</td></tr>", fp);
159
160 git_commit_free(commit);
161 err:
162 git_revwalk_free(w);
163 free(stripped_name);
164
165 return ret;
166 }
167
168 int
169 main(int argc, char *argv[])
170 {
171 FILE *fp;
172 char path[PATH_MAX], repodirabs[PATH_MAX + 1];
173 const char *repodir;
174 int i, ret = 0;
175
176 if (argc < 2) {
177 fprintf(stderr, "%s [repodir...]\n", argv[0]);
178 return 1;
179 }
180
181 git_libgit2_init();
182
183 #ifdef __OpenBSD__
184 if (pledge("stdio rpath", NULL) == -1)
185 err(1, "pledge");
186 #endif
187
188 writeheader(stdout);
189
190 for (i = 1; i < argc; i++) {
191 repodir = argv[i];
192 if (!realpath(repodir, repodirabs))
193 err(1, "realpath");
194
195 if (git_repository_open_ext(&repo, repodir,
196 GIT_REPOSITORY_OPEN_NO_SEARCH, NULL)) {
197 fprintf(stderr, "%s: cannot open repository\n", …
198 ret = 1;
199 continue;
200 }
201
202 /* use directory name as name */
203 if ((name = strrchr(repodirabs, '/')))
204 name++;
205 else
206 name = "";
207
208 /* read description or .git/description */
209 joinpath(path, sizeof(path), repodir, "description");
210 if (!(fp = fopen(path, "r"))) {
211 joinpath(path, sizeof(path), repodir, ".git/desc…
212 fp = fopen(path, "r");
213 }
214 description[0] = '\0';
215 if (fp) {
216 if (!fgets(description, sizeof(description), fp))
217 description[0] = '\0';
218 fclose(fp);
219 }
220
221 /* read owner or .git/owner */
222 joinpath(path, sizeof(path), repodir, "owner");
223 if (!(fp = fopen(path, "r"))) {
224 joinpath(path, sizeof(path), repodir, ".git/owne…
225 fp = fopen(path, "r");
226 }
227 owner[0] = '\0';
228 if (fp) {
229 if (!fgets(owner, sizeof(owner), fp))
230 owner[0] = '\0';
231 owner[strcspn(owner, "\n")] = '\0';
232 fclose(fp);
233 }
234 writelog(stdout);
235 }
236 writefooter(stdout);
237
238 /* cleanup */
239 git_repository_free(repo);
240 git_libgit2_shutdown();
241
242 return ret;
243 }
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.