2 cehtehs git web frontend
5 2007, 2008, Christian Thaeter <ct@pipapo.org>
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.
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.
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/>.
36 /* todo configure this */
37 #define SHA1_HEADER <openssl/sha.h>
38 #include "git/cache.h"
45 webgit_main_link (struct webgit_query* query, Html text)
49 html_attr ("href", html_str (query->request->script_name))
57 Main (repository list) page
60 webgit_main_menu_action (struct webgit_query* query)
62 return html (html_tag ("div"),
65 html_attr ("src", webgit_webskinpath (query, "icons/webgit_logo.png")),
66 html_attr ("alt", "Webgit-Logo")
69 html_include (webgit_skinpath (query, "inc/site.inc")), "<br />",
72 webgit_account_link (query, html ("Preferences")), "<br />",
73 webgit_account_logout_link (query, html ("Logout")), "<br />"
76 webgit_account_link (query, html ("Account")), "<br />"
80 html_attr ("href", webgit_webskinpath (query, "inc/about.html"))
88 webgit_main_content_action (struct webgit_query* query)
90 Html table_head = html_list ();
91 Html table_body = html_list ();
93 html_list_append (table_head, html(
95 html(html_tag ("th"),"Name"),
96 html(html_tag ("th"),"Git URL"),
97 html(html_tag ("th"),"Description"),
98 html(html_tag ("th"),"Owner"),
99 html(html_tag ("th"),"Last Change"),
100 html(html_tag ("th"),"Author"),
101 html(html_tag ("th"),"Committer"),
102 html(html_tag ("th"),"Action")
110 LLIST_FOREACH (&query->repos, node)
112 struct webgit_repo_info* n = (struct webgit_repo_info*)node;
114 webgit_repoinfo_find_last (n);
116 if (n->age < n->maxage)
118 html_list_append (table_body, html (
120 html_attr ("class", (++row & 1) ? "odd" : "even")
122 html(html_tag ("td"),
123 webgit_summary_link (query, n, html (n->name))),
124 html(html_tag ("td"), n->url ?
126 html_tag ("a", html_attr ("href", n->url)),
130 html(html_tag ("td"), n->description),
131 html(html_tag ("td"), n->owner),
132 html(html_tag ("td"),
133 webgit_object_link (query, webgit_pretty_age (n->age),
136 "commit", n->last_commit)
138 html(html_tag ("td"),
140 html (n->last_author_name),
141 html (n->last_author_email)
144 html(html_tag ("td"),
146 html (n->last_committer_name),
147 html (n->last_committer_email)
150 html(html_tag ("td"),
152 webgit_log_link (query,
161 //webgit_diff_link (query, n, n->last_head, html("Diff")),
163 webgit_object_link (query, html("Tree"),
166 "commit", n->last_commit,
179 html_attr ("id", "summary"),
180 html_attr ("class", "sortable"),
181 html_attr ("cellpadding", "0"),
182 html_attr ("cellspacing", "0")
184 html( html_tag("thead"), table_head),
185 html( html_tag("tbody"), table_body)
190 webgit_main_action (struct webgit_query* query)
193 html(html_tag("div", html_attr ("id", "sub-menu")), webgit_main_menu_action (query)), html_nl (),
194 html(html_tag("div", html_attr ("id", "content")), webgit_main_content_action (query)), html_nl ()
200 Summary of a single repository
203 webgit_summary_menu_action (struct webgit_repo_info* repo)
205 return html (html_tag ("div"),
206 webgit_repo_logo (repo), "<br />",
207 repo->readme ? html_include (repo->readme) : html (), "<br />",
210 html_attr ("href", html_fmt ("%s?repo=%s&action=config",
211 repo->query->request->script_name,
217 webgit_main_link (repo->query, html ("Main")), "<br />"
223 webgit_summary_content_action (struct webgit_repo_info* repo)
225 Html content = html_list ();
228 html_list_append (content, html (html_tag ("h1"), repo->description));
232 html_list_append (content, html_include (repo->readme));
235 html_list_append (content,
237 html (html_tag ("h2"), "Repository information"),
243 html_tag ("a", html_attr ("href", repo->url)),
249 "Owner: ", repo->owner
254 webgit_object_link (repo->query, webgit_pretty_age (repo->age),
256 "ref", repo->last_head,
257 "commit", repo->last_commit),
259 webgit_log_link (repo->query,
264 html ("'", repo->last_head, "'")
271 html_list_append (content,
273 html (html_tag ("h2"),
274 webgit_log_link (repo->query, repo->name, repo->last_head,
275 NULL, 0, repo->query->count,
276 html ("Log of branch '", repo->last_head, "'")
279 webgit_log_table (repo->query, repo->last_head, repo->last_head, 5 /*TODO: config this*/, 0))
284 html_list_append (content,
286 html (html_tag ("h2"),
287 webgit_branch_link (repo, NULL, repo->query->count,
291 webgit_branch_table (repo, NULL, 5 /*TODO: config this*/)
296 html_list_append (content,
298 html (html_tag ("h2"),
299 webgit_tag_link (repo, NULL, repo->query->count,
303 webgit_tag_table (repo, NULL, 5 /*TODO: config this*/)
312 webgit_summary_action (struct webgit_query* query)
314 struct webgit_repo_info* repo = webgit_repo_enter (query);
315 webgit_repoinfo_find_last (repo);
318 html(html_tag("div", html_attr ("id", "sub-menu")), webgit_summary_menu_action (repo)), html_nl (),
319 html(html_tag("div", html_attr ("id", "content")), webgit_summary_content_action (repo)), html_nl ()
328 webgit_log_action (struct webgit_query* query)
330 struct webgit_repo_info* repo = webgit_repo_enter (query);
333 html(html_tag("div", html_attr ("id", "sub-menu")), webgit_log_menu_action (repo)), html_nl (),
334 html(html_tag("div", html_attr ("id", "content")), webgit_log_content_action (repo)), html_nl ()
343 webgit_diff_action (struct webgit_query* query)
347 return html (html_tag ("div"),
349 "Readme.html <br />",
350 "User (cookie) config <br />",
351 "About webgit (info/admin) <br />"
359 pretty printed objects
362 webgit_object_action (struct webgit_query* query)
364 struct webgit_repo_info* repo = webgit_repo_enter (query);
365 webgit_object_deduce (query);
367 unsigned char sha1[20];
368 if (get_sha1 (query->object, sha1))
369 return html("error: unknown object");
371 switch (sha1_object_info(sha1, NULL))
374 return webgit_object_commit_action (repo, sha1);
376 return webgit_object_tree_action (repo, sha1);
378 return webgit_object_blob_action (repo, sha1);
380 return webgit_object_tag_action (repo, sha1);
384 return html ("error: unknown object type");
394 webgit_raw_action (struct webgit_query* query)
396 webgit_repo_enter (query);
397 webgit_object_deduce (query);
399 unsigned char sha1[20];
400 if (get_sha1 (query->object, sha1))
401 return html("error: unknown object");
406 buf = read_object_with_reference (sha1, "blob", &size, NULL);
408 free ((char*)query->content_type);
409 query->content_type = webgit_mimetype (query->path);
411 return html_binary (buf, size);
419 webgit_branch_menu_action (struct webgit_repo_info* repo)
421 return html (html_tag ("div"),
422 webgit_repo_logo (repo), "<br />",
423 // TODO: "switch-branch-dropdown <br />",
424 // TODO: "push/fetch/merge <br />",
425 // TODO: "branch administation <br />",
426 webgit_summary_link (repo->query, repo, html("Summary")), "<br />",
427 webgit_main_link (repo->query, html ("Main"))
433 webgit_branch_action (struct webgit_query* query)
435 struct webgit_repo_info* repo = webgit_repo_enter (query);
436 webgit_repoinfo_find_last (repo);
439 html(html_tag("div", html_attr ("id", "sub-menu")), webgit_branch_menu_action (repo)), html_nl (),
440 html(html_tag("div", html_attr ("id", "content")),
441 webgit_branch_table (repo, query->head, query->count), html_nl ())
450 webgit_tag_menu_action (struct webgit_repo_info* repo)
453 return html (html_tag ("div"),
454 webgit_repo_logo (repo), "<br />",
455 // TODO: "tag administation <br />",
456 webgit_summary_link (repo->query, repo, html("Summary")), "<br />",
457 webgit_main_link (repo->query, html ("Main"))
463 webgit_tag_action (struct webgit_query* query)
465 struct webgit_repo_info* repo = webgit_repo_enter (query);
466 webgit_repoinfo_find_last (repo);
469 html(html_tag("div", html_attr ("id", "sub-menu")), webgit_tag_menu_action (repo)), html_nl (),
470 html(html_tag("div", html_attr ("id", "content")),
471 webgit_tag_table (repo, query->head, query->count), html_nl ())
480 webgit_config_menu_action (struct webgit_repo_info* repo)
483 return html (html_tag ("div"),
484 webgit_repo_logo (repo), "<br />",
485 // TODO: "manage remotes? <br />",
486 // TODO: "manage subprojects? <br />",
487 webgit_summary_link (repo->query, repo, html("Summary")), "<br />",
488 webgit_main_link (repo->query, html ("Main"))
493 webgit_config_content_action (struct webgit_repo_info* repo)
495 int readonly = !!access (git_path("config"), W_OK);
499 html_attr ("name", "config-change"),
500 html_attr ("enctype", "multipart/form-data"),
501 html_attr ("method", "post"),
504 repo->query->request->script_name
509 html_hidden ("repo", repo->name),
510 html_hidden ("action", "config"),
512 html_tag ("textarea",
513 html_attr ("name", "blob"),
514 html_attr ("rows", "40"),
515 html_attr ("cols", "80"),
516 readonly ? "readonly" : ""
518 html_include_escaped (git_path("config"))
523 html_attr ("type", "submit"),
524 html_attr ("value", "Save")
531 webgit_config_action (struct webgit_query* query)
533 struct webgit_repo_info* repo = webgit_repo_enter (query);
534 webgit_repoinfo_find_last (repo);
538 FILE* cfg = fopen (git_path ("config"), "w");
542 webgit_warn ("could not open %s for writing", git_path("config"));
545 if (fwrite (query->blob, query->blob_size, 1, cfg) < 1)
546 webgit_warn ("could not write config");
552 html (html_tag ("div", html_attr("id", "sub-menu")), webgit_config_menu_action (repo)), html_nl (),
553 html (html_tag ("div", html_attr("id", "content")), webgit_config_content_action (repo)), html_nl ()
562 webgit_account_action (struct webgit_query* query)
565 html(html_tag("div", html_attr ("id", "sub-menu")), webgit_account_menu_action (query)), html_nl (),
566 html(html_tag("div", html_attr ("id", "content")), webgit_account_content_action (query)), html_nl ()
575 webgit_edit_action (struct webgit_query* query)
577 struct webgit_repo_info* repo = webgit_repo_enter (query);
578 webgit_object_deduce (query);
580 unsigned char sha1[20];
581 if (!query->object || get_sha1 (query->object, sha1))
582 return html("error: unknown object");
584 switch (sha1_object_info(sha1, NULL))
587 return webgit_edit_blob_action (repo, sha1);
594 return html ("error: unknown object type");
604 webgit_commit_action (struct webgit_query* query)
607 return html("commit");
612 webgit_action_dispatch (struct webgit_query* query)
614 #define WEBGIT_ACTION(name, _) \
617 webgit_##name##_action, \
621 Html (*cb)(struct webgit_query* query);
622 } cmds[] = {WEBGIT_ACTIONS {"", NULL}};
625 for (struct action_table* j = cmds; j->cb; ++j)
627 if (!strcmp (j->name, query->action))
628 return j->cb (query);
630 return html("error, no such action");
638 // c-file-style: "gnu"
639 // indent-tabs-mode: nil