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