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