322d3c665b276ba9ad7de3bba9a9053f6292e581
[webgit] / src / actions.c
1 /*
2     cehtehs git web frontend
3
4   Copyright (C)
5     2007,               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 "actions.h"
23 #include "summary.h"
24 #include "object.h"
25 #include "log.h"
26 #include "repo.h"
27 #include "age.h"
28 #include "branch.h"
29 #include "tag.h"
30
31 #include "llist.h"
32 #include <cwa.h>
33
34 /* todo configure this */
35 #define SHA1_HEADER <openssl/sha.h>
36 #include "git/cache.h"
37 #include "git/refs.h"
38
39 #include <stdio.h>
40
41
42 /*
43   Main (repository list) page
44 */
45 static Html
46 webgit_main_menu_action (struct webgit_query* query)
47 {
48   (void) query;
49   return html ("TODO: main menu");
50 }
51
52 static Html
53 webgit_header_action (struct webgit_query* query)
54 {
55   (void) query;
56   return html (
57                            "webgit header action"
58                            );
59 }
60
61 static Html
62 webgit_main_content_action (struct webgit_query* query)
63 {
64   Html table = html_list ();
65
66   html_list_append (table, html(
67                           html(html_tag ("tr"),
68                                html(html_tag ("th"),"Name"),
69                                html(html_tag ("th"),"Git URL"),
70                                html(html_tag ("th"),"Description"),
71                                html(html_tag ("th"),"Owner"),
72                                html(html_tag ("th"),"Last Change"),
73                                html(html_tag ("th"),"Author"),
74                                html(html_tag ("th"),"Committer"),
75                                html(html_tag ("th"),"Action")
76                                ),
77                           html_nl()
78                           )
79               );
80
81   LLIST_FOREACH (&query->repos, node)
82     {
83       struct webgit_repo_info* n = (struct webgit_repo_info*)node;
84
85       webgit_repoinfo_find_last (n);
86
87       html_list_append (table, html (
88                                      html_tag ("tr"),
89                                      html(html_tag ("td"),
90                                           webgit_summary_link (query, n, html (n->name))),
91                                      html(html_tag ("td"), n->url ?
92                                           html (
93                                                 html_tag ("a", html_attr ("href", n->url)),
94                                                 n->url)
95                                           : html("N/A")
96                                           ),
97                                      html(html_tag ("td"), n->description),
98                                      html(html_tag ("td"), n->owner),
99                                      html(html_tag ("td"),
100                                           webgit_object_link (query,
101                                                               n->name, strlen(n->name),
102                                                               n->last_commit, 40,
103                                                               NULL,
104                                                               NULL,
105                                                               webgit_pretty_age (n->age))
106                                           ),
107                                      html(html_tag ("td"),
108                                           webgit_email_link (
109                                                              html (n->last_author_name),
110                                                              html (n->last_author_email)
111                                                              )
112                                           ),
113                                      html(html_tag ("td"),
114                                           webgit_email_link (
115                                                              html (n->last_committer_name),
116                                                              html (n->last_committer_email)
117                                                              )
118                                           ),
119                                      html(html_tag ("td"),
120                                           html(
121                                                webgit_log_link (query,
122                                                                 n->name,
123                                                                 n->last_head,
124                                                                 NULL, 0,
125                                                                 query->count,
126                                                                 html("Log")
127                                                                 ),
128                                                " ",
129
130                                                "Diff ",
131                                                //webgit_diff_link (query, n, n->last_head, html("Diff")),
132                                                //" ",
133                                                webgit_object_link (query,
134                                                                    n->name, strlen(n->name),
135                                                                    n->last_tree, 40,
136                                                                    NULL,
137                                                                    NULL,
138                                                                    html("Tree"))
139                                                )
140                                           )
141                                      ),
142                         html_nl()
143                         );
144     }
145
146   return html (html_tag ("table", html_attr ("id", "summary")), table);
147 }
148
149 static Html
150 webgit_main_action (struct webgit_query* query)
151 {
152   return html(
153               html(html_tag("div", html_attr("id", "header-action")), webgit_header_action (query)) , html_nl (),
154               html(html_tag("div", html_attr("id", "main-menu")), webgit_main_menu_action (query)), html_nl (),
155               html(html_tag("div"), webgit_main_content_action (query)), html_nl ()
156               );
157 }
158
159
160 /*
161   Summary of a single repository
162 */
163 static Html
164 webgit_summary_menu_action (struct webgit_repo_info* repo)
165 {
166   (void) repo;
167   return html ("TODO: summary");
168 }
169
170
171 static Html
172 webgit_summary_content_action (struct webgit_repo_info* repo)
173 {
174   Html content = html_list ();
175
176   /* Title */
177   html_list_append (content, html (html_tag ("h1"), repo->description));
178
179   /* Readme */
180   if (repo->readme)
181     html_list_append (content, html_include (repo->readme));
182
183   /* Info */
184   html_list_append (content,
185                     html (
186                           html (html_tag ("h2"), "Repository information"),
187                           repo->url ?
188                           html (
189                                 html_tag ("div"),
190                                 "Public URL: ",
191                                 html (
192                                       html_tag ("a", html_attr ("href", repo->url)),
193                                       repo->url
194                                       )
195                                 ) : html(),
196                           html (
197                                 html_tag ("div"),
198                                 "Owner: ", repo->owner
199                                 ),
200                           html(
201                                html_tag ("div"),
202                                "Last change: ",
203                                webgit_object_link (repo->query,
204                                                    repo->name, strlen(repo->name),
205                                                    repo->last_commit, 40,
206                                                    NULL,
207                                                    NULL,
208                                                    webgit_pretty_age (repo->age)),
209                                " in branch ",
210                                 webgit_log_link (repo->query,
211                                                  repo->name,
212                                                  repo->last_head,
213                                                  NULL, 0,
214                                                  repo->query->count,
215                                                  html ("'", repo->last_head, "'")
216                                                  )
217                                )
218                           )
219                     );
220
221   /* log */
222   html_list_append (content,
223                     html (
224                           html (html_tag ("h2"), "Log of branch '", repo->last_head, "'"),
225                           webgit_log_table (repo->query, repo->last_head, 5 /*TODO: config this*/, 0))
226                     );
227
228
229   /* branches */
230   html_list_append (content,
231                     html (
232                           html (html_tag ("h2"), "Branches"),
233                           webgit_branch_table (repo, NULL, 5 /*TODO: config this*/)
234                           )
235                     );
236
237   /* tags */
238   html_list_append (content,
239                     html (
240                           html (html_tag ("h2"), "Tags"),
241                           webgit_tag_table (repo, NULL, 5 /*TODO: config this*/)
242                           )
243                     );
244
245
246   return content;
247 }
248
249
250 static Html
251 webgit_summary_action (struct webgit_query* query)
252 {
253   struct webgit_repo_info* repo = webgit_repo_enter (query);
254   webgit_repoinfo_find_last (repo);
255
256   return html(
257               html(html_tag("div"), webgit_summary_menu_action (repo)), html_nl (),
258               html(html_tag("div"), webgit_summary_content_action (repo)), html_nl ()
259               );
260 }
261
262
263 /*
264   Log page
265 */
266 static Html
267 webgit_log_action (struct webgit_query* query)
268 {
269   webgit_repo_enter (query);
270
271   return html(
272               html(html_tag("div"), webgit_log_menu_action (query)), html_nl (),
273               html(html_tag("div"), webgit_log_content_action (query)), html_nl ()
274               );
275 }
276
277
278 /*
279   Diff page
280 */
281 static Html
282 webgit_diff_action (struct webgit_query* query)
283 {
284   (void) query;
285   return html("diff");
286 }
287
288
289 /*
290   pretty printed objects
291 */
292 static Html
293 webgit_object_action (struct webgit_query* query)
294 {
295   struct webgit_repo_info* repo = webgit_repo_enter (query);
296
297   unsigned char sha1[20];
298   if (get_sha1 (query->object, sha1))
299     return html("error: unknown object");
300
301   switch (sha1_object_info(sha1, NULL))
302     {
303     case OBJ_COMMIT:
304       if (!query->deref_to_tree)
305         return webgit_object_commit_action (repo, sha1);
306       /* else fallthrough */
307     case OBJ_TREE:
308       return webgit_object_tree_action (repo, sha1);
309     case OBJ_BLOB:
310       return webgit_object_blob_action (repo, sha1);
311     case OBJ_TAG:
312       return webgit_object_tag_action (repo, sha1);
313
314       break;
315     default:
316       return html ("error: unknown object type");
317       break;
318     }
319 }
320
321
322 /*
323   treeish dereferenced to tree
324 */
325 static Html
326 webgit_tree_action (struct webgit_query* query)
327 {
328   query->deref_to_tree = 1;
329   return webgit_object_action (query);
330 }
331
332
333 /*
334   spew out raw data
335 */
336 static Html
337 webgit_raw_action (struct webgit_query* query)
338 {
339   webgit_repo_enter (query);
340
341   unsigned char sha1[20];
342   if (get_sha1 (query->object, sha1))
343     return html("error: unknown object");
344
345   void* buf;
346   unsigned long size;
347
348   buf = read_object_with_reference (sha1, "blob", &size, NULL);
349
350   free ((char*)query->content_type);
351   query->content_type = webgit_mimetype (query->path);
352
353   return html_binary (buf, size);
354 }
355
356
357 /*
358   show branch
359 */
360 static Html
361 webgit_branch_menu_action (struct webgit_repo_info* repo)
362 {
363   (void) repo;
364   return html ("TODO: branch sidebar");
365 }
366
367
368 static Html
369 webgit_branch_action (struct webgit_query* query)
370 {
371   struct webgit_repo_info* repo = webgit_repo_enter (query);
372   webgit_repoinfo_find_last (repo);
373
374   return html(
375                           html(html_tag("div", html_attr("id", "header")), webgit_header_action (query)) , html_nl (),
376               html(html_tag("div"), webgit_branch_menu_action (repo)), html_nl (),
377               html(html_tag("div"), webgit_branch_table (repo, query->head, query->count), html_nl ())
378               );
379 }
380
381
382 /*
383   show tag
384 */
385 static Html
386 webgit_tag_action (struct webgit_query* query)
387 {
388   (void) query;
389   return html("tag");
390 }
391
392
393 /*
394   show and edit config
395 */
396 static Html
397 webgit_config_menu_action (struct webgit_repo_info* repo)
398 {
399   (void) repo;
400   return html ("TODO: config menu");
401 }
402
403 static Html
404 webgit_config_content_action (struct webgit_repo_info* repo)
405 {
406   return html (
407                html_tag ("form",
408                          html_attr ("name", "config-change"),
409                          html_attr ("enctype", "multipart/form-data"),
410                          html_attr ("method", "post"),
411                          html_attr ("action",
412                                     html_fmt ("%s",
413                                               repo->query->request->script_name
414                                               )
415                                     )
416                          ),
417
418                html_hidden ("repo", repo->name),
419                html_hidden ("action", "config"),
420                html (
421                      html_tag ("textarea",
422                                html_attr ("name", "blob"),
423                                html_attr ("rows", "40"),
424                                html_attr ("cols", "80")
425                                )//,
426                      //html_include_escaped (git_path("config"))
427                      ),
428                html (
429                      html_tag ("input",
430                                html_attr ("type", "submit"),
431                                html_attr ("value", "Save")
432                                )
433                      )
434                );
435 }
436
437 static Html
438 webgit_config_action (struct webgit_query* query)
439 {
440   struct webgit_repo_info* repo = webgit_repo_enter (query);
441   webgit_repoinfo_find_last (repo);
442
443   if (query->blob)
444     {
445       FILE* cfg = fopen (git_path ("config"), "w");
446  
447       /*TODO rxpd check */
448       if (!cfg)
449         webgit_warn ("could not open %s for writing", git_path("config"));
450       else
451         {
452           if (fwrite (query->blob, query->blob_size, 1, cfg) < 1)
453             webgit_warn ("could not write config");
454           fclose (cfg);
455         }
456     }
457
458   return html(
459               html (html_tag ("div"), webgit_config_menu_action (repo)), html_nl (),
460               html (html_tag ("div"), webgit_config_content_action (repo)), html_nl ()
461               );
462 }
463
464
465 /*
466   edit an object
467 */
468 static Html
469 webgit_edit_action (struct webgit_query* query)
470 {
471   (void) query;
472   return html("edit");
473 }
474
475 /*
476   commit changes
477 */
478 static Html
479 webgit_commit_action (struct webgit_query* query)
480 {
481   (void) query;
482   return html("commit");
483 }
484
485
486 Html
487 webgit_action_dispatch (struct webgit_query* query)
488 {
489 #define WEBGIT_ACTION(name, _)                  \
490 {                                               \
491  #name,                                         \
492  webgit_##name##_action,                        \
493 },
494   struct action_table{
495     char* name;
496     Html (*cb)(struct webgit_query* query);
497   } cmds[] = {WEBGIT_ACTIONS {"", NULL}};
498 #undef WEBGIT_ACTION
499
500   for (struct action_table* j = cmds; j->cb; ++j)
501     {
502       if (!strcmp (j->name, query->action))
503         return j->cb (query);
504     }
505   return html("error, no such action");
506 }
507
508