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