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