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