-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | cgit.c | 3 | ||||
-rw-r--r-- | cgit.css | 6 | ||||
-rw-r--r-- | cgit.h | 1 | ||||
-rw-r--r-- | cgitrc.5.txt | 4 | ||||
m--------- | git | 0 | ||||
-rw-r--r-- | ui-commit.c | 2 | ||||
-rw-r--r-- | ui-log.c | 2 | ||||
-rw-r--r-- | ui-plain.c | 3 | ||||
-rw-r--r-- | ui-tree.c | 35 |
10 files changed, 37 insertions, 21 deletions
@@ -1,32 +1,32 @@ CGIT_VERSION = v0.8.2.1 CGIT_SCRIPT_NAME = cgit.cgi CGIT_SCRIPT_PATH = /var/www/htdocs/cgit CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH) CGIT_CONFIG = /etc/cgitrc CACHE_ROOT = /var/cache/cgit SHA1_HEADER = <openssl/sha.h> -GIT_VER = 1.6.3.4 +GIT_VER = 1.6.4.3 GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2 INSTALL = install # Define NO_STRCASESTR if you don't have strcasestr. # # Define NEEDS_LIBICONV if linking with libc is not enough (eg. Darwin). # #-include config.mak # # Platform specific tweaks # uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') ifeq ($(uname_O),Cygwin) NO_STRCASESTR = YesPlease NEEDS_LIBICONV = YesPlease endif # @@ -116,48 +116,50 @@ void config_cb(const char *name, const char *value) else if (!strcmp(name, "logo-link")) ctx.cfg.logo_link = xstrdup(value); else if (!strcmp(name, "module-link")) ctx.cfg.module_link = xstrdup(value); else if (!strcmp(name, "virtual-root")) { ctx.cfg.virtual_root = trim_end(value, '/'); if (!ctx.cfg.virtual_root && (!strcmp(value, "/"))) ctx.cfg.virtual_root = ""; } else if (!strcmp(name, "nocache")) ctx.cfg.nocache = atoi(value); else if (!strcmp(name, "noplainemail")) ctx.cfg.noplainemail = atoi(value); else if (!strcmp(name, "noheader")) ctx.cfg.noheader = atoi(value); else if (!strcmp(name, "snapshots")) ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); else if (!strcmp(name, "enable-filter-overrides")) ctx.cfg.enable_filter_overrides = atoi(value); else if (!strcmp(name, "enable-index-links")) ctx.cfg.enable_index_links = atoi(value); else if (!strcmp(name, "enable-log-filecount")) ctx.cfg.enable_log_filecount = atoi(value); else if (!strcmp(name, "enable-log-linecount")) ctx.cfg.enable_log_linecount = atoi(value); + else if (!strcmp(name, "enable-tree-linenumbers")) + ctx.cfg.enable_tree_linenumbers = atoi(value); else if (!strcmp(name, "max-stats")) ctx.cfg.max_stats = cgit_find_stats_period(value, NULL); else if (!strcmp(name, "cache-size")) ctx.cfg.cache_size = atoi(value); else if (!strcmp(name, "cache-root")) ctx.cfg.cache_root = xstrdup(value); else if (!strcmp(name, "cache-root-ttl")) ctx.cfg.cache_root_ttl = atoi(value); else if (!strcmp(name, "cache-repo-ttl")) ctx.cfg.cache_repo_ttl = atoi(value); else if (!strcmp(name, "cache-scanrc-ttl")) ctx.cfg.cache_scanrc_ttl = atoi(value); else if (!strcmp(name, "cache-static-ttl")) ctx.cfg.cache_static_ttl = atoi(value); else if (!strcmp(name, "cache-dynamic-ttl")) ctx.cfg.cache_dynamic_ttl = atoi(value); else if (!strcmp(name, "about-filter")) ctx.cfg.about_filter = new_filter(value, 0); else if (!strcmp(name, "commit-filter")) ctx.cfg.commit_filter = new_filter(value, 0); else if (!strcmp(name, "embedded")) ctx.cfg.embedded = atoi(value); else if (!strcmp(name, "max-message-length")) ctx.cfg.max_msg_len = atoi(value); @@ -239,48 +241,49 @@ static void querystring_cb(const char *name, const char *value) } } char *xstrdupn(const char *str) { return (str ? xstrdup(str) : NULL); } static void prepare_context(struct cgit_context *ctx) { memset(ctx, 0, sizeof(ctx)); ctx->cfg.agefile = "info/web/last-modified"; ctx->cfg.nocache = 0; ctx->cfg.cache_size = 0; ctx->cfg.cache_dynamic_ttl = 5; ctx->cfg.cache_max_create_time = 5; ctx->cfg.cache_repo_ttl = 5; ctx->cfg.cache_root = CGIT_CACHE_ROOT; ctx->cfg.cache_root_ttl = 5; ctx->cfg.cache_scanrc_ttl = 15; ctx->cfg.cache_static_ttl = -1; ctx->cfg.css = "/cgit.css"; ctx->cfg.logo = "/cgit.png"; ctx->cfg.local_time = 0; + ctx->cfg.enable_tree_linenumbers = 1; ctx->cfg.max_repo_count = 50; ctx->cfg.max_commit_count = 50; ctx->cfg.max_lock_attempts = 5; ctx->cfg.max_msg_len = 80; ctx->cfg.max_repodesc_len = 80; ctx->cfg.max_stats = 0; ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s"; ctx->cfg.renamelimit = -1; ctx->cfg.robots = "index, nofollow"; ctx->cfg.root_title = "Git repository browser"; ctx->cfg.root_desc = "a fast webinterface for the git dscm"; ctx->cfg.script_name = CGIT_SCRIPT_NAME; ctx->cfg.section = ""; ctx->cfg.summary_branches = 10; ctx->cfg.summary_log = 10; ctx->cfg.summary_tags = 10; ctx->env.cgit_config = xstrdupn(getenv("CGIT_CONFIG")); ctx->env.http_host = xstrdupn(getenv("HTTP_HOST")); ctx->env.https = xstrdupn(getenv("HTTPS")); ctx->env.no_http = xstrdupn(getenv("NO_HTTP")); ctx->env.path_info = xstrdupn(getenv("PATH_INFO")); ctx->env.query_string = xstrdupn(getenv("QUERY_STRING")); ctx->env.request_method = xstrdupn(getenv("REQUEST_METHOD")); ctx->env.script_name = xstrdupn(getenv("SCRIPT_NAME")); @@ -216,58 +216,58 @@ div.error { margin: 1em 2em; } a.ls-blob, a.ls-dir, a.ls-mod { font-family: monospace; } td.ls-size { text-align: right; font-family: monospace; width: 10em; } td.ls-mode { font-family: monospace; width: 10em; } table.blob { margin-top: 0.5em; border-top: solid 1px black; } table.blob td.lines { - margin: 0; padding: 0; + margin: 0; padding: 0 0 0 0.5em; vertical-align: top; color: black; } table.blob td.linenumbers { - margin: 0; padding: 0; + margin: 0; padding: 0 0.5em 0 0.5em; vertical-align: top; + text-align: right; border-right: 1px solid gray; - background-color: #eee; } table.blob pre { padding: 0; margin: 0; } table.blob a.no { color: gray; text-align: right; text-decoration: none; } table.blob a.no a:hover { color: black; } table.bin-blob { margin-top: 0.5em; border: solid 1px black; } table.bin-blob th { font-family: monospace; white-space: pre; @@ -157,48 +157,49 @@ struct cgit_config { char *index_header; char *index_info; char *logo; char *logo_link; char *module_link; char *robots; char *root_title; char *root_desc; char *root_readme; char *script_name; char *section; char *virtual_root; int cache_size; int cache_dynamic_ttl; int cache_max_create_time; int cache_repo_ttl; int cache_root_ttl; int cache_scanrc_ttl; int cache_static_ttl; int embedded; int enable_filter_overrides; int enable_index_links; int enable_log_filecount; int enable_log_linecount; + int enable_tree_linenumbers; int local_time; int max_repo_count; int max_commit_count; int max_lock_attempts; int max_msg_len; int max_repodesc_len; int max_stats; int nocache; int noplainemail; int noheader; int renamelimit; int snapshots; int summary_branches; int summary_log; int summary_tags; struct string_list mimetypes; struct cgit_filter *about_filter; struct cgit_filter *commit_filter; struct cgit_filter *source_filter; }; struct cgit_page { time_t modified; time_t expires; diff --git a/cgitrc.5.txt b/cgitrc.5.txt index 617b7c3..4dc383d 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@ -86,48 +86,52 @@ css:: embedded:: Flag which, when set to "1", will make cgit generate a html fragment suitable for embedding in other html pages. Default value: none. See also: "noheader". enable-filter-overrides:: Flag which, when set to "1", allows all filter settings to be overridden in repository-specific cgitrc files. Default value: none. enable-index-links:: Flag which, when set to "1", will make cgit generate extra links for each repo in the repository index (specifically, to the "summary", "commit" and "tree" pages). Default value: "0". enable-log-filecount:: Flag which, when set to "1", will make cgit print the number of modified files for each commit on the repository log page. Default value: "0". enable-log-linecount:: Flag which, when set to "1", will make cgit print the number of added and removed lines for each commit on the repository log page. Default value: "0". +enable-tree-linenumbers:: + Flag which, when set to "1", will make cgit generate linenumber links + for plaintext blobs printed in the tree view. Default value: "1". + favicon:: Url used as link to a shortcut icon for cgit. If specified, it is suggested to use the value "/favicon.ico" since certain browsers will ignore other values. Default value: none. footer:: The content of the file specified with this option will be included verbatim at the bottom of all pages (i.e. it replaces the standard "generated by..." message. Default value: none. head-include:: The content of the file specified with this option will be included verbatim in the html HEAD section on all pages. Default value: none. header:: The content of the file specified with this option will be included verbatim at the top of all pages. Default value: none. include:: Name of a configfile to include before the rest of the current config- file is parsed. Default value: none. index-header:: The content of the file specified with this option will be included diff --git a/git b/git -Subproject e276f018f2c1f0fc962fbe44a36708d1cdebada +Subproject 7fb6bcff2dece2ff9fbc5ebfe526d9b2a7e764c diff --git a/ui-commit.c b/ui-commit.c index d6b73ee..f5b0ae5 100644 --- a/ui-commit.c +++ b/ui-commit.c @@ -14,49 +14,49 @@ void cgit_print_commit(char *hex) { struct commit *commit, *parent; struct commitinfo *info; struct commit_list *p; unsigned char sha1[20]; char *tmp; int parents = 0; if (!hex) hex = ctx.qry.head; if (get_sha1(hex, sha1)) { cgit_print_error(fmt("Bad object id: %s", hex)); return; } commit = lookup_commit_reference(sha1); if (!commit) { cgit_print_error(fmt("Bad commit reference: %s", hex)); return; } info = cgit_parse_commit(commit); - load_ref_decorations(); + load_ref_decorations(DECORATE_FULL_REFS); html("<table summary='commit info' class='commit-info'>\n"); html("<tr><th>author</th><td>"); html_txt(info->author); if (!ctx.cfg.noplainemail) { html(" "); html_txt(info->author_email); } html("</td><td class='right'>"); cgit_print_date(info->author_date, FMT_LONGDATE, ctx.cfg.local_time); html("</td></tr>\n"); html("<tr><th>committer</th><td>"); html_txt(info->committer); if (!ctx.cfg.noplainemail) { html(" "); html_txt(info->committer_email); } html("</td><td class='right'>"); cgit_print_date(info->committer_date, FMT_LONGDATE, ctx.cfg.local_time); html("</td></tr>\n"); html("<tr><th>commit</th><td colspan='2' class='sha1'>"); tmp = sha1_to_hex(commit->object.sha1); cgit_commit_link(tmp, NULL, NULL, ctx.qry.head, tmp); html(" ("); @@ -140,49 +140,49 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern const char *argv[] = {NULL, NULL, NULL, NULL, NULL}; int argc = 2; int i, columns = 3; if (!tip) tip = ctx.qry.head; argv[1] = disambiguate_ref(tip); if (grep && pattern && (!strcmp(grep, "grep") || !strcmp(grep, "author") || !strcmp(grep, "committer"))) argv[argc++] = fmt("--%s=%s", grep, pattern); if (path) { argv[argc++] = "--"; argv[argc++] = path; } 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); - load_ref_decorations(); + load_ref_decorations(DECORATE_FULL_REFS); rev.show_decorations = 1; rev.grep_filter.regflags |= REG_ICASE; compile_grep_patterns(&rev.grep_filter); prepare_revision_walk(&rev); if (pager) html("<table class='list nowrap'>"); html("<tr class='nohover'><th class='left'>Age</th>" "<th class='left'>Commit message"); if (pager) { html(" ("); cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL, NULL, ctx.qry.head, ctx.qry.sha1, ctx.qry.path, ctx.qry.ofs, ctx.qry.grep, ctx.qry.search, ctx.qry.showmsg ? 0 : 1); html(")"); } html("</th><th class='left'>Author</th>"); if (ctx.repo->enable_log_filecount) { html("<th class='left'>Files</th>"); columns++; if (ctx.repo->enable_log_linecount) { html("<th class='left'>Lines</th>"); @@ -39,49 +39,50 @@ static void print_object(const unsigned char *sha1, const char *path) if (mime) ctx.page.mimetype = (char *)mime->util; } if (!ctx.page.mimetype) { if (buffer_is_binary(buf, size)) ctx.page.mimetype = "application/octet-stream"; else ctx.page.mimetype = "text/plain"; } ctx.page.filename = fmt("%s", path); ctx.page.size = size; ctx.page.etag = sha1_to_hex(sha1); cgit_print_http_headers(&ctx); html_raw(buf, size); match = 1; } static int walk_tree(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *cbdata) { if (S_ISDIR(mode)) return READ_TREE_RECURSIVE; - if (S_ISREG(mode)) + if (S_ISREG(mode) && !strncmp(base, match_path, baselen) && + !strcmp(pathname, match_path + baselen)) print_object(sha1, pathname); return 0; } void cgit_print_plain(struct cgit_context *ctx) { const char *rev = ctx->qry.sha1; unsigned char sha1[20]; struct commit *commit; const char *paths[] = {ctx->qry.path, NULL}; if (!rev) rev = ctx->qry.head; curr_rev = xstrdup(rev); if (get_sha1(rev, sha1)) { html_status(404, "Not found", 0); return; } commit = lookup_commit_reference(sha1); if (!commit || parse_commit(commit)) { html_status(404, "Not found", 0); return; @@ -1,71 +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 <ctype.h> #include "cgit.h" #include "html.h" #include "ui-shared.h" char *curr_rev; char *match_path; int header = 0; static void print_text_buffer(const char *name, char *buf, unsigned long size) { unsigned long lineno, idx; const char *numberfmt = "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n"; html("<table summary='blob content' class='blob'>\n"); + + if (ctx.cfg.enable_tree_linenumbers) { + html("<tr><td class='linenumbers'><pre>"); + idx = 0; + lineno = 0; + + if (size) { + htmlf(numberfmt, ++lineno); + while(idx < size - 1) { // skip absolute last newline + if (buf[idx] == '\n') + htmlf(numberfmt, ++lineno); + idx++; + } + } + html("</pre></td>\n"); + } + else { + html("<tr>\n"); + } + if (ctx.repo->source_filter) { - html("<tr><td class='lines'><pre><code>"); + html("<td class='lines'><pre><code>"); ctx.repo->source_filter->argv[1] = xstrdup(name); cgit_open_filter(ctx.repo->source_filter); write(STDOUT_FILENO, buf, size); cgit_close_filter(ctx.repo->source_filter); html("</code></pre></td></tr></table>\n"); return; } - html("<tr><td class='linenumbers'><pre>"); - idx = 0; - lineno = 0; - - if (size) { - htmlf(numberfmt, ++lineno); - while(idx < size - 1) { // skip absolute last newline - if (buf[idx] == '\n') - htmlf(numberfmt, ++lineno); - idx++; - } - } - html("</pre></td>\n"); html("<td class='lines'><pre><code>"); html_txt(buf); html("</code></pre></td></tr></table>\n"); } #define ROWLEN 32 static void print_binary_buffer(char *buf, unsigned long size) { unsigned long ofs, idx; static char ascii[ROWLEN + 1]; html("<table summary='blob content' class='bin-blob'>\n"); html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>"); for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) { htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs); for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) htmlf("%*s%02x", idx == 16 ? 4 : 1, "", buf[idx] & 0xff); html(" </td><td class='hex'>"); for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.'; ascii[idx] = '\0'; |