-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | Makefile | 21 | ||||
-rw-r--r-- | cgit-doc.css | 3 | ||||
-rw-r--r-- | cgit.c | 8 | ||||
-rw-r--r-- | cgit.h | 4 | ||||
-rw-r--r-- | cgitrc.5.txt | 122 | ||||
-rw-r--r-- | ui-atom.c | 6 | ||||
-rw-r--r-- | ui-blob.c | 8 | ||||
-rw-r--r-- | ui-plain.c | 6 | ||||
-rw-r--r-- | ui-shared.c | 26 | ||||
-rw-r--r-- | ui-shared.h | 1 | ||||
-rw-r--r-- | ui-snapshot.c | 23 | ||||
-rw-r--r-- | ui-tree.c | 26 |
13 files changed, 177 insertions, 82 deletions
@@ -3,4 +3,9 @@ cgit cgit.conf VERSION +cgitrc.5 +cgitrc.5.fo +cgitrc.5.html +cgitrc.5.pdf +cgitrc.5.xml *.o *.d @@ -1,3 +1,3 @@ -CGIT_VERSION = v0.8.2 +CGIT_VERSION = v0.8.2.1 CGIT_SCRIPT_NAME = cgit.cgi CGIT_SCRIPT_PATH = /var/www/htdocs/cgit @@ -101,5 +101,6 @@ endif -.PHONY: all libgit test install uninstall clean force-version get-git +.PHONY: all libgit test install uninstall clean force-version get-git \ + doc man-doc html-doc clean-doc all: cgit @@ -150,7 +151,21 @@ uninstall: rm -f $(CGIT_DATA_PATH)/cgit.png -clean: +doc: man-doc html-doc pdf-doc + +man-doc: cgitrc.5.txt + a2x -f manpage cgitrc.5.txt + +html-doc: cgitrc.5.txt + a2x -f xhtml --stylesheet=cgit-doc.css cgitrc.5.txt + +pdf-doc: cgitrc.5.txt + a2x -f pdf cgitrc.5.txt + +clean: clean-doc rm -f cgit VERSION *.o *.d +clean-doc: + rm -f cgitrc.5 cgitrc.5.html cgitrc.5.pdf cgitrc.5.xml cgitrc.5.fo + get-git: curl $(GIT_URL) | tar -xj && rm -rf git && mv git-$(GIT_VER) git diff --git a/cgit-doc.css b/cgit-doc.css new file mode 100644 index 0000000..5a399b6 --- a/dev/null +++ b/cgit-doc.css @@ -0,0 +1,3 @@ +div.variablelist dt { + margin-top: 1em; +} @@ -32,4 +32,6 @@ void config_cb(const char *name, const char *value) else if (!strcmp(name, "footer")) ctx.cfg.footer = xstrdup(value); + else if (!strcmp(name, "head-include")) + ctx.cfg.head_include = xstrdup(value); else if (!strcmp(name, "header")) ctx.cfg.header = xstrdup(value); @@ -211,4 +213,5 @@ static void prepare_context(struct cgit_context *ctx) ctx->page.modified = time(NULL); ctx->page.expires = ctx->page.modified; + ctx->page.etag = NULL; } @@ -290,4 +293,6 @@ static int prepare_repo_cmd(struct cgit_context *ctx) tmp = xstrdup(ctx->qry.head); ctx->qry.head = ctx->repo->defbranch; + ctx->page.status = 404; + ctx->page.statusmsg = "not found"; cgit_print_http_headers(ctx); cgit_print_docstart(ctx); @@ -434,4 +439,5 @@ int main(int argc, const char **argv) { const char *cgit_config_env = getenv("CGIT_CONFIG"); + const char *method = getenv("REQUEST_METHOD"); const char *path; char *qry; @@ -480,4 +486,6 @@ int main(int argc, const char **argv) ttl = calc_ttl(); ctx.page.expires += ttl*60; + if (method && !strcmp(method, "HEAD")) + ctx.cfg.nocache = 1; if (ctx.cfg.nocache) ctx.cfg.cache_size = 0; @@ -137,4 +137,5 @@ struct cgit_config { char *favicon; char *footer; + char *head_include; char *header; char *index_header; @@ -183,5 +184,8 @@ struct cgit_page { char *charset; char *filename; + char *etag; char *title; + int status; + char *statusmsg; }; diff --git a/cgitrc.5.txt b/cgitrc.5.txt index 771bb7d..a207fe0 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@ -1,13 +1,13 @@ -CGITRC -====== +CGITRC(5) +======== NAME ---- - cgitrc - runtime configuration for cgit +cgitrc - runtime configuration for cgit -DESCRIPTION ------------ +SYNOPSIS +-------- Cgitrc contains all runtime settings for cgit, including the list of git repositories, formatted as a line-separated list of NAME=VALUE pairs. Blank @@ -17,5 +17,5 @@ lines, and lines starting with '#', are ignored. GLOBAL SETTINGS --------------- -agefile +agefile:: Specifies a path, relative to each repository path, which can be used to specify the date and time of the youngest commit in the repository. @@ -24,31 +24,31 @@ agefile hh:mm:ss". Default value: "info/web/last-modified". -cache-root +cache-root:: Path used to store the cgit cache entries. Default value: "/var/cache/cgit". -cache-dynamic-ttl +cache-dynamic-ttl:: Number which specifies the time-to-live, in minutes, for the cached version of repository pages accessed without a fixed SHA1. Default value: "5". -cache-repo-ttl +cache-repo-ttl:: Number which specifies the time-to-live, in minutes, for the cached version of the repository summary page. Default value: "5". -cache-root-ttl +cache-root-ttl:: Number which specifies the time-to-live, in minutes, for the cached version of the repository index page. Default value: "5". -cache-size +cache-size:: The maximum number of entries in the cgit cache. Default value: "0" (i.e. caching is disabled). -cache-static-ttl +cache-static-ttl:: Number which specifies the time-to-live, in minutes, for the cached version of repository pages accessed with a fixed SHA1. Default value: "5". -clone-prefix +clone-prefix:: Space-separated list of common prefixes which, when combined with a repository url, generates valid clone urls for the repository. This @@ -56,47 +56,51 @@ clone-prefix none. -css +css:: Url which specifies the css document to include in all cgit pages. Default value: "/cgit.css". -embedded +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-index-links +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 +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 +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". -favicon +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 +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. -header +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 +include:: Name of a configfile to include before the rest of the current config- file is parsed. Default value: none. -index-header +index-header:: The content of the file specified with this option will be included verbatim above the repository index. This setting is deprecated, and @@ -104,5 +108,5 @@ index-header value: none. -index-info +index-info:: The content of the file specified with this option will be included verbatim below the heading on the repository index page. This setting @@ -110,39 +114,39 @@ index-info instead). Default value: none. -local-time +local-time:: Flag which, if set to "1", makes cgit print commit and tag times in the servers timezone. Default value: "0". -logo +logo:: Url which specifies the source of an image which will be used as a logo on all cgit pages. -logo-link +logo-link:: Url loaded when clicking on the cgit logo image. If unspecified the calculated url of the repository index page will be used. Default value: none. -max-commit-count +max-commit-count:: Specifies the number of entries to list per page in "log" view. Default value: "50". -max-message-length +max-message-length:: Specifies the maximum number of commit message characters to display in "log" view. Default value: "80". -max-repo-count +max-repo-count:: Specifies the number of entries to list per page on the repository index page. Default value: "50". -max-repodesc-length +max-repodesc-length:: Specifies the maximum number of repo description characters to display on the repository index page. Default value: "80". -max-stats +max-stats:: Set the default maximum statistics period. Valid values are "week", "month", "quarter" and "year". If unspecified, statistics are disabled. Default value: none. See also: "repo.max-stats". -module-link +module-link:: Text which will be used as the formatstring for a hyperlink when a submodule is printed in a directory listing. The arguments for the @@ -150,40 +154,40 @@ module-link value: "./?repo=%s&page=commit&id=%s" -nocache +nocache:: If set to the value "1" caching will be disabled. This settings is deprecated, and will not be honored starting with cgit-1.0. Default value: "0". -noheader +noheader:: Flag which, when set to "1", will make cgit omit the standard header on all pages. Default value: none. See also: "embedded". -renamelimit +renamelimit:: Maximum number of files to consider when detecting renames. The value "-1" uses the compiletime value in git (for further info, look at `man git-diff`). Default value: "-1". -repo.group +repo.group:: A value for the current repository group, which all repositories specified after this setting will inherit. Default value: none. -robots +robots:: Text used as content for the "robots" meta-tag. Default value: "index, nofollow". -root-desc +root-desc:: Text printed below the heading on the repository index page. Default value: "a fast webinterface for the git dscm". -root-readme: +root-readme:: The content of the file specified with this option will be included verbatim below the "about" link on the repository index page. Default value: none. -root-title +root-title:: Text printed as heading on the repository index page. Default value: "Git Repository Browser". -snapshots +snapshots:: Text which specifies the default (and allowed) set of snapshot formats supported by cgit. The value is a space-separated list of zero or more @@ -195,17 +199,17 @@ snapshots Default value: none. -summary-branches +summary-branches:: Specifies the number of branches to display in the repository "summary" view. Default value: "10". -summary-log +summary-log:: Specifies the number of log entries to display in the repository "summary" view. Default value: "10". -summary-tags +summary-tags:: Specifies the number of tags to display in the repository "summary" view. Default value: "10". -virtual-root +virtual-root:: Url which, if specified, will be used as root for all cgit links. It will also cause cgit to generate 'virtual urls', i.e. urls like @@ -217,49 +221,49 @@ virtual-root REPOSITORY SETTINGS ------------------- -repo.clone-url +repo.clone-url:: A list of space-separated urls which can be used to clone this repo. Default value: none. -repo.defbranch +repo.defbranch:: The name of the default branch for this repository. If no such branch exists in the repository, the first branch name (when sorted) is used as default instead. Default value: "master". -repo.desc +repo.desc:: The value to show as repository description. Default value: none. -repo.enable-log-filecount +repo.enable-log-filecount:: A flag which can be used to disable the global setting `enable-log-filecount'. Default value: none. -repo.enable-log-linecount +repo.enable-log-linecount:: A flag which can be used to disable the global setting `enable-log-linecount'. Default value: none. -repo.max-stats +repo.max-stats:: Override the default maximum statistics period. Valid values are equal to the values specified for the global "max-stats" setting. Default value: none. -repo.name +repo.name:: The value to show as repository name. Default value: <repo.url>. -repo.owner +repo.owner:: A value used to identify the owner of the repository. Default value: none. -repo.path +repo.path:: An absolute path to the repository directory. For non-bare repositories this is the .git-directory. Default value: none. -repo.readme +repo.readme:: A path (relative to <repo.path>) which specifies a file to include verbatim as the "About" page for this repo. Default value: none. -repo.snapshots +repo.snapshots:: A mask of allowed snapshot-formats for this repo, restricted by the "snapshots" global setting. Default value: <snapshots>. -repo.url +repo.url:: The relative url used to access the repository. This must be the first setting specified for each repo. Default value: none. @@ -269,4 +273,5 @@ EXAMPLE CGITRC FILE ------------------- +.... # Enable caching of up to 1000 output entriess cache-size=1000 @@ -378,4 +383,5 @@ repo.enable-log-linecount=0 # Restrict the max statistics period for this repo repo.max-stats=month +.... @@ -53,5 +53,6 @@ void add_entry(struct commit *commit, char *host) html("</published>\n"); if (host) { - html("<link rel='alternate' type='text/html' href='http://"); + html("<link rel='alternate' type='text/html' href='"); + html(cgit_httpscheme()); html_attr(host); html_attr(cgit_pageurl(ctx.repo->url, "commit", NULL)); @@ -114,5 +115,6 @@ void cgit_print_atom(char *tip, char *path, int max_count) html("</subtitle>\n"); if (host) { - html("<link rel='alternate' type='text/html' href='http://"); + html("<link rel='alternate' type='text/html' href='"); + html(cgit_httpscheme()); html_attr(host); html_attr(cgit_repourl(ctx.repo->url)); @@ -28,5 +28,5 @@ void cgit_print_blob(const char *hex, char *path, const char *head) unsigned char sha1[20]; enum object_type type; - unsigned char *buf; + char *buf; unsigned long size; struct commit *commit; @@ -68,4 +68,10 @@ void cgit_print_blob(const char *hex, char *path, const char *head) buf[size] = '\0'; ctx.page.mimetype = ctx.qry.mimetype; + 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 = path; cgit_print_http_headers(&ctx); @@ -32,7 +32,11 @@ static void print_object(const unsigned char *sha1, const char *path) return; } - ctx.page.mimetype = "text/plain"; + 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); diff --git a/ui-shared.c b/ui-shared.c index 5e03a7a..015c52b 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -35,4 +35,15 @@ void cgit_print_error(char *msg) } +char *cgit_httpscheme() +{ + char *https; + + https = getenv("HTTPS"); + if (https != NULL && strcmp(https, "on") == 0) + return "https://"; + else + return "http://"; +} + char *cgit_hosturl() { @@ -457,7 +468,11 @@ void cgit_print_age(time_t t, time_t max_relative, char *format) void cgit_print_http_headers(struct cgit_context *ctx) { + const char *method = getenv("REQUEST_METHOD"); + if (ctx->cfg.embedded) return; + if (ctx->page.status) + htmlf("Status: %d %s\n", ctx->page.status, ctx->page.statusmsg); if (ctx->page.mimetype && ctx->page.charset) htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype, @@ -472,5 +487,9 @@ void cgit_print_http_headers(struct cgit_context *ctx) htmlf("Last-Modified: %s\n", http_date(ctx->page.modified)); htmlf("Expires: %s\n", http_date(ctx->page.expires)); + if (ctx->page.etag) + htmlf("ETag: \"%s\"\n", ctx->page.etag); html("\n"); + if (method && !strcmp(method, "HEAD")) + exit(0); } @@ -499,10 +518,13 @@ void cgit_print_docstart(struct cgit_context *ctx) } if (host && ctx->repo) { - html("<link rel='alternate' title='Atom feed' href='http://"); + html("<link rel='alternate' title='Atom feed' href='"); + html(cgit_httpscheme()); html_attr(cgit_hosturl()); html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path, fmt("h=%s", ctx->qry.head))); - html("' type='application/atom+xml'/>"); + html("' type='application/atom+xml'/>\n"); } + if (ctx->cfg.head_include) + html_include(ctx->cfg.head_include); html("</head>\n"); html("<body>\n"); diff --git a/ui-shared.h b/ui-shared.h index 5a3821f..bff4826 100644 --- a/ui-shared.h +++ b/ui-shared.h @@ -2,4 +2,5 @@ #define UI_SHARED_H +extern char *cgit_httpscheme(); extern char *cgit_hosturl(); extern char *cgit_repourl(const char *reponame); diff --git a/ui-snapshot.c b/ui-snapshot.c index f25613e..5372f5d 100644 --- a/ui-snapshot.c +++ b/ui-snapshot.c @@ -157,4 +157,14 @@ static const char *get_ref_from_filename(const char *url, const char *filename, } +void show_error(char *msg) +{ + ctx.page.mimetype = "text/html"; + cgit_print_http_headers(&ctx); + cgit_print_docstart(&ctx); + cgit_print_pageheader(&ctx); + cgit_print_error(msg); + cgit_print_docend(); +} + void cgit_print_snapshot(const char *head, const char *hex, const char *filename, int snapshots, int dwim) @@ -163,12 +173,13 @@ void cgit_print_snapshot(const char *head, const char *hex, char *prefix = NULL; + if (!filename) { + show_error("No snapshot name specified"); + return; + } + f = get_format(filename); if (!f) { - ctx.page.mimetype = "text/html"; - cgit_print_http_headers(&ctx); - cgit_print_docstart(&ctx); - cgit_print_pageheader(&ctx); - cgit_print_error(fmt("Unsupported snapshot format: %s", filename)); - cgit_print_docend(); + show_error(xstrdup(fmt("Unsupported snapshot format: %s", + filename))); return; } @@ -26,9 +26,12 @@ static void print_text_buffer(char *buf, unsigned long size) idx = 0; lineno = 0; - htmlf(numberfmt, ++lineno); - while(idx < size - 1) { // skip absolute last newline - if (buf[idx] == '\n') - htmlf(numberfmt, ++lineno); - idx++; + + 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"); @@ -38,19 +41,24 @@ static void print_text_buffer(char *buf, unsigned long size) } +#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 += 32, buf += 32) { + for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) { htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs); - for (idx = 0; idx < 32 && ofs + idx < size; idx++) + 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 < 32 && ofs + idx < size; idx++) - htmlf("%c", isgraph(buf[idx]) ? buf[idx] : '.'); + for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) + ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.'; + ascii[idx] = '\0'; + html_txt(ascii); html("</td></tr>\n"); } |