adjusting id/css for object-commit
[webgit] / src / object_commit.c
1 /*
2     cehtehs git web frontend
3
4   Copyright (C)
5     2007, 2008          Christian Thaeter <ct@pipapo.org>
6
7   This program is free software; you can redistribute it and/or
8   modify it under the terms of the GNU General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "object.h"
23 #include "repo.h"
24
25 char*
26 webgit_object_commit_tree_parse (struct commit* commit)
27 {
28   char* tree = strstr (commit->buffer, "tree ");
29   if (!tree)
30     return NULL;
31   return tree + 5;
32 }
33
34 time_t
35 webgit_object_commit_author_date_parse (struct commit* commit, struct tm* tm)
36 {
37   struct tm tmp;
38   if (!tm)
39     tm = &tmp;
40
41   char* author = strstr (commit->buffer, "author ");
42   if (!author)
43     return (time_t)-1;
44
45   char* beg = strchr (author, '>');
46   if (!beg)
47     return (time_t)-1;
48
49   if (!strptime (beg + 2, "%s %Z", tm))
50     return (time_t)-1;
51
52   return mktime (tm);
53 }
54
55 Html
56 webgit_object_commit_author_name_parse (struct commit* commit)
57 {
58   char* author = strstr (commit->buffer, "author ");
59   if (!author)
60     return NULL;
61
62   char* end = strchr (author, '<');
63   if (!end)
64     return NULL;
65
66   return html_fmt ("%.*s", end-author-8, author+7);
67 }
68
69 Html
70 webgit_object_commit_author_email_parse (struct commit* commit)
71 {
72   char* author = strstr (commit->buffer, "author ");
73   if (!author)
74     return NULL;
75
76   char* beg = strchr (author, '<');
77   if (!beg)
78     return NULL;
79
80   char* end = strchr (beg, '>');
81   if (!end)
82     return NULL;
83
84
85   return html_fmt ("%.*s", end-beg-1, beg+1);
86 }
87
88 time_t
89 webgit_object_commit_committer_date_parse (struct commit* commit, struct tm* tm)
90 {
91   struct tm tmp;
92   if (!tm)
93     tm = &tmp;
94
95   char* committer = strstr (commit->buffer, "committer ");
96   if (!committer)
97     return (time_t)-1;
98
99   char* beg = strchr (committer, '>');
100   if (!beg)
101     return (time_t)-1;
102
103   if (!strptime (beg + 2, "%s %Z", tm))
104     return (time_t)-1;
105
106   return mktime (tm);
107 }
108
109 Html
110 webgit_object_commit_committer_name_parse (struct commit* commit)
111 {
112   char* committer = strstr (commit->buffer, "committer ");
113   if (!committer)
114     return NULL;
115
116   char* end = strchr (committer, '<');
117   if (!end)
118     return NULL;
119
120   return html_fmt ("%.*s", end-committer-11, committer+10);
121 }
122
123 Html
124 webgit_object_commit_committer_email_parse (struct commit* commit)
125 {
126   char* committer = strstr (commit->buffer, "committer ");
127   if (!committer)
128     return NULL;
129
130   char* beg = strchr (committer, '<');
131   if (!beg)
132     return NULL;
133
134   char* end = strchr (beg, '>');
135   if (!end)
136     return NULL;
137
138
139   return html_fmt ("%.*s", end-beg-1, beg+1);
140 }
141
142 Html
143 webgit_object_commit_header_parse (struct commit* commit)
144 {
145   char* header = strstr (commit->buffer, "\n\n");
146   if (!header)
147     return NULL;
148
149   char* end = strchr (header+2, '\n');
150   if (!end)
151     end = header + strlen (header+2);
152   else
153     --end;
154
155   return html_fmt ("%.*s", end-header, header+2);
156 }
157
158 Html
159 webgit_object_commit_message_parse (struct commit* commit)
160 {
161   char* header = strstr (commit->buffer, "\n\n");
162   if (!header)
163     return NULL;
164
165   header = strchr (header+2, '\n');
166   if (!header)
167     return html ();
168   else
169     ++header;
170
171   return html_fmt ("%.*s", strlen (header), header);
172 }
173
174
175 /*
176   Display commits
177 */
178
179 static Html
180 webgit_object_commit_menu_action (struct webgit_repo_info* repo, unsigned char* sha1, void* buf, unsigned long size)
181 {
182   (void) repo;
183   (void) sha1;
184   (void) buf;
185   (void) size;
186
187   return html ("TODO: commit-object sidebar");
188 }
189
190 static Html
191 webgit_object_commit_content_action (struct webgit_repo_info* repo, unsigned char* sha1, void* buf, unsigned long size)
192 {
193 /*
194   TODO pass commit objects instead buf/size, use parsers from above
195 */
196   (void) sha1;
197
198   Html tree = html_list ();
199   Html parents = html_list ();
200   Html author_text = html_list ();
201   Html author = html_list ();
202   Html committer = html_list ();
203
204   const char* author_beg = NULL;
205   const char* author_end = NULL;
206
207   const char* i = buf;
208   while (i && (void*)i < buf+size)
209     {
210       if (*i == '\n')
211         {
212           while (*i == '\n')
213             ++i;
214           break; /* message */
215         }
216       if (!strncmp (i, "tree ", 5))
217         {
218           html_list_append (tree,
219                             "Tree: ",
220                             webgit_object_link (repo->query,
221                                                 repo->name, strlen (repo->name),
222                                                 i+5, 40,
223                                                 NULL,
224                                                 NULL,
225                                                 html_fmt ("%.40s", i+5))
226                             );
227           if ((i = strchr (i, '\n')))
228             ++i;
229           continue;
230         }
231       else if (!strncmp (i, "parent ", 7))
232         {
233           html_list_append (parents, html (
234                                            "Parent: ",
235                                            webgit_object_link (repo->query,
236                                                                repo->name, strlen (repo->name),
237                                                                i+7, 40,
238                                                                NULL,
239                                                                NULL,
240                                                                html_fmt ("%.40s", i+7))
241                                            )
242                             );
243           if ((i = strchr (i, '\n')))
244             ++i;
245           continue;
246         }
247       else if (!strncmp (i, "author ", 7))
248         {
249           char* email_beg = strchr (i, '<');
250           char* email_end = strchr (email_beg, '>');
251
252           author_beg = i+7;
253           author_end = strchr (author_beg, '\n');
254
255           Html name = html_strndup (i+7, email_beg - i - 8);
256           Html email = html_strndup (email_beg + 1, email_end - email_beg - 1);
257
258           struct tm tm;
259           strptime (email_end + 2, "%s %Z", &tm);
260           char pretty_date[256];
261           strftime (pretty_date, 255, "%c", &tm);
262
263           html_list_append (author_text, "Author");
264
265           html_list_append (author, html (
266                                           html ( author_text ), /*BUG: libcwa bug, must be wraped in html()*/
267                                           webgit_email_link (name, email),
268                                           html_strndup (pretty_date, 255)
269                                           )
270                             );
271           if ((i = strchr (i, '\n')))
272             ++i;
273           continue;
274         }
275       else if (!strncmp (i, "committer ", 10))
276         {
277           char* email_beg = strchr (i, '<');
278           char* email_end = strchr (email_beg, '>');
279
280           if (author_beg && author_end && strncmp (i + 10, author_beg, author_end - author_beg))
281             {
282               Html name = html_strndup (i+10, email_beg - i - 11);
283               Html email = html_strndup (email_beg + 1, email_end - email_beg - 1);
284
285               struct tm tm;
286               strptime (email_end + 2, "%s %Z", &tm);
287               char pretty_date[256];
288               strftime (pretty_date, 255, "%c", &tm);
289
290               html_list_append (committer, html ("Committer: ",
291                                                  webgit_email_link (name, email),
292                                                  html_strndup (pretty_date, 255)
293                                                  )
294                                 );
295             }
296           else
297             html_list_append (author_text, " and Committer");
298
299           if ((i = strchr (i, '\n')))
300             ++i;
301           continue;
302         }
303       ++i;
304     }
305
306   html_list_append (author_text, ": ");
307
308   Html headline = html_list ();
309   Html message = html_list ();
310
311   if (i)
312     {
313       const char* message_beg = strchr (i, '\n');
314
315       if (message_beg)
316         {
317           html_list_append (headline,
318                             html_strndup (i, message_beg - i)
319                             );
320
321           while (*message_beg == '\n')
322             ++message_beg;
323
324           html_list_append (message,
325                             html_strndup (message_beg, SIZE_MAX)
326                             );
327         }
328       else
329         {
330           html_list_append (headline,
331                             html_strndup (i, SIZE_MAX)
332                             );
333           html_list_append (message,
334                             html_strndup (i, SIZE_MAX)
335                             );
336         }
337     }
338
339   /* TODO: diffstat */
340
341
342   return html (
343                html (html_tag ("h3"), headline),
344                html (html_tag ("div"), tree), html_nl (),
345                html (html_tag ("div"), parents), html_nl (),
346                html (html_tag ("div"), author), html_nl (),
347                html (html_tag ("div"), committer), html_nl (),
348                html (html_tag ("pre"), message)
349                );
350 }
351
352 Html
353 webgit_object_commit_action (struct webgit_repo_info* repo, unsigned char* sha1)
354 {
355   void* buf;
356   unsigned long size;
357
358   buf = read_object_with_reference (sha1, "commit", &size, NULL);
359
360   return html(
361                                    html(html_tag("div"), webgit_object_commit_menu_action (repo, sha1, buf, size)), html_nl (),
362                                    html(html_tag("div", html_attr ("id", "object-commit")), webgit_object_commit_content_action (repo, sha1, buf, size)), html_nl ()
363               );
364 }