summaryrefslogtreecommitdiffabout
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2010-12-23 11:47:54 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2011-02-19 13:41:39 (UTC)
commit808c685ebb7cd2d24d3881b74e3be2439bd1393b (patch) (unidiff)
tree5bb224b73bbbc7d57864c587cc022fcc9826f4b3
parent17596459fe9a43428a261e66f65b227d15bf7ee5 (diff)
downloadcgit-808c685ebb7cd2d24d3881b74e3be2439bd1393b.zip
cgit-808c685ebb7cd2d24d3881b74e3be2439bd1393b.tar.gz
cgit-808c685ebb7cd2d24d3881b74e3be2439bd1393b.tar.bz2
implement repo.logo and repo.logo-link
Allow for per repo logo and logo-link; Use global logo and logo-link per default. Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c8
-rw-r--r--cgit.h2
-rw-r--r--cgitrc.5.txt9
-rw-r--r--ui-shared.c18
4 files changed, 31 insertions, 6 deletions
diff --git a/cgit.c b/cgit.c
index 412fbf0..e8c1f94 100644
--- a/cgit.c
+++ b/cgit.c
@@ -1,172 +1,176 @@
1/* cgit.c: cgi for the git scm 1/* cgit.c: cgi for the git scm
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com> 4 * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com>
5 * 5 *
6 * Licensed under GNU General Public License v2 6 * Licensed under GNU General Public License v2
7 * (see COPYING for full license text) 7 * (see COPYING for full license text)
8 */ 8 */
9 9
10#include "cgit.h" 10#include "cgit.h"
11#include "cache.h" 11#include "cache.h"
12#include "cmd.h" 12#include "cmd.h"
13#include "configfile.h" 13#include "configfile.h"
14#include "html.h" 14#include "html.h"
15#include "ui-shared.h" 15#include "ui-shared.h"
16#include "ui-stats.h" 16#include "ui-stats.h"
17#include "scan-tree.h" 17#include "scan-tree.h"
18 18
19const char *cgit_version = CGIT_VERSION; 19const char *cgit_version = CGIT_VERSION;
20 20
21void add_mimetype(const char *name, const char *value) 21void add_mimetype(const char *name, const char *value)
22{ 22{
23 struct string_list_item *item; 23 struct string_list_item *item;
24 24
25 item = string_list_insert(&ctx.cfg.mimetypes, xstrdup(name)); 25 item = string_list_insert(&ctx.cfg.mimetypes, xstrdup(name));
26 item->util = xstrdup(value); 26 item->util = xstrdup(value);
27} 27}
28 28
29struct cgit_filter *new_filter(const char *cmd, int extra_args) 29struct cgit_filter *new_filter(const char *cmd, int extra_args)
30{ 30{
31 struct cgit_filter *f; 31 struct cgit_filter *f;
32 32
33 if (!cmd || !cmd[0]) 33 if (!cmd || !cmd[0])
34 return NULL; 34 return NULL;
35 35
36 f = xmalloc(sizeof(struct cgit_filter)); 36 f = xmalloc(sizeof(struct cgit_filter));
37 f->cmd = xstrdup(cmd); 37 f->cmd = xstrdup(cmd);
38 f->argv = xmalloc((2 + extra_args) * sizeof(char *)); 38 f->argv = xmalloc((2 + extra_args) * sizeof(char *));
39 f->argv[0] = f->cmd; 39 f->argv[0] = f->cmd;
40 f->argv[1] = NULL; 40 f->argv[1] = NULL;
41 return f; 41 return f;
42} 42}
43 43
44static void process_cached_repolist(const char *path); 44static void process_cached_repolist(const char *path);
45 45
46void repo_config(struct cgit_repo *repo, const char *name, const char *value) 46void repo_config(struct cgit_repo *repo, const char *name, const char *value)
47{ 47{
48 if (!strcmp(name, "name")) 48 if (!strcmp(name, "name"))
49 repo->name = xstrdup(value); 49 repo->name = xstrdup(value);
50 else if (!strcmp(name, "clone-url")) 50 else if (!strcmp(name, "clone-url"))
51 repo->clone_url = xstrdup(value); 51 repo->clone_url = xstrdup(value);
52 else if (!strcmp(name, "desc")) 52 else if (!strcmp(name, "desc"))
53 repo->desc = xstrdup(value); 53 repo->desc = xstrdup(value);
54 else if (!strcmp(name, "owner")) 54 else if (!strcmp(name, "owner"))
55 repo->owner = xstrdup(value); 55 repo->owner = xstrdup(value);
56 else if (!strcmp(name, "defbranch")) 56 else if (!strcmp(name, "defbranch"))
57 repo->defbranch = xstrdup(value); 57 repo->defbranch = xstrdup(value);
58 else if (!strcmp(name, "snapshots")) 58 else if (!strcmp(name, "snapshots"))
59 repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); 59 repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value);
60 else if (!strcmp(name, "enable-log-filecount")) 60 else if (!strcmp(name, "enable-log-filecount"))
61 repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value); 61 repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value);
62 else if (!strcmp(name, "enable-log-linecount")) 62 else if (!strcmp(name, "enable-log-linecount"))
63 repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); 63 repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value);
64 else if (!strcmp(name, "enable-remote-branches")) 64 else if (!strcmp(name, "enable-remote-branches"))
65 repo->enable_remote_branches = atoi(value); 65 repo->enable_remote_branches = atoi(value);
66 else if (!strcmp(name, "enable-subject-links")) 66 else if (!strcmp(name, "enable-subject-links"))
67 repo->enable_subject_links = atoi(value); 67 repo->enable_subject_links = atoi(value);
68 else if (!strcmp(name, "max-stats")) 68 else if (!strcmp(name, "max-stats"))
69 repo->max_stats = cgit_find_stats_period(value, NULL); 69 repo->max_stats = cgit_find_stats_period(value, NULL);
70 else if (!strcmp(name, "module-link")) 70 else if (!strcmp(name, "module-link"))
71 repo->module_link= xstrdup(value); 71 repo->module_link= xstrdup(value);
72 else if (!strcmp(name, "section")) 72 else if (!strcmp(name, "section"))
73 repo->section = xstrdup(value); 73 repo->section = xstrdup(value);
74 else if (!strcmp(name, "readme") && value != NULL) { 74 else if (!strcmp(name, "readme") && value != NULL)
75 repo->readme = xstrdup(value); 75 repo->readme = xstrdup(value);
76 } else if (ctx.cfg.enable_filter_overrides) { 76 else if (!strcmp(name, "logo") && value != NULL)
77 repo->logo = xstrdup(value);
78 else if (!strcmp(name, "logo-link") && value != NULL)
79 repo->logo_link = xstrdup(value);
80 else if (ctx.cfg.enable_filter_overrides) {
77 if (!strcmp(name, "about-filter")) 81 if (!strcmp(name, "about-filter"))
78 repo->about_filter = new_filter(value, 0); 82 repo->about_filter = new_filter(value, 0);
79 else if (!strcmp(name, "commit-filter")) 83 else if (!strcmp(name, "commit-filter"))
80 repo->commit_filter = new_filter(value, 0); 84 repo->commit_filter = new_filter(value, 0);
81 else if (!strcmp(name, "source-filter")) 85 else if (!strcmp(name, "source-filter"))
82 repo->source_filter = new_filter(value, 1); 86 repo->source_filter = new_filter(value, 1);
83 } 87 }
84} 88}
85 89
86void config_cb(const char *name, const char *value) 90void config_cb(const char *name, const char *value)
87{ 91{
88 if (!strcmp(name, "section") || !strcmp(name, "repo.group")) 92 if (!strcmp(name, "section") || !strcmp(name, "repo.group"))
89 ctx.cfg.section = xstrdup(value); 93 ctx.cfg.section = xstrdup(value);
90 else if (!strcmp(name, "repo.url")) 94 else if (!strcmp(name, "repo.url"))
91 ctx.repo = cgit_add_repo(value); 95 ctx.repo = cgit_add_repo(value);
92 else if (ctx.repo && !strcmp(name, "repo.path")) 96 else if (ctx.repo && !strcmp(name, "repo.path"))
93 ctx.repo->path = trim_end(value, '/'); 97 ctx.repo->path = trim_end(value, '/');
94 else if (ctx.repo && !prefixcmp(name, "repo.")) 98 else if (ctx.repo && !prefixcmp(name, "repo."))
95 repo_config(ctx.repo, name + 5, value); 99 repo_config(ctx.repo, name + 5, value);
96 else if (!strcmp(name, "readme")) 100 else if (!strcmp(name, "readme"))
97 ctx.cfg.readme = xstrdup(value); 101 ctx.cfg.readme = xstrdup(value);
98 else if (!strcmp(name, "root-title")) 102 else if (!strcmp(name, "root-title"))
99 ctx.cfg.root_title = xstrdup(value); 103 ctx.cfg.root_title = xstrdup(value);
100 else if (!strcmp(name, "root-desc")) 104 else if (!strcmp(name, "root-desc"))
101 ctx.cfg.root_desc = xstrdup(value); 105 ctx.cfg.root_desc = xstrdup(value);
102 else if (!strcmp(name, "root-readme")) 106 else if (!strcmp(name, "root-readme"))
103 ctx.cfg.root_readme = xstrdup(value); 107 ctx.cfg.root_readme = xstrdup(value);
104 else if (!strcmp(name, "css")) 108 else if (!strcmp(name, "css"))
105 ctx.cfg.css = xstrdup(value); 109 ctx.cfg.css = xstrdup(value);
106 else if (!strcmp(name, "favicon")) 110 else if (!strcmp(name, "favicon"))
107 ctx.cfg.favicon = xstrdup(value); 111 ctx.cfg.favicon = xstrdup(value);
108 else if (!strcmp(name, "footer")) 112 else if (!strcmp(name, "footer"))
109 ctx.cfg.footer = xstrdup(value); 113 ctx.cfg.footer = xstrdup(value);
110 else if (!strcmp(name, "head-include")) 114 else if (!strcmp(name, "head-include"))
111 ctx.cfg.head_include = xstrdup(value); 115 ctx.cfg.head_include = xstrdup(value);
112 else if (!strcmp(name, "header")) 116 else if (!strcmp(name, "header"))
113 ctx.cfg.header = xstrdup(value); 117 ctx.cfg.header = xstrdup(value);
114 else if (!strcmp(name, "logo")) 118 else if (!strcmp(name, "logo"))
115 ctx.cfg.logo = xstrdup(value); 119 ctx.cfg.logo = xstrdup(value);
116 else if (!strcmp(name, "index-header")) 120 else if (!strcmp(name, "index-header"))
117 ctx.cfg.index_header = xstrdup(value); 121 ctx.cfg.index_header = xstrdup(value);
118 else if (!strcmp(name, "index-info")) 122 else if (!strcmp(name, "index-info"))
119 ctx.cfg.index_info = xstrdup(value); 123 ctx.cfg.index_info = xstrdup(value);
120 else if (!strcmp(name, "logo-link")) 124 else if (!strcmp(name, "logo-link"))
121 ctx.cfg.logo_link = xstrdup(value); 125 ctx.cfg.logo_link = xstrdup(value);
122 else if (!strcmp(name, "module-link")) 126 else if (!strcmp(name, "module-link"))
123 ctx.cfg.module_link = xstrdup(value); 127 ctx.cfg.module_link = xstrdup(value);
124 else if (!strcmp(name, "strict-export")) 128 else if (!strcmp(name, "strict-export"))
125 ctx.cfg.strict_export = xstrdup(value); 129 ctx.cfg.strict_export = xstrdup(value);
126 else if (!strcmp(name, "virtual-root")) { 130 else if (!strcmp(name, "virtual-root")) {
127 ctx.cfg.virtual_root = trim_end(value, '/'); 131 ctx.cfg.virtual_root = trim_end(value, '/');
128 if (!ctx.cfg.virtual_root && (!strcmp(value, "/"))) 132 if (!ctx.cfg.virtual_root && (!strcmp(value, "/")))
129 ctx.cfg.virtual_root = ""; 133 ctx.cfg.virtual_root = "";
130 } else if (!strcmp(name, "nocache")) 134 } else if (!strcmp(name, "nocache"))
131 ctx.cfg.nocache = atoi(value); 135 ctx.cfg.nocache = atoi(value);
132 else if (!strcmp(name, "noplainemail")) 136 else if (!strcmp(name, "noplainemail"))
133 ctx.cfg.noplainemail = atoi(value); 137 ctx.cfg.noplainemail = atoi(value);
134 else if (!strcmp(name, "noheader")) 138 else if (!strcmp(name, "noheader"))
135 ctx.cfg.noheader = atoi(value); 139 ctx.cfg.noheader = atoi(value);
136 else if (!strcmp(name, "snapshots")) 140 else if (!strcmp(name, "snapshots"))
137 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); 141 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);
138 else if (!strcmp(name, "enable-filter-overrides")) 142 else if (!strcmp(name, "enable-filter-overrides"))
139 ctx.cfg.enable_filter_overrides = atoi(value); 143 ctx.cfg.enable_filter_overrides = atoi(value);
140 else if (!strcmp(name, "enable-gitweb-owner")) 144 else if (!strcmp(name, "enable-gitweb-owner"))
141 ctx.cfg.enable_gitweb_owner = atoi(value); 145 ctx.cfg.enable_gitweb_owner = atoi(value);
142 else if (!strcmp(name, "enable-index-links")) 146 else if (!strcmp(name, "enable-index-links"))
143 ctx.cfg.enable_index_links = atoi(value); 147 ctx.cfg.enable_index_links = atoi(value);
144 else if (!strcmp(name, "enable-log-filecount")) 148 else if (!strcmp(name, "enable-log-filecount"))
145 ctx.cfg.enable_log_filecount = atoi(value); 149 ctx.cfg.enable_log_filecount = atoi(value);
146 else if (!strcmp(name, "enable-log-linecount")) 150 else if (!strcmp(name, "enable-log-linecount"))
147 ctx.cfg.enable_log_linecount = atoi(value); 151 ctx.cfg.enable_log_linecount = atoi(value);
148 else if (!strcmp(name, "enable-remote-branches")) 152 else if (!strcmp(name, "enable-remote-branches"))
149 ctx.cfg.enable_remote_branches = atoi(value); 153 ctx.cfg.enable_remote_branches = atoi(value);
150 else if (!strcmp(name, "enable-subject-links")) 154 else if (!strcmp(name, "enable-subject-links"))
151 ctx.cfg.enable_subject_links = atoi(value); 155 ctx.cfg.enable_subject_links = atoi(value);
152 else if (!strcmp(name, "enable-tree-linenumbers")) 156 else if (!strcmp(name, "enable-tree-linenumbers"))
153 ctx.cfg.enable_tree_linenumbers = atoi(value); 157 ctx.cfg.enable_tree_linenumbers = atoi(value);
154 else if (!strcmp(name, "max-stats")) 158 else if (!strcmp(name, "max-stats"))
155 ctx.cfg.max_stats = cgit_find_stats_period(value, NULL); 159 ctx.cfg.max_stats = cgit_find_stats_period(value, NULL);
156 else if (!strcmp(name, "cache-size")) 160 else if (!strcmp(name, "cache-size"))
157 ctx.cfg.cache_size = atoi(value); 161 ctx.cfg.cache_size = atoi(value);
158 else if (!strcmp(name, "cache-root")) 162 else if (!strcmp(name, "cache-root"))
159 ctx.cfg.cache_root = xstrdup(expand_macros(value)); 163 ctx.cfg.cache_root = xstrdup(expand_macros(value));
160 else if (!strcmp(name, "cache-root-ttl")) 164 else if (!strcmp(name, "cache-root-ttl"))
161 ctx.cfg.cache_root_ttl = atoi(value); 165 ctx.cfg.cache_root_ttl = atoi(value);
162 else if (!strcmp(name, "cache-repo-ttl")) 166 else if (!strcmp(name, "cache-repo-ttl"))
163 ctx.cfg.cache_repo_ttl = atoi(value); 167 ctx.cfg.cache_repo_ttl = atoi(value);
164 else if (!strcmp(name, "cache-scanrc-ttl")) 168 else if (!strcmp(name, "cache-scanrc-ttl"))
165 ctx.cfg.cache_scanrc_ttl = atoi(value); 169 ctx.cfg.cache_scanrc_ttl = atoi(value);
166 else if (!strcmp(name, "cache-static-ttl")) 170 else if (!strcmp(name, "cache-static-ttl"))
167 ctx.cfg.cache_static_ttl = atoi(value); 171 ctx.cfg.cache_static_ttl = atoi(value);
168 else if (!strcmp(name, "cache-dynamic-ttl")) 172 else if (!strcmp(name, "cache-dynamic-ttl"))
169 ctx.cfg.cache_dynamic_ttl = atoi(value); 173 ctx.cfg.cache_dynamic_ttl = atoi(value);
170 else if (!strcmp(name, "about-filter")) 174 else if (!strcmp(name, "about-filter"))
171 ctx.cfg.about_filter = new_filter(value, 0); 175 ctx.cfg.about_filter = new_filter(value, 0);
172 else if (!strcmp(name, "commit-filter")) 176 else if (!strcmp(name, "commit-filter"))
diff --git a/cgit.h b/cgit.h
index f5f68ac..8a9d5fa 100644
--- a/cgit.h
+++ b/cgit.h
@@ -1,168 +1,170 @@
1#ifndef CGIT_H 1#ifndef CGIT_H
2#define CGIT_H 2#define CGIT_H
3 3
4 4
5#include <git-compat-util.h> 5#include <git-compat-util.h>
6#include <cache.h> 6#include <cache.h>
7#include <grep.h> 7#include <grep.h>
8#include <object.h> 8#include <object.h>
9#include <tree.h> 9#include <tree.h>
10#include <commit.h> 10#include <commit.h>
11#include <tag.h> 11#include <tag.h>
12#include <diff.h> 12#include <diff.h>
13#include <diffcore.h> 13#include <diffcore.h>
14#include <refs.h> 14#include <refs.h>
15#include <revision.h> 15#include <revision.h>
16#include <log-tree.h> 16#include <log-tree.h>
17#include <archive.h> 17#include <archive.h>
18#include <string-list.h> 18#include <string-list.h>
19#include <xdiff-interface.h> 19#include <xdiff-interface.h>
20#include <xdiff/xdiff.h> 20#include <xdiff/xdiff.h>
21#include <utf8.h> 21#include <utf8.h>
22#include <notes.h> 22#include <notes.h>
23 23
24 24
25/* 25/*
26 * Dateformats used on misc. pages 26 * Dateformats used on misc. pages
27 */ 27 */
28#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S (%Z)" 28#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S (%Z)"
29#define FMT_SHORTDATE "%Y-%m-%d" 29#define FMT_SHORTDATE "%Y-%m-%d"
30#define FMT_ATOMDATE "%Y-%m-%dT%H:%M:%SZ" 30#define FMT_ATOMDATE "%Y-%m-%dT%H:%M:%SZ"
31 31
32 32
33/* 33/*
34 * Limits used for relative dates 34 * Limits used for relative dates
35 */ 35 */
36#define TM_MIN 60 36#define TM_MIN 60
37#define TM_HOUR (TM_MIN * 60) 37#define TM_HOUR (TM_MIN * 60)
38#define TM_DAY (TM_HOUR * 24) 38#define TM_DAY (TM_HOUR * 24)
39#define TM_WEEK (TM_DAY * 7) 39#define TM_WEEK (TM_DAY * 7)
40#define TM_YEAR (TM_DAY * 365) 40#define TM_YEAR (TM_DAY * 365)
41#define TM_MONTH (TM_YEAR / 12.0) 41#define TM_MONTH (TM_YEAR / 12.0)
42 42
43 43
44/* 44/*
45 * Default encoding 45 * Default encoding
46 */ 46 */
47#define PAGE_ENCODING "UTF-8" 47#define PAGE_ENCODING "UTF-8"
48 48
49typedef void (*configfn)(const char *name, const char *value); 49typedef void (*configfn)(const char *name, const char *value);
50typedef void (*filepair_fn)(struct diff_filepair *pair); 50typedef void (*filepair_fn)(struct diff_filepair *pair);
51typedef void (*linediff_fn)(char *line, int len); 51typedef void (*linediff_fn)(char *line, int len);
52 52
53struct cgit_filter { 53struct cgit_filter {
54 char *cmd; 54 char *cmd;
55 char **argv; 55 char **argv;
56 int old_stdout; 56 int old_stdout;
57 int pipe_fh[2]; 57 int pipe_fh[2];
58 int pid; 58 int pid;
59 int exitstatus; 59 int exitstatus;
60}; 60};
61 61
62struct cgit_repo { 62struct cgit_repo {
63 char *url; 63 char *url;
64 char *name; 64 char *name;
65 char *path; 65 char *path;
66 char *desc; 66 char *desc;
67 char *owner; 67 char *owner;
68 char *defbranch; 68 char *defbranch;
69 char *module_link; 69 char *module_link;
70 char *readme; 70 char *readme;
71 char *section; 71 char *section;
72 char *clone_url; 72 char *clone_url;
73 char *logo;
74 char *logo_link;
73 int snapshots; 75 int snapshots;
74 int enable_log_filecount; 76 int enable_log_filecount;
75 int enable_log_linecount; 77 int enable_log_linecount;
76 int enable_remote_branches; 78 int enable_remote_branches;
77 int enable_subject_links; 79 int enable_subject_links;
78 int max_stats; 80 int max_stats;
79 time_t mtime; 81 time_t mtime;
80 struct cgit_filter *about_filter; 82 struct cgit_filter *about_filter;
81 struct cgit_filter *commit_filter; 83 struct cgit_filter *commit_filter;
82 struct cgit_filter *source_filter; 84 struct cgit_filter *source_filter;
83}; 85};
84 86
85typedef void (*repo_config_fn)(struct cgit_repo *repo, const char *name, 87typedef void (*repo_config_fn)(struct cgit_repo *repo, const char *name,
86 const char *value); 88 const char *value);
87 89
88struct cgit_repolist { 90struct cgit_repolist {
89 int length; 91 int length;
90 int count; 92 int count;
91 struct cgit_repo *repos; 93 struct cgit_repo *repos;
92}; 94};
93 95
94struct commitinfo { 96struct commitinfo {
95 struct commit *commit; 97 struct commit *commit;
96 char *author; 98 char *author;
97 char *author_email; 99 char *author_email;
98 unsigned long author_date; 100 unsigned long author_date;
99 char *committer; 101 char *committer;
100 char *committer_email; 102 char *committer_email;
101 unsigned long committer_date; 103 unsigned long committer_date;
102 char *subject; 104 char *subject;
103 char *msg; 105 char *msg;
104 char *msg_encoding; 106 char *msg_encoding;
105}; 107};
106 108
107struct taginfo { 109struct taginfo {
108 char *tagger; 110 char *tagger;
109 char *tagger_email; 111 char *tagger_email;
110 unsigned long tagger_date; 112 unsigned long tagger_date;
111 char *msg; 113 char *msg;
112}; 114};
113 115
114struct refinfo { 116struct refinfo {
115 const char *refname; 117 const char *refname;
116 struct object *object; 118 struct object *object;
117 union { 119 union {
118 struct taginfo *tag; 120 struct taginfo *tag;
119 struct commitinfo *commit; 121 struct commitinfo *commit;
120 }; 122 };
121}; 123};
122 124
123struct reflist { 125struct reflist {
124 struct refinfo **refs; 126 struct refinfo **refs;
125 int alloc; 127 int alloc;
126 int count; 128 int count;
127}; 129};
128 130
129struct cgit_query { 131struct cgit_query {
130 int has_symref; 132 int has_symref;
131 int has_sha1; 133 int has_sha1;
132 char *raw; 134 char *raw;
133 char *repo; 135 char *repo;
134 char *page; 136 char *page;
135 char *search; 137 char *search;
136 char *grep; 138 char *grep;
137 char *head; 139 char *head;
138 char *sha1; 140 char *sha1;
139 char *sha2; 141 char *sha2;
140 char *path; 142 char *path;
141 char *name; 143 char *name;
142 char *mimetype; 144 char *mimetype;
143 char *url; 145 char *url;
144 char *period; 146 char *period;
145 int ofs; 147 int ofs;
146 int nohead; 148 int nohead;
147 char *sort; 149 char *sort;
148 int showmsg; 150 int showmsg;
149 int ssdiff; 151 int ssdiff;
150 int show_all; 152 int show_all;
151 int context; 153 int context;
152 int ignorews; 154 int ignorews;
153 char *vpath; 155 char *vpath;
154}; 156};
155 157
156struct cgit_config { 158struct cgit_config {
157 char *agefile; 159 char *agefile;
158 char *cache_root; 160 char *cache_root;
159 char *clone_prefix; 161 char *clone_prefix;
160 char *css; 162 char *css;
161 char *favicon; 163 char *favicon;
162 char *footer; 164 char *footer;
163 char *head_include; 165 char *head_include;
164 char *header; 166 char *header;
165 char *index_header; 167 char *index_header;
166 char *index_info; 168 char *index_info;
167 char *logo; 169 char *logo;
168 char *logo_link; 170 char *logo_link;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 8e51ca5..01157a9 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -277,192 +277,201 @@ scan-path::
277 project-list. Default value: none. See also: cache-scanrc-ttl, 277 project-list. Default value: none. See also: cache-scanrc-ttl,
278 project-list. 278 project-list.
279 279
280section:: 280section::
281 The name of the current repository section - all repositories defined 281 The name of the current repository section - all repositories defined
282 after this option will inherit the current section name. Default value: 282 after this option will inherit the current section name. Default value:
283 none. 283 none.
284 284
285section-from-path:: 285section-from-path::
286 A number which, if specified before scan-path, specifies how many 286 A number which, if specified before scan-path, specifies how many
287 path elements from each repo path to use as a default section name. 287 path elements from each repo path to use as a default section name.
288 If negative, cgit will discard the specified number of path elements 288 If negative, cgit will discard the specified number of path elements
289 above the repo directory. Default value: 0. 289 above the repo directory. Default value: 0.
290 290
291side-by-side-diffs:: 291side-by-side-diffs::
292 If set to "1" shows side-by-side diffs instead of unidiffs per 292 If set to "1" shows side-by-side diffs instead of unidiffs per
293 default. Default value: "0". 293 default. Default value: "0".
294 294
295snapshots:: 295snapshots::
296 Text which specifies the default set of snapshot formats generated by 296 Text which specifies the default set of snapshot formats generated by
297 cgit. The value is a space-separated list of zero or more of the 297 cgit. The value is a space-separated list of zero or more of the
298 values "tar", "tar.gz", "tar.bz2" and "zip". Default value: none. 298 values "tar", "tar.gz", "tar.bz2" and "zip". Default value: none.
299 299
300source-filter:: 300source-filter::
301 Specifies a command which will be invoked to format plaintext blobs 301 Specifies a command which will be invoked to format plaintext blobs
302 in the tree view. The command will get the blob content on its STDIN 302 in the tree view. The command will get the blob content on its STDIN
303 and the name of the blob as its only command line argument. The STDOUT 303 and the name of the blob as its only command line argument. The STDOUT
304 from the command will be included verbatim as the blob contents, i.e. 304 from the command will be included verbatim as the blob contents, i.e.
305 this can be used to implement e.g. syntax highlighting. Default value: 305 this can be used to implement e.g. syntax highlighting. Default value:
306 none. 306 none.
307 307
308summary-branches:: 308summary-branches::
309 Specifies the number of branches to display in the repository "summary" 309 Specifies the number of branches to display in the repository "summary"
310 view. Default value: "10". 310 view. Default value: "10".
311 311
312summary-log:: 312summary-log::
313 Specifies the number of log entries to display in the repository 313 Specifies the number of log entries to display in the repository
314 "summary" view. Default value: "10". 314 "summary" view. Default value: "10".
315 315
316summary-tags:: 316summary-tags::
317 Specifies the number of tags to display in the repository "summary" 317 Specifies the number of tags to display in the repository "summary"
318 view. Default value: "10". 318 view. Default value: "10".
319 319
320strict-export:: 320strict-export::
321 Filename which, if specified, needs to be present within the repository 321 Filename which, if specified, needs to be present within the repository
322 for cgit to allow access to that repository. This can be used to emulate 322 for cgit to allow access to that repository. This can be used to emulate
323 gitweb's EXPORT_OK and STRICT_EXPORT functionality and limit cgit's 323 gitweb's EXPORT_OK and STRICT_EXPORT functionality and limit cgit's
324 repositories to match those exported by git-daemon. This option MUST come 324 repositories to match those exported by git-daemon. This option MUST come
325 before 'scan-path'. 325 before 'scan-path'.
326 326
327virtual-root:: 327virtual-root::
328 Url which, if specified, will be used as root for all cgit links. It 328 Url which, if specified, will be used as root for all cgit links. It
329 will also cause cgit to generate 'virtual urls', i.e. urls like 329 will also cause cgit to generate 'virtual urls', i.e. urls like
330 '/cgit/tree/README' as opposed to '?r=cgit&p=tree&path=README'. Default 330 '/cgit/tree/README' as opposed to '?r=cgit&p=tree&path=README'. Default
331 value: none. 331 value: none.
332 NOTE: cgit has recently learned how to use PATH_INFO to achieve the 332 NOTE: cgit has recently learned how to use PATH_INFO to achieve the
333 same kind of virtual urls, so this option will probably be deprecated. 333 same kind of virtual urls, so this option will probably be deprecated.
334 334
335REPOSITORY SETTINGS 335REPOSITORY SETTINGS
336------------------- 336-------------------
337repo.about-filter:: 337repo.about-filter::
338 Override the default about-filter. Default value: none. See also: 338 Override the default about-filter. Default value: none. See also:
339 "enable-filter-overrides". 339 "enable-filter-overrides".
340 340
341repo.clone-url:: 341repo.clone-url::
342 A list of space-separated urls which can be used to clone this repo. 342 A list of space-separated urls which can be used to clone this repo.
343 Default value: none. 343 Default value: none.
344 344
345repo.commit-filter:: 345repo.commit-filter::
346 Override the default commit-filter. Default value: none. See also: 346 Override the default commit-filter. Default value: none. See also:
347 "enable-filter-overrides". 347 "enable-filter-overrides".
348 348
349repo.defbranch:: 349repo.defbranch::
350 The name of the default branch for this repository. If no such branch 350 The name of the default branch for this repository. If no such branch
351 exists in the repository, the first branch name (when sorted) is used 351 exists in the repository, the first branch name (when sorted) is used
352 as default instead. Default value: "master". 352 as default instead. Default value: "master".
353 353
354repo.desc:: 354repo.desc::
355 The value to show as repository description. Default value: none. 355 The value to show as repository description. Default value: none.
356 356
357repo.enable-log-filecount:: 357repo.enable-log-filecount::
358 A flag which can be used to disable the global setting 358 A flag which can be used to disable the global setting
359 `enable-log-filecount'. Default value: none. 359 `enable-log-filecount'. Default value: none.
360 360
361repo.enable-log-linecount:: 361repo.enable-log-linecount::
362 A flag which can be used to disable the global setting 362 A flag which can be used to disable the global setting
363 `enable-log-linecount'. Default value: none. 363 `enable-log-linecount'. Default value: none.
364 364
365repo.enable-remote-branches:: 365repo.enable-remote-branches::
366 Flag which, when set to "1", will make cgit display remote branches 366 Flag which, when set to "1", will make cgit display remote branches
367 in the summary and refs views. Default value: <enable-remote-branches>. 367 in the summary and refs views. Default value: <enable-remote-branches>.
368 368
369repo.enable-subject-links:: 369repo.enable-subject-links::
370 A flag which can be used to override the global setting 370 A flag which can be used to override the global setting
371 `enable-subject-links'. Default value: none. 371 `enable-subject-links'. Default value: none.
372 372
373repo.logo::
374 Url which specifies the source of an image which will be used as a logo
375 on this repo's pages. Default value: global logo.
376
377repo.logo-link::
378 Url loaded when clicking on the cgit logo image. If unspecified the
379 calculated url of the repository index page will be used. Default
380 value: global logo-link.
381
373repo.max-stats:: 382repo.max-stats::
374 Override the default maximum statistics period. Valid values are equal 383 Override the default maximum statistics period. Valid values are equal
375 to the values specified for the global "max-stats" setting. Default 384 to the values specified for the global "max-stats" setting. Default
376 value: none. 385 value: none.
377 386
378repo.name:: 387repo.name::
379 The value to show as repository name. Default value: <repo.url>. 388 The value to show as repository name. Default value: <repo.url>.
380 389
381repo.owner:: 390repo.owner::
382 A value used to identify the owner of the repository. Default value: 391 A value used to identify the owner of the repository. Default value:
383 none. 392 none.
384 393
385repo.path:: 394repo.path::
386 An absolute path to the repository directory. For non-bare repositories 395 An absolute path to the repository directory. For non-bare repositories
387 this is the .git-directory. Default value: none. 396 this is the .git-directory. Default value: none.
388 397
389repo.readme:: 398repo.readme::
390 A path (relative to <repo.path>) which specifies a file to include 399 A path (relative to <repo.path>) which specifies a file to include
391 verbatim as the "About" page for this repo. You may also specify a 400 verbatim as the "About" page for this repo. You may also specify a
392 git refspec by head or by hash by prepending the refspec followed by 401 git refspec by head or by hash by prepending the refspec followed by
393 a colon. For example, "master:docs/readme.mkd" Default value: <readme>. 402 a colon. For example, "master:docs/readme.mkd" Default value: <readme>.
394 403
395repo.snapshots:: 404repo.snapshots::
396 A mask of allowed snapshot-formats for this repo, restricted by the 405 A mask of allowed snapshot-formats for this repo, restricted by the
397 "snapshots" global setting. Default value: <snapshots>. 406 "snapshots" global setting. Default value: <snapshots>.
398 407
399repo.section:: 408repo.section::
400 Override the current section name for this repository. Default value: 409 Override the current section name for this repository. Default value:
401 none. 410 none.
402 411
403repo.source-filter:: 412repo.source-filter::
404 Override the default source-filter. Default value: none. See also: 413 Override the default source-filter. Default value: none. See also:
405 "enable-filter-overrides". 414 "enable-filter-overrides".
406 415
407repo.url:: 416repo.url::
408 The relative url used to access the repository. This must be the first 417 The relative url used to access the repository. This must be the first
409 setting specified for each repo. Default value: none. 418 setting specified for each repo. Default value: none.
410 419
411 420
412REPOSITORY-SPECIFIC CGITRC FILE 421REPOSITORY-SPECIFIC CGITRC FILE
413------------------------------- 422-------------------------------
414When the option "scan-path" is used to auto-discover git repositories, cgit 423When the option "scan-path" is used to auto-discover git repositories, cgit
415will try to parse the file "cgitrc" within any found repository. Such a 424will try to parse the file "cgitrc" within any found repository. Such a
416repo-specific config file may contain any of the repo-specific options 425repo-specific config file may contain any of the repo-specific options
417described above, except "repo.url" and "repo.path". Additionally, the "filter" 426described above, except "repo.url" and "repo.path". Additionally, the "filter"
418options are only acknowledged in repo-specific config files when 427options are only acknowledged in repo-specific config files when
419"enable-filter-overrides" is set to "1". 428"enable-filter-overrides" is set to "1".
420 429
421Note: the "repo." prefix is dropped from the option names in repo-specific 430Note: the "repo." prefix is dropped from the option names in repo-specific
422config files, e.g. "repo.desc" becomes "desc". 431config files, e.g. "repo.desc" becomes "desc".
423 432
424 433
425EXAMPLE CGITRC FILE 434EXAMPLE CGITRC FILE
426------------------- 435-------------------
427 436
428.... 437....
429# Enable caching of up to 1000 output entriess 438# Enable caching of up to 1000 output entriess
430cache-size=1000 439cache-size=1000
431 440
432 441
433# Specify some default clone prefixes 442# Specify some default clone prefixes
434clone-prefix=git://example.com ssh://example.com/pub/git http://example.com/git 443clone-prefix=git://example.com ssh://example.com/pub/git http://example.com/git
435 444
436# Specify the css url 445# Specify the css url
437css=/css/cgit.css 446css=/css/cgit.css
438 447
439 448
440# Show extra links for each repository on the index page 449# Show extra links for each repository on the index page
441enable-index-links=1 450enable-index-links=1
442 451
443 452
444# Show number of affected files per commit on the log pages 453# Show number of affected files per commit on the log pages
445enable-log-filecount=1 454enable-log-filecount=1
446 455
447 456
448# Show number of added/removed lines per commit on the log pages 457# Show number of added/removed lines per commit on the log pages
449enable-log-linecount=1 458enable-log-linecount=1
450 459
451 460
452# Add a cgit favicon 461# Add a cgit favicon
453favicon=/favicon.ico 462favicon=/favicon.ico
454 463
455 464
456# Use a custom logo 465# Use a custom logo
457logo=/img/mylogo.png 466logo=/img/mylogo.png
458 467
459 468
460# Enable statistics per week, month and quarter 469# Enable statistics per week, month and quarter
461max-stats=quarter 470max-stats=quarter
462 471
463 472
464# Set the title and heading of the repository index page 473# Set the title and heading of the repository index page
465root-title=example.com git repositories 474root-title=example.com git repositories
466 475
467 476
468# Set a subheading for the repository index page 477# Set a subheading for the repository index page
diff --git a/ui-shared.c b/ui-shared.c
index ae29615..7efae7a 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -663,203 +663,213 @@ int print_archive_ref(const char *refname, const unsigned char *sha1,
663{ 663{
664 struct tag *tag; 664 struct tag *tag;
665 struct taginfo *info; 665 struct taginfo *info;
666 struct object *obj; 666 struct object *obj;
667 char buf[256], *url; 667 char buf[256], *url;
668 unsigned char fileid[20]; 668 unsigned char fileid[20];
669 int *header = (int *)cb_data; 669 int *header = (int *)cb_data;
670 670
671 if (prefixcmp(refname, "refs/archives")) 671 if (prefixcmp(refname, "refs/archives"))
672 return 0; 672 return 0;
673 strncpy(buf, refname+14, sizeof(buf)); 673 strncpy(buf, refname+14, sizeof(buf));
674 obj = parse_object(sha1); 674 obj = parse_object(sha1);
675 if (!obj) 675 if (!obj)
676 return 1; 676 return 1;
677 if (obj->type == OBJ_TAG) { 677 if (obj->type == OBJ_TAG) {
678 tag = lookup_tag(sha1); 678 tag = lookup_tag(sha1);
679 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) 679 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
680 return 0; 680 return 0;
681 hashcpy(fileid, tag->tagged->sha1); 681 hashcpy(fileid, tag->tagged->sha1);
682 } else if (obj->type != OBJ_BLOB) { 682 } else if (obj->type != OBJ_BLOB) {
683 return 0; 683 return 0;
684 } else { 684 } else {
685 hashcpy(fileid, sha1); 685 hashcpy(fileid, sha1);
686 } 686 }
687 if (!*header) { 687 if (!*header) {
688 html("<h1>download</h1>\n"); 688 html("<h1>download</h1>\n");
689 *header = 1; 689 *header = 1;
690 } 690 }
691 url = cgit_pageurl(ctx.qry.repo, "blob", 691 url = cgit_pageurl(ctx.qry.repo, "blob",
692 fmt("id=%s&amp;path=%s", sha1_to_hex(fileid), 692 fmt("id=%s&amp;path=%s", sha1_to_hex(fileid),
693 buf)); 693 buf));
694 html_link_open(url, NULL, "menu"); 694 html_link_open(url, NULL, "menu");
695 html_txt(strlpart(buf, 20)); 695 html_txt(strlpart(buf, 20));
696 html_link_close(); 696 html_link_close();
697 return 0; 697 return 0;
698} 698}
699 699
700void cgit_add_hidden_formfields(int incl_head, int incl_search, 700void cgit_add_hidden_formfields(int incl_head, int incl_search,
701 const char *page) 701 const char *page)
702{ 702{
703 char *url; 703 char *url;
704 704
705 if (!ctx.cfg.virtual_root) { 705 if (!ctx.cfg.virtual_root) {
706 url = fmt("%s/%s", ctx.qry.repo, page); 706 url = fmt("%s/%s", ctx.qry.repo, page);
707 if (ctx.qry.vpath) 707 if (ctx.qry.vpath)
708 url = fmt("%s/%s", url, ctx.qry.vpath); 708 url = fmt("%s/%s", url, ctx.qry.vpath);
709 html_hidden("url", url); 709 html_hidden("url", url);
710 } 710 }
711 711
712 if (incl_head && ctx.qry.head && ctx.repo->defbranch && 712 if (incl_head && ctx.qry.head && ctx.repo->defbranch &&
713 strcmp(ctx.qry.head, ctx.repo->defbranch)) 713 strcmp(ctx.qry.head, ctx.repo->defbranch))
714 html_hidden("h", ctx.qry.head); 714 html_hidden("h", ctx.qry.head);
715 715
716 if (ctx.qry.sha1) 716 if (ctx.qry.sha1)
717 html_hidden("id", ctx.qry.sha1); 717 html_hidden("id", ctx.qry.sha1);
718 if (ctx.qry.sha2) 718 if (ctx.qry.sha2)
719 html_hidden("id2", ctx.qry.sha2); 719 html_hidden("id2", ctx.qry.sha2);
720 if (ctx.qry.showmsg) 720 if (ctx.qry.showmsg)
721 html_hidden("showmsg", "1"); 721 html_hidden("showmsg", "1");
722 722
723 if (incl_search) { 723 if (incl_search) {
724 if (ctx.qry.grep) 724 if (ctx.qry.grep)
725 html_hidden("qt", ctx.qry.grep); 725 html_hidden("qt", ctx.qry.grep);
726 if (ctx.qry.search) 726 if (ctx.qry.search)
727 html_hidden("q", ctx.qry.search); 727 html_hidden("q", ctx.qry.search);
728 } 728 }
729} 729}
730 730
731static const char *hc(struct cgit_context *ctx, const char *page) 731static const char *hc(struct cgit_context *ctx, const char *page)
732{ 732{
733 return strcmp(ctx->qry.page, page) ? NULL : "active"; 733 return strcmp(ctx->qry.page, page) ? NULL : "active";
734} 734}
735 735
736static void cgit_print_path_crumbs(struct cgit_context *ctx, char *path) 736static void cgit_print_path_crumbs(struct cgit_context *ctx, char *path)
737{ 737{
738 char *old_path = ctx->qry.path; 738 char *old_path = ctx->qry.path;
739 char *p = path, *q, *end = path + strlen(path); 739 char *p = path, *q, *end = path + strlen(path);
740 740
741 ctx->qry.path = NULL; 741 ctx->qry.path = NULL;
742 cgit_self_link("root", NULL, NULL, ctx); 742 cgit_self_link("root", NULL, NULL, ctx);
743 ctx->qry.path = p = path; 743 ctx->qry.path = p = path;
744 while (p < end) { 744 while (p < end) {
745 if (!(q = strchr(p, '/'))) 745 if (!(q = strchr(p, '/')))
746 q = end; 746 q = end;
747 *q = '\0'; 747 *q = '\0';
748 html_txt("/"); 748 html_txt("/");
749 cgit_self_link(p, NULL, NULL, ctx); 749 cgit_self_link(p, NULL, NULL, ctx);
750 if (q < end) 750 if (q < end)
751 *q = '/'; 751 *q = '/';
752 p = q + 1; 752 p = q + 1;
753 } 753 }
754 ctx->qry.path = old_path; 754 ctx->qry.path = old_path;
755} 755}
756 756
757static void print_header(struct cgit_context *ctx) 757static void print_header(struct cgit_context *ctx)
758{ 758{
759 char *logo = NULL, *logo_link = NULL;
760
759 html("<table id='header'>\n"); 761 html("<table id='header'>\n");
760 html("<tr>\n"); 762 html("<tr>\n");
761 763
762 if (ctx->cfg.logo && ctx->cfg.logo[0] != 0) { 764 if (ctx->repo && ctx->repo->logo && *ctx->repo->logo)
765 logo = ctx->repo->logo;
766 else
767 logo = ctx->cfg.logo;
768 if (ctx->repo && ctx->repo->logo_link && *ctx->repo->logo_link)
769 logo_link = ctx->repo->logo_link;
770 else
771 logo_link = ctx->cfg.logo_link;
772 if (logo && *logo) {
763 html("<td class='logo' rowspan='2'><a href='"); 773 html("<td class='logo' rowspan='2'><a href='");
764 if (ctx->cfg.logo_link) 774 if (logo_link && *logo_link)
765 html_attr(ctx->cfg.logo_link); 775 html_attr(logo_link);
766 else 776 else
767 html_attr(cgit_rooturl()); 777 html_attr(cgit_rooturl());
768 html("'><img src='"); 778 html("'><img src='");
769 html_attr(ctx->cfg.logo); 779 html_attr(logo);
770 html("' alt='cgit logo'/></a></td>\n"); 780 html("' alt='cgit logo'/></a></td>\n");
771 } 781 }
772 782
773 html("<td class='main'>"); 783 html("<td class='main'>");
774 if (ctx->repo) { 784 if (ctx->repo) {
775 cgit_index_link("index", NULL, NULL, NULL, 0); 785 cgit_index_link("index", NULL, NULL, NULL, 0);
776 html(" : "); 786 html(" : ");
777 cgit_summary_link(ctx->repo->name, ctx->repo->name, NULL, NULL); 787 cgit_summary_link(ctx->repo->name, ctx->repo->name, NULL, NULL);
778 html("</td><td class='form'>"); 788 html("</td><td class='form'>");
779 html("<form method='get' action=''>\n"); 789 html("<form method='get' action=''>\n");
780 cgit_add_hidden_formfields(0, 1, ctx->qry.page); 790 cgit_add_hidden_formfields(0, 1, ctx->qry.page);
781 html("<select name='h' onchange='this.form.submit();'>\n"); 791 html("<select name='h' onchange='this.form.submit();'>\n");
782 for_each_branch_ref(print_branch_option, ctx->qry.head); 792 for_each_branch_ref(print_branch_option, ctx->qry.head);
783 html("</select> "); 793 html("</select> ");
784 html("<input type='submit' name='' value='switch'/>"); 794 html("<input type='submit' name='' value='switch'/>");
785 html("</form>"); 795 html("</form>");
786 } else 796 } else
787 html_txt(ctx->cfg.root_title); 797 html_txt(ctx->cfg.root_title);
788 html("</td></tr>\n"); 798 html("</td></tr>\n");
789 799
790 html("<tr><td class='sub'>"); 800 html("<tr><td class='sub'>");
791 if (ctx->repo) { 801 if (ctx->repo) {
792 html_txt(ctx->repo->desc); 802 html_txt(ctx->repo->desc);
793 html("</td><td class='sub right'>"); 803 html("</td><td class='sub right'>");
794 html_txt(ctx->repo->owner); 804 html_txt(ctx->repo->owner);
795 } else { 805 } else {
796 if (ctx->cfg.root_desc) 806 if (ctx->cfg.root_desc)
797 html_txt(ctx->cfg.root_desc); 807 html_txt(ctx->cfg.root_desc);
798 else if (ctx->cfg.index_info) 808 else if (ctx->cfg.index_info)
799 html_include(ctx->cfg.index_info); 809 html_include(ctx->cfg.index_info);
800 } 810 }
801 html("</td></tr></table>\n"); 811 html("</td></tr></table>\n");
802} 812}
803 813
804void cgit_print_pageheader(struct cgit_context *ctx) 814void cgit_print_pageheader(struct cgit_context *ctx)
805{ 815{
806 html("<div id='cgit'>"); 816 html("<div id='cgit'>");
807 if (!ctx->cfg.noheader) 817 if (!ctx->cfg.noheader)
808 print_header(ctx); 818 print_header(ctx);
809 819
810 html("<table class='tabs'><tr><td>\n"); 820 html("<table class='tabs'><tr><td>\n");
811 if (ctx->repo) { 821 if (ctx->repo) {
812 cgit_summary_link("summary", NULL, hc(ctx, "summary"), 822 cgit_summary_link("summary", NULL, hc(ctx, "summary"),
813 ctx->qry.head); 823 ctx->qry.head);
814 cgit_refs_link("refs", NULL, hc(ctx, "refs"), ctx->qry.head, 824 cgit_refs_link("refs", NULL, hc(ctx, "refs"), ctx->qry.head,
815 ctx->qry.sha1, NULL); 825 ctx->qry.sha1, NULL);
816 cgit_log_link("log", NULL, hc(ctx, "log"), ctx->qry.head, 826 cgit_log_link("log", NULL, hc(ctx, "log"), ctx->qry.head,
817 NULL, ctx->qry.vpath, 0, NULL, NULL, 827 NULL, ctx->qry.vpath, 0, NULL, NULL,
818 ctx->qry.showmsg); 828 ctx->qry.showmsg);
819 cgit_tree_link("tree", NULL, hc(ctx, "tree"), ctx->qry.head, 829 cgit_tree_link("tree", NULL, hc(ctx, "tree"), ctx->qry.head,
820 ctx->qry.sha1, ctx->qry.vpath); 830 ctx->qry.sha1, ctx->qry.vpath);
821 cgit_commit_link("commit", NULL, hc(ctx, "commit"), 831 cgit_commit_link("commit", NULL, hc(ctx, "commit"),
822 ctx->qry.head, ctx->qry.sha1, ctx->qry.vpath, 0); 832 ctx->qry.head, ctx->qry.sha1, ctx->qry.vpath, 0);
823 cgit_diff_link("diff", NULL, hc(ctx, "diff"), ctx->qry.head, 833 cgit_diff_link("diff", NULL, hc(ctx, "diff"), ctx->qry.head,
824 ctx->qry.sha1, ctx->qry.sha2, ctx->qry.vpath, 0); 834 ctx->qry.sha1, ctx->qry.sha2, ctx->qry.vpath, 0);
825 if (ctx->repo->max_stats) 835 if (ctx->repo->max_stats)
826 cgit_stats_link("stats", NULL, hc(ctx, "stats"), 836 cgit_stats_link("stats", NULL, hc(ctx, "stats"),
827 ctx->qry.head, ctx->qry.vpath); 837 ctx->qry.head, ctx->qry.vpath);
828 if (ctx->repo->readme) 838 if (ctx->repo->readme)
829 reporevlink("about", "about", NULL, 839 reporevlink("about", "about", NULL,
830 hc(ctx, "about"), ctx->qry.head, NULL, 840 hc(ctx, "about"), ctx->qry.head, NULL,
831 NULL); 841 NULL);
832 html("</td><td class='form'>"); 842 html("</td><td class='form'>");
833 html("<form class='right' method='get' action='"); 843 html("<form class='right' method='get' action='");
834 if (ctx->cfg.virtual_root) 844 if (ctx->cfg.virtual_root)
835 html_url_path(cgit_fileurl(ctx->qry.repo, "log", 845 html_url_path(cgit_fileurl(ctx->qry.repo, "log",
836 ctx->qry.vpath, NULL)); 846 ctx->qry.vpath, NULL));
837 html("'>\n"); 847 html("'>\n");
838 cgit_add_hidden_formfields(1, 0, "log"); 848 cgit_add_hidden_formfields(1, 0, "log");
839 html("<select name='qt'>\n"); 849 html("<select name='qt'>\n");
840 html_option("grep", "log msg", ctx->qry.grep); 850 html_option("grep", "log msg", ctx->qry.grep);
841 html_option("author", "author", ctx->qry.grep); 851 html_option("author", "author", ctx->qry.grep);
842 html_option("committer", "committer", ctx->qry.grep); 852 html_option("committer", "committer", ctx->qry.grep);
843 html_option("range", "range", ctx->qry.grep); 853 html_option("range", "range", ctx->qry.grep);
844 html("</select>\n"); 854 html("</select>\n");
845 html("<input class='txt' type='text' size='10' name='q' value='"); 855 html("<input class='txt' type='text' size='10' name='q' value='");
846 html_attr(ctx->qry.search); 856 html_attr(ctx->qry.search);
847 html("'/>\n"); 857 html("'/>\n");
848 html("<input type='submit' value='search'/>\n"); 858 html("<input type='submit' value='search'/>\n");
849 html("</form>\n"); 859 html("</form>\n");
850 } else { 860 } else {
851 site_link(NULL, "index", NULL, hc(ctx, "repolist"), NULL, 0); 861 site_link(NULL, "index", NULL, hc(ctx, "repolist"), NULL, 0);
852 if (ctx->cfg.root_readme) 862 if (ctx->cfg.root_readme)
853 site_link("about", "about", NULL, hc(ctx, "about"), 863 site_link("about", "about", NULL, hc(ctx, "about"),
854 NULL, 0); 864 NULL, 0);
855 html("</td><td class='form'>"); 865 html("</td><td class='form'>");
856 html("<form method='get' action='"); 866 html("<form method='get' action='");
857 html_attr(cgit_rooturl()); 867 html_attr(cgit_rooturl());
858 html("'>\n"); 868 html("'>\n");
859 html("<input type='text' name='q' size='10' value='"); 869 html("<input type='text' name='q' size='10' value='");
860 html_attr(ctx->qry.search); 870 html_attr(ctx->qry.search);
861 html("'/>\n"); 871 html("'/>\n");
862 html("<input type='submit' value='search'/>\n"); 872 html("<input type='submit' value='search'/>\n");
863 html("</form>"); 873 html("</form>");
864 } 874 }
865 html("</td></tr></table>\n"); 875 html("</td></tr></table>\n");