add atom feed support + some fixes
1 files changed, 115 insertions(+), 40 deletions(-) | |||
---|---|---|---|
M | urmoms.c | +115 | -40 |
1@@ -22,10 +22,10 @@ static int hasreadme, haslicense;
2 int
3 writeheader(FILE *fp)
4 {
5- fprintf(fp, "<!DOCTYPE HTML>"
6+ fputs("<!DOCTYPE HTML>"
7 "<html dir=\"ltr\" lang=\"en\"><head>"
8 "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />"
9- "<meta http-equiv=\"Content-Language\" content=\"en\" />");
10+ "<meta http-equiv=\"Content-Language\" content=\"en\" />", fp);
11 fprintf(fp, "<title>%s%s%s</title>", name, description[0] ? " - " : "", description);
12 fprintf(fp, "<link rel=\"icon\" type=\"image/png\" href=\"%sfavicon.png\" />", relpath);
13 fprintf(fp, "<link rel=\"alternate\" type=\"application/atom+xml\" title=\"%s Atom Feed\" href=\"%satom.xml\" />",
14@@ -35,13 +35,13 @@ writeheader(FILE *fp)
15 fprintf(fp, "<h1><img src=\"%slogo.png\" alt=\"\" /> %s</h1>", relpath, name);
16 fprintf(fp, "<span class=\"desc\">%s</span><br/>", description);
17 fprintf(fp, "<a href=\"%slog.html\">Log</a> |", relpath);
18- fprintf(fp, "<a href=\"%sfiles.html\">Files</a>| ", relpath);
19+ fprintf(fp, "<a href=\"%sfiles.html\">Files</a> | ", relpath);
20 fprintf(fp, "<a href=\"%sstats.html\">Stats</a>", relpath);
21 if (hasreadme)
22 fprintf(fp, " | <a href=\"%sreadme.html\">README</a>", relpath);
23 if (haslicense)
24 fprintf(fp, " | <a href=\"%slicense.html\">LICENSE</a>", relpath);
25- fprintf(fp, "</center><hr/><pre>");
26+ fputs("</center><hr/><pre>", fp);
27
28 return 0;
29 }
30@@ -49,9 +49,7 @@ writeheader(FILE *fp)
31 int
32 writefooter(FILE *fp)
33 {
34- fprintf(fp, "</pre></body></html>");
35-
36- return 0;
37+ return !fputs("</pre></body></html>", fp);
38 }
39
40 FILE *
41@@ -104,6 +102,32 @@ xbasename(const char *path)
42 return b;
43 }
44
45+void
46+printtimez(FILE *fp, const git_time *intime)
47+{
48+ struct tm *intm;
49+ time_t t;
50+ int offset, hours, minutes;
51+ char sign, out[32];
52+
53+ offset = intime->offset;
54+ if (offset < 0) {
55+ sign = '-';
56+ offset = -offset;
57+ } else {
58+ sign = '+';
59+ }
60+
61+ hours = offset / 60;
62+ minutes = offset % 60;
63+
64+ t = (time_t) intime->time + (intime->offset * 60);
65+
66+ intm = gmtime(&t);
67+ strftime(out, sizeof(out), "%Y-%m-%dT%H:%M:%SZ", intm);
68+ fputs(out, fp);
69+}
70+
71 void
72 printtime(FILE *fp, const git_time *intime)
73 {
74@@ -328,6 +352,7 @@ writelog(FILE *fp)
75
76 /* TODO: show tag when commit has it */
77
78+ /* TODO: collect stats per author and make stats.html page */
79 author = git_commit_author(commit);
80 summary = git_commit_summary(commit);
81
82@@ -366,29 +391,107 @@ writelog(FILE *fp)
83 return 0;
84 }
85
86-#if 0
87+void
88+printcommitatom(FILE *fp, git_commit *commit)
89+{
90+ const git_signature *sig;
91+ char buf[GIT_OID_HEXSZ + 1];
92+ int i, count;
93+ const char *scan, *eol, *summary;
94+
95+ fputs("<entry>", fp);
96+
97+ /* TODO: show tag when commit has it */
98+ git_oid_tostr(buf, sizeof(buf), git_commit_id(commit));
99+ fprintf(fp, "<id>%s</id>", buf);
100+
101+ sig = git_commit_author(commit);
102+
103+ if (sig) {
104+ fputs("<updated>", fp);
105+ printtimez(fp, &sig->when);
106+ fputs("</updated>", fp);
107+ }
108+
109+ if ((summary = git_commit_summary(commit))) {
110+ fputs("<title>", fp);
111+ xmlencode(fp, summary, strlen(summary));
112+ fputs("</title>", fp);
113+ }
114+
115+ fputs("<content type=\"text\">", fp);
116+ fprintf(fp, "commit %s\n", buf);
117+ if (git_oid_tostr(buf, sizeof(buf), git_commit_parent_id(commit, 0)))
118+ fprintf(fp, "parent %s\n", buf);
119+
120+ if ((count = (int)git_commit_parentcount(commit)) > 1) {
121+ fprintf(fp, "Merge:");
122+ for (i = 0; i < count; ++i) {
123+ git_oid_tostr(buf, 8, git_commit_parent_id(commit, i));
124+ fprintf(fp, " %s", buf);
125+ }
126+ fputc('\n', fp);
127+ }
128+
129+ if (sig) {
130+ fprintf(fp, "Author: ");
131+ xmlencode(fp, sig->name, strlen(sig->name));
132+ fprintf(fp, " <");
133+ xmlencode(fp, sig->email, strlen(sig->email));
134+ fprintf(fp, ">\nDate: ");
135+ printtime(fp, &sig->when);
136+ }
137+ fputc('\n', fp);
138+
139+ for (scan = git_commit_message(commit); scan && *scan;) {
140+ for (eol = scan; *eol && *eol != '\n'; ++eol) /* find eol */
141+ ;
142+
143+ fprintf(fp, " %.*s\n", (int) (eol - scan), scan);
144+ scan = *eol ? eol + 1 : NULL;
145+ }
146+ fputc('\n', fp);
147+ fputs("</content>", fp);
148+ if (sig) {
149+ fputs("<author><name>", fp);
150+ xmlencode(fp, sig->name, strlen(sig->name));
151+ fputs("</name><email>", fp);
152+ xmlencode(fp, sig->email, strlen(sig->email));
153+ fputs("</email></author>", fp);
154+ }
155+ fputs("</entry>", fp);
156+}
157+
158 int
159 writeatom(FILE *fp)
160 {
161 git_revwalk *w = NULL;
162 git_oid id;
163 git_commit *c = NULL;
164+ size_t i, m = 100; /* max */
165+
166+ fputs("<feed xmlns=\"http://www.w3.org/2005/Atom\"><title>", fp);
167+ xmlencode(fp, name, strlen(name));
168+ fputs(", branch master</title><subtitle>", fp);
169+
170+ xmlencode(fp, description, strlen(description));
171+ fputs("</subtitle>", fp);
172
173 git_revwalk_new(&w, repo);
174 git_revwalk_push_head(w);
175
176- while (!git_revwalk_next(&id, w)) {
177+ for (i = 0; i < m && !git_revwalk_next(&id, w); i++) {
178 if (git_commit_lookup(&c, repo, &id))
179 return 1; /* TODO: error */
180- printcommit(fp, c);
181- printshowfile(c);
182+ printcommitatom(fp, c);
183 git_commit_free(c);
184 }
185 git_revwalk_free(w);
186
187+ fputs("</feed>", fp);
188+
189 return 0;
190 }
191-#endif
192
193 int
194 writefiles(FILE *fp)
195@@ -409,32 +512,6 @@ writefiles(FILE *fp)
196 return 0;
197 }
198
199-#if 0
200-int
201-writebranches(FILE *fp)
202-{
203- git_branch_iterator *branchit = NULL;
204- git_branch_t branchtype;
205- git_reference *branchref;
206- char branchbuf[BUFSIZ] = "";
207- int status;
208-
209- git_branch_iterator_new(&branchit, repo, GIT_BRANCH_LOCAL);
210-
211- while ((status = git_branch_next(&branchref, &branchtype, branchit)) == GIT_ITEROVER) {
212- git_reference_normalize_name(branchbuf, sizeof(branchbuf),
213- git_reference_name(branchref),
214- GIT_REF_FORMAT_ALLOW_ONELEVEL | GIT_REF_FORMAT_REFSPEC_SHORTHAND);
215-
216- /* fprintf(fp, "branch: |%s|\n", branchbuf); */
217- }
218-
219- git_branch_iterator_free(branchit);
220-
221- return 0;
222-}
223-#endif
224-
225 void
226 writeblobhtml(FILE *fp, const git_blob *blob)
227 {
228@@ -516,11 +593,9 @@ main(int argc, char *argv[])
229 writefooter(fp);
230 fclose(fp);
231
232-#if 0
233 fp = efopen("atom.xml", "w+b");
234 writeatom(fp);
235 fclose(fp);
236-#endif
237
238 fp = efopen("files.html", "w+b");
239 writeheader(fp);