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