author | Lars Hjemli <hjemli@gmail.com> | 2007-02-17 12:46:18 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2007-02-20 23:24:36 (UTC) |
commit | 66cacd053ba900c8eb3b7962027370c84a97f990 (patch) (side-by-side diff) | |
tree | 9ccd8202204bf556a186ba1520a6c767756855bf | |
parent | ac70cb4795c90db02917db63d169b0fadfe9fb99 (diff) | |
download | cgit-66cacd053ba900c8eb3b7962027370c84a97f990.zip cgit-66cacd053ba900c8eb3b7962027370c84a97f990.tar.gz cgit-66cacd053ba900c8eb3b7962027370c84a97f990.tar.bz2 |
Layout update
-rw-r--r-- | cgit.c | 13 | ||||
-rw-r--r-- | cgit.css | 98 | ||||
-rw-r--r-- | ui-diff.c | 1 | ||||
-rw-r--r-- | ui-log.c | 1 | ||||
-rw-r--r-- | ui-repolist.c | 1 | ||||
-rw-r--r-- | ui-shared.c | 37 | ||||
-rw-r--r-- | ui-summary.c | 6 | ||||
-rw-r--r-- | ui-tree.c | 1 | ||||
-rw-r--r-- | ui-view.c | 1 |
9 files changed, 127 insertions, 32 deletions
@@ -1,245 +1,254 @@ /* cgit.c: cgi for the git scm * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" const char cgit_version[] = CGIT_VERSION; static struct repoinfo *cgit_get_repoinfo(char *url) { int i; struct repoinfo *repo; for (i=0; i<cgit_repolist.count; i++) { repo = &cgit_repolist.repos[i]; if (!strcmp(repo->url, url)) return repo; } return NULL; } static int cgit_prepare_cache(struct cacheitem *item) { if (!cgit_query_repo) { item->name = xstrdup(fmt("%s/index.html", cgit_cache_root)); item->ttl = cgit_cache_root_ttl; return 1; } cgit_repo = cgit_get_repoinfo(cgit_query_repo); if (!cgit_repo) { char *title = fmt("%s - %s", cgit_root_title, "Bad request"); cgit_print_docstart(title, item); cgit_print_pageheader(title, 0); cgit_print_error(fmt("Unknown repo: %s", cgit_query_repo)); cgit_print_docend(); return 0; } if (!cgit_query_page) { item->name = xstrdup(fmt("%s/%s/index.html", cgit_cache_root, cgit_repo->url)); item->ttl = cgit_cache_repo_ttl; } else { item->name = xstrdup(fmt("%s/%s/%s/%s.html", cgit_cache_root, cgit_repo->url, cgit_query_page, cache_safe_filename(cgit_querystring))); if (cgit_query_has_symref) item->ttl = cgit_cache_dynamic_ttl; else if (cgit_query_has_sha1) item->ttl = cgit_cache_static_ttl; else item->ttl = cgit_cache_repo_ttl; } return 1; } static void cgit_print_repo_page(struct cacheitem *item) { char *title; int show_search; if (chdir(cgit_repo->path)) { title = fmt("%s - %s", cgit_root_title, "Bad request"); cgit_print_docstart(title, item); cgit_print_pageheader(title, 0); cgit_print_error(fmt("Unable to scan repository: %s", strerror(errno))); cgit_print_docend(); return; } title = fmt("%s - %s", cgit_repo->name, cgit_repo->desc); show_search = 0; setenv("GIT_DIR", cgit_repo->path, 1); if (cgit_repo->snapshots && cgit_query_page && !strcmp(cgit_query_page, "snapshot")) { cgit_print_snapshot(item, cgit_query_sha1, "zip", cgit_repo->url, cgit_query_name); return; } if (cgit_query_page && !strcmp(cgit_query_page, "log")) show_search = 1; + cgit_print_docstart(title, item); - cgit_print_pageheader(title, show_search); + + if (!cgit_query_page) { + cgit_print_pageheader("summary", show_search); cgit_print_summary(); - } else if (!strcmp(cgit_query_page, "log")) { + cgit_print_docend(); + return; + } + + cgit_print_pageheader(cgit_query_page, show_search); + + if (!strcmp(cgit_query_page, "log")) { cgit_print_log(cgit_query_head, cgit_query_ofs, 100, cgit_query_search); } else if (!strcmp(cgit_query_page, "tree")) { cgit_print_tree(cgit_query_sha1, cgit_query_path); } else if (!strcmp(cgit_query_page, "commit")) { cgit_print_commit(cgit_query_sha1); } else if (!strcmp(cgit_query_page, "view")) { cgit_print_view(cgit_query_sha1); } else if (!strcmp(cgit_query_page, "diff")) { cgit_print_diff(cgit_query_sha1, cgit_query_sha2); } else { cgit_print_error("Invalid request"); } cgit_print_docend(); } static void cgit_fill_cache(struct cacheitem *item, int use_cache) { static char buf[PATH_MAX]; int stdout2; getcwd(buf, sizeof(buf)); item->st.st_mtime = time(NULL); if (use_cache) { stdout2 = chk_positive(dup(STDOUT_FILENO), "Preserving STDOUT"); chk_zero(close(STDOUT_FILENO), "Closing STDOUT"); chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)"); } if (cgit_query_repo) cgit_print_repo_page(item); else cgit_print_repolist(item); if (use_cache) { chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT"); chk_positive(dup2(stdout2, STDOUT_FILENO), "Restoring original STDOUT"); chk_zero(close(stdout2), "Closing temporary STDOUT"); } chdir(buf); } static void cgit_check_cache(struct cacheitem *item) { int i = 0; top: if (++i > cgit_max_lock_attempts) { die("cgit_refresh_cache: unable to lock %s: %s", item->name, strerror(errno)); } if (!cache_exist(item)) { if (!cache_lock(item)) { sleep(1); goto top; } if (!cache_exist(item)) { cgit_fill_cache(item, 1); cache_unlock(item); } else { cache_cancel_lock(item); } } else if (cache_expired(item) && cache_lock(item)) { if (cache_expired(item)) { cgit_fill_cache(item, 1); cache_unlock(item); } else { cache_cancel_lock(item); } } } static void cgit_print_cache(struct cacheitem *item) { static char buf[4096]; ssize_t i; int fd = open(item->name, O_RDONLY); if (fd<0) die("Unable to open cached file %s", item->name); while((i=read(fd, buf, sizeof(buf))) > 0) write(STDOUT_FILENO, buf, i); close(fd); } static void cgit_parse_args(int argc, const char **argv) { int i; for (i = 1; i < argc; i++) { if (!strncmp(argv[i], "--cache=", 8)) { cgit_cache_root = xstrdup(argv[i]+8); } if (!strcmp(argv[i], "--nocache")) { cgit_nocache = 1; } if (!strncmp(argv[i], "--query=", 8)) { cgit_querystring = xstrdup(argv[i]+8); } if (!strncmp(argv[i], "--repo=", 7)) { cgit_query_repo = xstrdup(argv[i]+7); } if (!strncmp(argv[i], "--page=", 7)) { cgit_query_page = xstrdup(argv[i]+7); } if (!strncmp(argv[i], "--head=", 7)) { cgit_query_head = xstrdup(argv[i]+7); cgit_query_has_symref = 1; } if (!strncmp(argv[i], "--sha1=", 7)) { cgit_query_sha1 = xstrdup(argv[i]+7); cgit_query_has_sha1 = 1; } if (!strncmp(argv[i], "--ofs=", 6)) { cgit_query_ofs = atoi(argv[i]+6); } } } int main(int argc, const char **argv) { struct cacheitem item; htmlfd = STDOUT_FILENO; item.st.st_mtime = time(NULL); cgit_repolist.length = 0; cgit_repolist.count = 0; cgit_repolist.repos = NULL; cgit_read_config("/etc/cgitrc", cgit_global_config_cb); if (getenv("QUERY_STRING")) cgit_querystring = xstrdup(getenv("QUERY_STRING")); cgit_parse_args(argc, argv); cgit_parse_query(cgit_querystring, cgit_querystring_cb); if (!cgit_prepare_cache(&item)) return 0; if (cgit_nocache) { cgit_fill_cache(&item, 0); } else { cgit_check_cache(&item); cgit_print_cache(&item); } return 0; } @@ -1,199 +1,271 @@ body { font-family: arial; font-size: 11pt; background: white; padding: 0em; margin: 0em; } h2 { font-size: 120%; font-weight: bold; - margin-bottom: 0.5em; + margin-bottom: 0.25em; +} + +h3 { + margin-top: 0em; + font-size: 100%; + font-weight: normal; } a { color: blue; text-decoration: none; } a:hover { text-decoration: underline; } table.list { border: none; border-collapse: collapse; } + table.list tr { background: white; } + table.list tr:hover { background: #eee; } + table.list tr.nohover:hover { background: white; } + table.list th { font-weight: normal; border-bottom: solid 1px #777; padding: 0.1em 0.5em 0.1em 0.5em; vertical-align: baseline; } + table.list td { border: none; padding: 0.1em 0.5em 0.1em 0.5em; } + img { border: none; } + table#layout { width: 100%; - border-collapse: collapse; + border-collapse: separate; + border-spacing: 0px; margin: 0px; } -td#header { + +td#header, td#logo { + color: #666; background-color: #ddd; - padding: 0.25em 0.25em 0.25em 0.5em; + border-bottom: solid 1px #000; +} + +td#header { font-size: 150%; font-weight: bold; - border-bottom: solid 1px #aaa; + padding: 0.2em 0.5em; + vertical-align: text-bottom; +} + +td#logo { + text-align: right; vertical-align: middle; + padding-right: 0.5em; +} + +td#crumb, td#search { + color: #ccc; + border-top: solid 3px #555; + background-color: #666; + border-bottom: solid 1px #333; + padding: 2px 1em; +} + +td#crumb { + font-weight: bold; +} + +td#crumb a { + color: #ccc; } -td#header img#logo { - float: right; + +td#crumb a:hover { + color: #eee; } -td#header input { - float: right; - margin: 0.25em 1em; +td#search { + text-align: right; + vertical-align: center; + padding-right: 0.5em; } -td#header a { - color: black; + +td#search form { + margin: 0px; + padding: 0px; +} + +td#search input { + font-size: 9pt; + padding: 0px; + width: 10em; + border: solid 1px #333; + color: #333; + background-color: #fff; } td#content { padding: 1em 0.5em; } div#blob { border: solid 1px black; } div.error { color: red; font-weight: bold; margin: 1em 2em; } + div.ls-blob, div.ls-dir { font-family: monospace; } + div.ls-dir a { font-weight: bold; } + th.filesize, td.filesize { text-align: right; } + td.filesize { font-family: monospace; } + td.filemode { font-family: monospace; } td.blob { white-space: pre; font-family: monospace; background-color: white; } table.nowrap td { white-space: nowrap; } table.commit-info { border-collapse: collapse; margin-top: 1.5em; } + table.commit-info th { text-align: left; font-weight: normal; padding: 0.1em 1em 0.1em 0.1em; } + table.commit-info td { font-weight: normal; padding: 0.1em 1em 0.1em 0.1em; } + div.commit-subject { font-weight: bold; font-size: 125%; margin: 1.5em 0em 0.5em 0em; padding: 0em; } + div.commit-msg { white-space: pre; font-family: monospace; } + table.diffstat { border-collapse: collapse; margin-top: 1.5em; } + table.diffstat th { font-weight: normal; text-align: left; text-decoration: underline; padding: 0.1em 1em 0.1em 0.1em; font-size: 100%; } + table.diffstat td { padding: 0.1em 1em 0.1em 0.1em; font-size: 100%; } + table.diffstat td span.modechange { padding-left: 1em; color: red; } + table.diffstat td.add a { color: green; } + table.diffstat td.del a { color: red; } + table.diffstat td.upd a { color: blue; } + table.diffstat td.summary { - /* border-top: solid 1px black; */ color: #888; padding-top: 0.5em; } table.diff td { border: solid 1px black; font-family: monospace; white-space: pre; } table.diff td div.hunk { background: #ccc; } table.diff td div.add { color: green; } table.diff td div.del { color: red; } .sha1 { font-family: courier; font-size: 90%; } + .left { text-align: left; } + .right { text-align: right; } @@ -1,131 +1,130 @@ /* ui-diff.c: show diff between two blobs * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" #include "xdiff.h" char *diff_buffer; int diff_buffer_size; /* * print a single line returned from xdiff */ static void print_line(char *line, int len) { char *class = "ctx"; char c = line[len-1]; if (line[0] == '+') class = "add"; else if (line[0] == '-') class = "del"; else if (line[0] == '@') class = "hunk"; htmlf("<div class='%s'>", class); line[len-1] = '\0'; html_txt(line); html("</div>"); line[len-1] = c; } /* * Receive diff-buffers from xdiff and concatenate them as * needed across multiple callbacks. * * This is basically a copy of xdiff-interface.c/xdiff_outf(), * ripped from git and modified to use globals instead of * a special callback-struct. */ int diff_cb(void *priv_, mmbuffer_t *mb, int nbuf) { int i; for (i = 0; i < nbuf; i++) { if (mb[i].ptr[mb[i].size-1] != '\n') { /* Incomplete line */ diff_buffer = xrealloc(diff_buffer, diff_buffer_size + mb[i].size); memcpy(diff_buffer + diff_buffer_size, mb[i].ptr, mb[i].size); diff_buffer_size += mb[i].size; continue; } /* we have a complete line */ if (!diff_buffer) { print_line(mb[i].ptr, mb[i].size); continue; } diff_buffer = xrealloc(diff_buffer, diff_buffer_size + mb[i].size); memcpy(diff_buffer + diff_buffer_size, mb[i].ptr, mb[i].size); print_line(diff_buffer, diff_buffer_size + mb[i].size); free(diff_buffer); diff_buffer = NULL; diff_buffer_size = 0; } if (diff_buffer) { print_line(diff_buffer, diff_buffer_size); free(diff_buffer); diff_buffer = NULL; diff_buffer_size = 0; } return 0; } static int load_mmfile(mmfile_t *file, const unsigned char *sha1) { char type[20]; if (is_null_sha1(sha1)) { file->ptr = (char *)""; file->size = 0; } else { file->ptr = read_sha1_file(sha1, type, &file->size); } return 1; } static void run_diff(const unsigned char *sha1, const unsigned char *sha2) { mmfile_t file1, file2; xpparam_t diff_params; xdemitconf_t emit_params; xdemitcb_t emit_cb; if (!load_mmfile(&file1, sha1) || !load_mmfile(&file2, sha2)) { cgit_print_error("Unable to load files for diff"); return; } diff_params.flags = XDF_NEED_MINIMAL; emit_params.ctxlen = 3; emit_params.flags = XDL_EMIT_FUNCNAMES; emit_cb.outf = diff_cb; xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); } void cgit_print_diff(const char *old_hex, const char *new_hex) { unsigned char sha1[20], sha2[20]; get_sha1(old_hex, sha1); get_sha1(new_hex, sha2); - html("<h2>diff</h2>\n"); html("<table class='diff'><tr><td>"); run_diff(sha1, sha2); html("</td></tr></table>"); } @@ -1,98 +1,97 @@ /* ui-log.c: functions for log output * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" void print_commit(struct commit *commit) { char buf[32]; struct commitinfo *info; struct tm *time; info = cgit_parse_commit(commit); time = gmtime(&commit->date); html("<tr><td>"); strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", time); html_txt(buf); html("</td><td>"); char *qry = fmt("id=%s", sha1_to_hex(commit->object.sha1)); char *url = cgit_pageurl(cgit_query_repo, "commit", qry); html_link_open(url, NULL, NULL); html_ntxt(cgit_max_msg_len, info->subject); html_link_close(); html("</td><td>"); html_txt(info->author); html("</td></tr>\n"); cgit_free_commitinfo(info); } void cgit_print_log(const char *tip, int ofs, int cnt, char *grep) { struct rev_info rev; struct commit *commit; const char *argv[3] = {NULL, tip, NULL}; int argc = 2; int i; if (grep) argv[argc++] = fmt("--grep=%s", grep); init_revisions(&rev, NULL); rev.abbrev = DEFAULT_ABBREV; rev.commit_format = CMIT_FMT_DEFAULT; rev.verbose_header = 1; rev.show_root_diff = 0; setup_revisions(argc, argv, &rev, NULL); if (rev.grep_filter) { rev.grep_filter->regflags |= REG_ICASE; compile_grep_patterns(rev.grep_filter); } prepare_revision_walk(&rev); - html("<h2>Log</h2>"); html("<table class='list nowrap'>"); html("<tr class='nohover'><th class='left'>Date</th>" "<th class='left'>Message</th>" "<th class='left'>Author</th></tr>\n"); if (ofs<0) ofs = 0; for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) { free(commit->buffer); commit->buffer = NULL; free_commit_list(commit->parents); commit->parents = NULL; } for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) { print_commit(commit); free(commit->buffer); commit->buffer = NULL; free_commit_list(commit->parents); commit->parents = NULL; } html("</table>\n"); html("<div class='pager'>"); if (ofs > 0) { html(" <a href='"); html(cgit_pageurl(cgit_query_repo, cgit_query_page, fmt("h=%s&ofs=%d", tip, ofs-cnt))); html("'>[prev]</a> "); } if ((commit = get_revision(&rev)) != NULL) { html(" <a href='"); html(cgit_pageurl(cgit_query_repo, "log", fmt("h=%s&ofs=%d", tip, ofs+cnt))); html("'>[next]</a> "); } html("</div>"); } diff --git a/ui-repolist.c b/ui-repolist.c index 011ec95..2ce0d6a 100644 --- a/ui-repolist.c +++ b/ui-repolist.c @@ -1,40 +1,39 @@ /* ui-repolist.c: functions for generating the repolist page * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" void cgit_print_repolist(struct cacheitem *item) { struct repoinfo *repo; int i; cgit_print_docstart(cgit_root_title, item); cgit_print_pageheader(cgit_root_title, 0); - html("<h2>Repositories</h2>\n"); html("<table class='list nowrap'>"); html("<tr class='nohover'>" "<th class='left'>Name</th>" "<th class='left'>Description</th>" "<th class='left'>Owner</th></tr>\n"); for (i=0; i<cgit_repolist.count; i++) { repo = &cgit_repolist.repos[i]; html("<tr><td>"); html_link_open(cgit_repourl(repo->url), NULL, NULL); html_txt(repo->name); html_link_close(); html("</td><td>"); html_txt(repo->desc); html("</td><td>"); html_txt(repo->owner); html("</td></tr>\n"); } html("</table>"); cgit_print_docend(); } diff --git a/ui-shared.c b/ui-shared.c index 172499c..bca50aa 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -1,157 +1,174 @@ /* ui-shared.c: common web output functions * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" const char cgit_doctype[] = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"; static char *http_date(time_t t) { static char day[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static char month[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Now", "Dec"}; struct tm *tm = gmtime(&t); return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday], tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec); } static long ttl_seconds(long ttl) { if (ttl<0) return 60 * 60 * 24 * 365; else return ttl * 60; } void cgit_print_error(char *msg) { html("<div class='error'>"); html_txt(msg); html("</div>\n"); } +char *cgit_rooturl() +{ + if (cgit_virtual_root) + return fmt("%s/", cgit_virtual_root); + else + return "./cgit.cgi"; +} + char *cgit_repourl(const char *reponame) { if (cgit_virtual_root) { return fmt("%s/%s/", cgit_virtual_root, reponame); } else { return fmt("?r=%s", reponame); } } char *cgit_pageurl(const char *reponame, const char *pagename, const char *query) { if (cgit_virtual_root) { return fmt("%s/%s/%s/?%s", cgit_virtual_root, reponame, pagename, query); } else { return fmt("?r=%s&p=%s&%s", reponame, pagename, query); } } char *cgit_currurl() { if (!cgit_virtual_root) return "./cgit.cgi"; else if (cgit_query_page) return fmt("%s/%s/%s/", cgit_virtual_root, cgit_query_repo, cgit_query_page); else if (cgit_query_repo) return fmt("%s/%s/", cgit_virtual_root, cgit_query_repo); else return fmt("%s/", cgit_virtual_root); } void cgit_print_date(unsigned long secs) { char buf[32]; struct tm *time; time = gmtime(&secs); strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", time); html_txt(buf); } void cgit_print_docstart(char *title, struct cacheitem *item) { html("Content-Type: text/html; charset=utf-8\n"); htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime)); htmlf("Expires: %s\n", http_date(item->st.st_mtime + ttl_seconds(item->ttl))); html("\n"); html(cgit_doctype); html("<html>\n"); html("<head>\n"); html("<title>"); html_txt(title); html("</title>\n"); htmlf("<meta name='generator' content='cgit v%s'/>\n", cgit_version); html("<link rel='stylesheet' type='text/css' href='"); html_attr(cgit_css); html("'/>\n"); html("</head>\n"); html("<body>\n"); } void cgit_print_docend() { html("</td></tr></table>"); html("</body>\n</html>\n"); } void cgit_print_pageheader(char *title, int show_search) { - html("<table id='layout'><tr><td id='header'>"); - htmlf("<a href='%s'>", cgit_logo_link); - htmlf("<img id='logo' src='%s'/>\n", cgit_logo); - htmlf("</a>"); + html("<table id='layout'>"); + html("<tr><td id='header'>"); + html(cgit_root_title); + html("</td><td id='logo'>"); + html("<a href='"); + html_attr(cgit_logo_link); + htmlf("'><img src='%s'/></a>", cgit_logo); + html("</td></tr>"); + html("<tr><td id='crumb'>"); + htmlf("<a href='%s'>root</a>", cgit_rooturl()); + if (cgit_query_repo) { + htmlf(" : <a href='%s'>", cgit_repourl(cgit_repo->url)); + html_txt(cgit_repo->name); + htmlf("</a> : %s", title); + } + html("</td>"); + html("<td id='search'>"); if (show_search) { html("<form method='get' href='"); html_attr(cgit_currurl()); html("'>"); if (!cgit_virtual_root) { if (cgit_query_repo) html_hidden("r", cgit_query_repo); if (cgit_query_page) html_hidden("p", cgit_query_page); } if (cgit_query_head) html_hidden("h", cgit_query_head); if (cgit_query_sha1) html_hidden("id", cgit_query_sha1); if (cgit_query_sha2) html_hidden("id2", cgit_query_sha2); html("<input type='text' name='q' value='"); html_attr(cgit_query_search); html("'/></form>"); } - if (cgit_query_repo) - htmlf("<a href='%s'>", cgit_repourl(cgit_query_repo)); - html_txt(title); - if (cgit_query_repo) - html("</a>"); - html("</td></tr><tr><td id='content'>"); + html("</td></tr>"); + html("<tr><td id='content' colspan='2'>"); } void cgit_print_snapshot_start(const char *mimetype, const char *filename, struct cacheitem *item) { htmlf("Content-Type: %s\n", mimetype); htmlf("Content-Disposition: inline; filename=\"%s\"\n", filename); htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime)); htmlf("Expires: %s\n", http_date(item->st.st_mtime + ttl_seconds(item->ttl))); html("\n"); } diff --git a/ui-summary.c b/ui-summary.c index ff3ed4d..42f4300 100644 --- a/ui-summary.c +++ b/ui-summary.c @@ -1,139 +1,141 @@ /* ui-summary.c: functions for generating repo summary page * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" static int cgit_print_branch_cb(const char *refname, const unsigned char *sha1, int flags, void *cb_data) { struct commit *commit; struct commitinfo *info; char buf[256], *url; strncpy(buf, refname, sizeof(buf)); commit = lookup_commit(sha1); if (commit && !parse_commit(commit)){ info = cgit_parse_commit(commit); html("<tr><td>"); url = cgit_pageurl(cgit_query_repo, "log", fmt("h=%s", refname)); html_link_open(url, NULL, NULL); html_txt(buf); html_link_close(); html("</td><td>"); cgit_print_date(commit->date); html("</td><td>"); html_txt(info->author); html("</td><td>"); url = cgit_pageurl(cgit_query_repo, "commit", fmt("id=%s", sha1_to_hex(sha1))); html_link_open(url, NULL, NULL); html_ntxt(cgit_max_msg_len, info->subject); html_link_close(); html("</td></tr>\n"); cgit_free_commitinfo(info); } else { html("<tr><td>"); html_txt(buf); html("</td><td colspan='3'>"); htmlf("*** bad ref %s ***", sha1_to_hex(sha1)); html("</td></tr>\n"); } return 0; } static void cgit_print_object_ref(struct object *obj) { char *page, *url; if (obj->type == OBJ_COMMIT) page = "commit"; else if (obj->type == OBJ_TREE) page = "tree"; else page = "view"; url = cgit_pageurl(cgit_query_repo, page, fmt("id=%s", sha1_to_hex(obj->sha1))); html_link_open(url, NULL, NULL); htmlf("%s %s", type_names[obj->type], sha1_to_hex(obj->sha1)); html_link_close(); } static int cgit_print_tag_cb(const char *refname, const unsigned char *sha1, int flags, void *cb_data) { struct tag *tag; struct taginfo *info; struct object *obj; char buf[256], *url; strncpy(buf, refname, sizeof(buf)); obj = parse_object(sha1); if (!obj) return 1; if (obj->type == OBJ_TAG) { tag = lookup_tag(sha1); if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) return 2; html("<tr><td>"); url = cgit_pageurl(cgit_query_repo, "view", fmt("id=%s", sha1_to_hex(sha1))); html_link_open(url, NULL, NULL); html_txt(buf); html_link_close(); html("</td><td>"); if (info->tagger_date > 0) cgit_print_date(info->tagger_date); html("</td><td>"); if (info->tagger) html(info->tagger); html("</td><td>"); cgit_print_object_ref(tag->tagged); html("</td></tr>\n"); } else { html("<tr><td>"); html_txt(buf); html("</td><td colspan='2'/><td>"); cgit_print_object_ref(obj); html("</td></tr>\n"); } return 0; } static void cgit_print_branches() { html("<tr class='nohover'><th class='left'>Branch</th>" "<th class='left'>Updated</th>" "<th class='left'>Author</th>" "<th class='left'>Head commit</th></tr>\n"); for_each_branch_ref(cgit_print_branch_cb, NULL); } static void cgit_print_tags() { html("<tr class='nohover'><th class='left'>Tag</th>" "<th class='left'>Created</th>" "<th class='left'>Author</th>" "<th class='left'>Reference</th></tr>\n"); for_each_tag_ref(cgit_print_tag_cb, NULL); } void cgit_print_summary() { html("<h2>"); - html_txt("Repo summary page"); - html("</h2>"); + html(cgit_repo->name); + html("</h2><h3>"); + html(cgit_repo->desc); + html("</h3>"); html("<table class='list nowrap'>"); cgit_print_branches(); html("<tr class='nohover'><td colspan='4'> </td></tr>"); cgit_print_tags(); html("</table>"); } @@ -1,79 +1,78 @@ /* ui-tree.c: functions for tree output * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" static int print_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned int mode, int stage) { char *name; char type[20]; unsigned long size; if (sha1_object_info(sha1, type, &size)) { cgit_print_error(fmt("Bad object name: %s", sha1_to_hex(sha1))); return 0; } name = xstrdup(pathname); html("<tr><td class='filemode'>"); html_filemode(mode); html("</td><td>"); if (S_ISDIR(mode)) { html("<div class='ls-dir'><a href='"); html_attr(cgit_pageurl(cgit_query_repo, "tree", fmt("id=%s&path=%s%s/", sha1_to_hex(sha1), cgit_query_path ? cgit_query_path : "", pathname))); } else { html("<div class='ls-blob'><a href='"); html_attr(cgit_pageurl(cgit_query_repo, "view", fmt("id=%s&path=%s%s", sha1_to_hex(sha1), cgit_query_path ? cgit_query_path : "", pathname))); } html("'>"); html_txt(name); if (S_ISDIR(mode)) html("/"); html("</a></div></td>"); htmlf("<td class='filesize'>%li</td>", size); html("</tr>\n"); free(name); return 0; } void cgit_print_tree(const char *hex, char *path) { struct tree *tree; unsigned char sha1[20]; if (get_sha1_hex(hex, sha1)) { cgit_print_error(fmt("Invalid object id: %s", hex)); return; } tree = parse_tree_indirect(sha1); if (!tree) { cgit_print_error(fmt("Not a tree object: %s", hex)); return; } - html("<h2>Tree content</h2>\n"); html_txt(path); html("<table class='list'>\n"); html("<tr class='nohover'>"); html("<th class='left'>Mode</th>"); html("<th class='left'>Name</th>"); html("<th class='right'>Size</th>"); html("</tr>\n"); read_tree_recursive(tree, "", 0, 1, NULL, print_entry); html("</table>\n"); } @@ -1,42 +1,41 @@ /* ui-view.c: functions to output _any_ object, given it's sha1 * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" void cgit_print_view(const char *hex) { unsigned char sha1[20]; char type[20]; unsigned char *buf; unsigned long size; if (get_sha1_hex(hex, sha1)){ cgit_print_error(fmt("Bad hex value: %s", hex)); return; } if (sha1_object_info(sha1, type, &size)){ cgit_print_error("Bad object name"); return; } buf = read_sha1_file(sha1, type, &size); if (!buf) { cgit_print_error("Error reading object"); return; } buf[size] = '\0'; - html("<h2>Object content</h2>\n"); html("<table class='list'>\n"); htmlf("<tr class='nohover'><th class='left'>%s %s, %li bytes</th></tr>\n", type, hex, size); html("<tr><td class='blob'>\n"); html_txt(buf); html("\n</td></tr>\n"); html("</table>\n"); } |