summaryrefslogtreecommitdiffabout
path: root/cgit.c
authorLars Hjemli <hjemli@gmail.com>2009-08-21 12:26:52 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2009-08-21 12:26:52 (UTC)
commitb0f946bcc7f08168ea2858d8658a74a32accd7f5 (patch) (unidiff)
tree6bda2ca8e07bc19070155f5aa7e6e32e05d02782 /cgit.c
parentd67cc7f9d556650438e421cdcda37bc52710bffd (diff)
downloadcgit-b0f946bcc7f08168ea2858d8658a74a32accd7f5.zip
cgit-b0f946bcc7f08168ea2858d8658a74a32accd7f5.tar.gz
cgit-b0f946bcc7f08168ea2858d8658a74a32accd7f5.tar.bz2
Rename "linenumbers" to "enable-tree-linenumbers", change default to "1"
This makes the name of the cgitrc option more descriptive and at the same time changes the default from "0" to "1" in an attempt to stay backwards compatible - prior to the introduction of "source-filter" and "linenumbers", cgit always generated linenumber links in the tree view, but now this feature can be turned off (one might want to do this if the source-filter performs line-wrapping etc). While at it, the documentation is updated to match the surrounding descriptions. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'cgit.c') (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/cgit.c b/cgit.c
index a4788cb..ec40e1f 100644
--- a/cgit.c
+++ b/cgit.c
@@ -1,498 +1,499 @@
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 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include "cache.h" 10#include "cache.h"
11#include "cmd.h" 11#include "cmd.h"
12#include "configfile.h" 12#include "configfile.h"
13#include "html.h" 13#include "html.h"
14#include "ui-shared.h" 14#include "ui-shared.h"
15#include "ui-stats.h" 15#include "ui-stats.h"
16#include "scan-tree.h" 16#include "scan-tree.h"
17 17
18const char *cgit_version = CGIT_VERSION; 18const char *cgit_version = CGIT_VERSION;
19 19
20void add_mimetype(const char *name, const char *value) 20void add_mimetype(const char *name, const char *value)
21{ 21{
22 struct string_list_item *item; 22 struct string_list_item *item;
23 23
24 item = string_list_insert(xstrdup(name), &ctx.cfg.mimetypes); 24 item = string_list_insert(xstrdup(name), &ctx.cfg.mimetypes);
25 item->util = xstrdup(value); 25 item->util = xstrdup(value);
26} 26}
27 27
28struct cgit_filter *new_filter(const char *cmd, int extra_args) 28struct cgit_filter *new_filter(const char *cmd, int extra_args)
29{ 29{
30 struct cgit_filter *f; 30 struct cgit_filter *f;
31 31
32 if (!cmd || !cmd[0]) 32 if (!cmd || !cmd[0])
33 return NULL; 33 return NULL;
34 34
35 f = xmalloc(sizeof(struct cgit_filter)); 35 f = xmalloc(sizeof(struct cgit_filter));
36 f->cmd = xstrdup(cmd); 36 f->cmd = xstrdup(cmd);
37 f->argv = xmalloc((2 + extra_args) * sizeof(char *)); 37 f->argv = xmalloc((2 + extra_args) * sizeof(char *));
38 f->argv[0] = f->cmd; 38 f->argv[0] = f->cmd;
39 f->argv[1] = NULL; 39 f->argv[1] = NULL;
40 return f; 40 return f;
41} 41}
42 42
43void config_cb(const char *name, const char *value) 43void config_cb(const char *name, const char *value)
44{ 44{
45 if (!strcmp(name, "root-title")) 45 if (!strcmp(name, "root-title"))
46 ctx.cfg.root_title = xstrdup(value); 46 ctx.cfg.root_title = xstrdup(value);
47 else if (!strcmp(name, "root-desc")) 47 else if (!strcmp(name, "root-desc"))
48 ctx.cfg.root_desc = xstrdup(value); 48 ctx.cfg.root_desc = xstrdup(value);
49 else if (!strcmp(name, "root-readme")) 49 else if (!strcmp(name, "root-readme"))
50 ctx.cfg.root_readme = xstrdup(value); 50 ctx.cfg.root_readme = xstrdup(value);
51 else if (!strcmp(name, "css")) 51 else if (!strcmp(name, "css"))
52 ctx.cfg.css = xstrdup(value); 52 ctx.cfg.css = xstrdup(value);
53 else if (!strcmp(name, "favicon")) 53 else if (!strcmp(name, "favicon"))
54 ctx.cfg.favicon = xstrdup(value); 54 ctx.cfg.favicon = xstrdup(value);
55 else if (!strcmp(name, "footer")) 55 else if (!strcmp(name, "footer"))
56 ctx.cfg.footer = xstrdup(value); 56 ctx.cfg.footer = xstrdup(value);
57 else if (!strcmp(name, "head-include")) 57 else if (!strcmp(name, "head-include"))
58 ctx.cfg.head_include = xstrdup(value); 58 ctx.cfg.head_include = xstrdup(value);
59 else if (!strcmp(name, "header")) 59 else if (!strcmp(name, "header"))
60 ctx.cfg.header = xstrdup(value); 60 ctx.cfg.header = xstrdup(value);
61 else if (!strcmp(name, "logo")) 61 else if (!strcmp(name, "logo"))
62 ctx.cfg.logo = xstrdup(value); 62 ctx.cfg.logo = xstrdup(value);
63 else if (!strcmp(name, "index-header")) 63 else if (!strcmp(name, "index-header"))
64 ctx.cfg.index_header = xstrdup(value); 64 ctx.cfg.index_header = xstrdup(value);
65 else if (!strcmp(name, "index-info")) 65 else if (!strcmp(name, "index-info"))
66 ctx.cfg.index_info = xstrdup(value); 66 ctx.cfg.index_info = xstrdup(value);
67 else if (!strcmp(name, "logo-link")) 67 else if (!strcmp(name, "logo-link"))
68 ctx.cfg.logo_link = xstrdup(value); 68 ctx.cfg.logo_link = xstrdup(value);
69 else if (!strcmp(name, "linenumbers"))
70 ctx.cfg.linenumbers = atoi(value);
71 else if (!strcmp(name, "module-link")) 69 else if (!strcmp(name, "module-link"))
72 ctx.cfg.module_link = xstrdup(value); 70 ctx.cfg.module_link = xstrdup(value);
73 else if (!strcmp(name, "virtual-root")) { 71 else if (!strcmp(name, "virtual-root")) {
74 ctx.cfg.virtual_root = trim_end(value, '/'); 72 ctx.cfg.virtual_root = trim_end(value, '/');
75 if (!ctx.cfg.virtual_root && (!strcmp(value, "/"))) 73 if (!ctx.cfg.virtual_root && (!strcmp(value, "/")))
76 ctx.cfg.virtual_root = ""; 74 ctx.cfg.virtual_root = "";
77 } else if (!strcmp(name, "nocache")) 75 } else if (!strcmp(name, "nocache"))
78 ctx.cfg.nocache = atoi(value); 76 ctx.cfg.nocache = atoi(value);
79 else if (!strcmp(name, "noplainemail")) 77 else if (!strcmp(name, "noplainemail"))
80 ctx.cfg.noplainemail = atoi(value); 78 ctx.cfg.noplainemail = atoi(value);
81 else if (!strcmp(name, "noheader")) 79 else if (!strcmp(name, "noheader"))
82 ctx.cfg.noheader = atoi(value); 80 ctx.cfg.noheader = atoi(value);
83 else if (!strcmp(name, "snapshots")) 81 else if (!strcmp(name, "snapshots"))
84 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); 82 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);
85 else if (!strcmp(name, "enable-index-links")) 83 else if (!strcmp(name, "enable-index-links"))
86 ctx.cfg.enable_index_links = atoi(value); 84 ctx.cfg.enable_index_links = atoi(value);
87 else if (!strcmp(name, "enable-log-filecount")) 85 else if (!strcmp(name, "enable-log-filecount"))
88 ctx.cfg.enable_log_filecount = atoi(value); 86 ctx.cfg.enable_log_filecount = atoi(value);
89 else if (!strcmp(name, "enable-log-linecount")) 87 else if (!strcmp(name, "enable-log-linecount"))
90 ctx.cfg.enable_log_linecount = atoi(value); 88 ctx.cfg.enable_log_linecount = atoi(value);
89 else if (!strcmp(name, "enable-tree-linenumbers"))
90 ctx.cfg.enable_tree_linenumbers = atoi(value);
91 else if (!strcmp(name, "max-stats")) 91 else if (!strcmp(name, "max-stats"))
92 ctx.cfg.max_stats = cgit_find_stats_period(value, NULL); 92 ctx.cfg.max_stats = cgit_find_stats_period(value, NULL);
93 else if (!strcmp(name, "cache-size")) 93 else if (!strcmp(name, "cache-size"))
94 ctx.cfg.cache_size = atoi(value); 94 ctx.cfg.cache_size = atoi(value);
95 else if (!strcmp(name, "cache-root")) 95 else if (!strcmp(name, "cache-root"))
96 ctx.cfg.cache_root = xstrdup(value); 96 ctx.cfg.cache_root = xstrdup(value);
97 else if (!strcmp(name, "cache-root-ttl")) 97 else if (!strcmp(name, "cache-root-ttl"))
98 ctx.cfg.cache_root_ttl = atoi(value); 98 ctx.cfg.cache_root_ttl = atoi(value);
99 else if (!strcmp(name, "cache-repo-ttl")) 99 else if (!strcmp(name, "cache-repo-ttl"))
100 ctx.cfg.cache_repo_ttl = atoi(value); 100 ctx.cfg.cache_repo_ttl = atoi(value);
101 else if (!strcmp(name, "cache-static-ttl")) 101 else if (!strcmp(name, "cache-static-ttl"))
102 ctx.cfg.cache_static_ttl = atoi(value); 102 ctx.cfg.cache_static_ttl = atoi(value);
103 else if (!strcmp(name, "cache-dynamic-ttl")) 103 else if (!strcmp(name, "cache-dynamic-ttl"))
104 ctx.cfg.cache_dynamic_ttl = atoi(value); 104 ctx.cfg.cache_dynamic_ttl = atoi(value);
105 else if (!strcmp(name, "about-filter")) 105 else if (!strcmp(name, "about-filter"))
106 ctx.cfg.about_filter = new_filter(value, 0); 106 ctx.cfg.about_filter = new_filter(value, 0);
107 else if (!strcmp(name, "commit-filter")) 107 else if (!strcmp(name, "commit-filter"))
108 ctx.cfg.commit_filter = new_filter(value, 0); 108 ctx.cfg.commit_filter = new_filter(value, 0);
109 else if (!strcmp(name, "embedded")) 109 else if (!strcmp(name, "embedded"))
110 ctx.cfg.embedded = atoi(value); 110 ctx.cfg.embedded = atoi(value);
111 else if (!strcmp(name, "max-message-length")) 111 else if (!strcmp(name, "max-message-length"))
112 ctx.cfg.max_msg_len = atoi(value); 112 ctx.cfg.max_msg_len = atoi(value);
113 else if (!strcmp(name, "max-repodesc-length")) 113 else if (!strcmp(name, "max-repodesc-length"))
114 ctx.cfg.max_repodesc_len = atoi(value); 114 ctx.cfg.max_repodesc_len = atoi(value);
115 else if (!strcmp(name, "max-repo-count")) 115 else if (!strcmp(name, "max-repo-count"))
116 ctx.cfg.max_repo_count = atoi(value); 116 ctx.cfg.max_repo_count = atoi(value);
117 else if (!strcmp(name, "max-commit-count")) 117 else if (!strcmp(name, "max-commit-count"))
118 ctx.cfg.max_commit_count = atoi(value); 118 ctx.cfg.max_commit_count = atoi(value);
119 else if (!strcmp(name, "source-filter")) 119 else if (!strcmp(name, "source-filter"))
120 ctx.cfg.source_filter = new_filter(value, 1); 120 ctx.cfg.source_filter = new_filter(value, 1);
121 else if (!strcmp(name, "summary-log")) 121 else if (!strcmp(name, "summary-log"))
122 ctx.cfg.summary_log = atoi(value); 122 ctx.cfg.summary_log = atoi(value);
123 else if (!strcmp(name, "summary-branches")) 123 else if (!strcmp(name, "summary-branches"))
124 ctx.cfg.summary_branches = atoi(value); 124 ctx.cfg.summary_branches = atoi(value);
125 else if (!strcmp(name, "summary-tags")) 125 else if (!strcmp(name, "summary-tags"))
126 ctx.cfg.summary_tags = atoi(value); 126 ctx.cfg.summary_tags = atoi(value);
127 else if (!strcmp(name, "agefile")) 127 else if (!strcmp(name, "agefile"))
128 ctx.cfg.agefile = xstrdup(value); 128 ctx.cfg.agefile = xstrdup(value);
129 else if (!strcmp(name, "renamelimit")) 129 else if (!strcmp(name, "renamelimit"))
130 ctx.cfg.renamelimit = atoi(value); 130 ctx.cfg.renamelimit = atoi(value);
131 else if (!strcmp(name, "robots")) 131 else if (!strcmp(name, "robots"))
132 ctx.cfg.robots = xstrdup(value); 132 ctx.cfg.robots = xstrdup(value);
133 else if (!strcmp(name, "clone-prefix")) 133 else if (!strcmp(name, "clone-prefix"))
134 ctx.cfg.clone_prefix = xstrdup(value); 134 ctx.cfg.clone_prefix = xstrdup(value);
135 else if (!strcmp(name, "local-time")) 135 else if (!strcmp(name, "local-time"))
136 ctx.cfg.local_time = atoi(value); 136 ctx.cfg.local_time = atoi(value);
137 else if (!prefixcmp(name, "mimetype.")) 137 else if (!prefixcmp(name, "mimetype."))
138 add_mimetype(name + 9, value); 138 add_mimetype(name + 9, value);
139 else if (!strcmp(name, "repo.group")) 139 else if (!strcmp(name, "repo.group"))
140 ctx.cfg.repo_group = xstrdup(value); 140 ctx.cfg.repo_group = xstrdup(value);
141 else if (!strcmp(name, "repo.url")) 141 else if (!strcmp(name, "repo.url"))
142 ctx.repo = cgit_add_repo(value); 142 ctx.repo = cgit_add_repo(value);
143 else if (!strcmp(name, "repo.name")) 143 else if (!strcmp(name, "repo.name"))
144 ctx.repo->name = xstrdup(value); 144 ctx.repo->name = xstrdup(value);
145 else if (ctx.repo && !strcmp(name, "repo.path")) 145 else if (ctx.repo && !strcmp(name, "repo.path"))
146 ctx.repo->path = trim_end(value, '/'); 146 ctx.repo->path = trim_end(value, '/');
147 else if (ctx.repo && !strcmp(name, "repo.clone-url")) 147 else if (ctx.repo && !strcmp(name, "repo.clone-url"))
148 ctx.repo->clone_url = xstrdup(value); 148 ctx.repo->clone_url = xstrdup(value);
149 else if (ctx.repo && !strcmp(name, "repo.desc")) 149 else if (ctx.repo && !strcmp(name, "repo.desc"))
150 ctx.repo->desc = xstrdup(value); 150 ctx.repo->desc = xstrdup(value);
151 else if (ctx.repo && !strcmp(name, "repo.owner")) 151 else if (ctx.repo && !strcmp(name, "repo.owner"))
152 ctx.repo->owner = xstrdup(value); 152 ctx.repo->owner = xstrdup(value);
153 else if (ctx.repo && !strcmp(name, "repo.defbranch")) 153 else if (ctx.repo && !strcmp(name, "repo.defbranch"))
154 ctx.repo->defbranch = xstrdup(value); 154 ctx.repo->defbranch = xstrdup(value);
155 else if (ctx.repo && !strcmp(name, "repo.snapshots")) 155 else if (ctx.repo && !strcmp(name, "repo.snapshots"))
156 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */ 156 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */
157 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount")) 157 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount"))
158 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value); 158 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value);
159 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount")) 159 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount"))
160 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); 160 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value);
161 else if (ctx.repo && !strcmp(name, "repo.max-stats")) 161 else if (ctx.repo && !strcmp(name, "repo.max-stats"))
162 ctx.repo->max_stats = cgit_find_stats_period(value, NULL); 162 ctx.repo->max_stats = cgit_find_stats_period(value, NULL);
163 else if (ctx.repo && !strcmp(name, "repo.module-link")) 163 else if (ctx.repo && !strcmp(name, "repo.module-link"))
164 ctx.repo->module_link= xstrdup(value); 164 ctx.repo->module_link= xstrdup(value);
165 else if (ctx.repo && !strcmp(name, "repo.about-filter")) 165 else if (ctx.repo && !strcmp(name, "repo.about-filter"))
166 ctx.repo->about_filter = new_filter(value, 0); 166 ctx.repo->about_filter = new_filter(value, 0);
167 else if (ctx.repo && !strcmp(name, "repo.commit-filter")) 167 else if (ctx.repo && !strcmp(name, "repo.commit-filter"))
168 ctx.repo->commit_filter = new_filter(value, 0); 168 ctx.repo->commit_filter = new_filter(value, 0);
169 else if (ctx.repo && !strcmp(name, "repo.source-filter")) 169 else if (ctx.repo && !strcmp(name, "repo.source-filter"))
170 ctx.repo->source_filter = new_filter(value, 1); 170 ctx.repo->source_filter = new_filter(value, 1);
171 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) { 171 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) {
172 if (*value == '/') 172 if (*value == '/')
173 ctx.repo->readme = xstrdup(value); 173 ctx.repo->readme = xstrdup(value);
174 else 174 else
175 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value)); 175 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value));
176 } else if (!strcmp(name, "include")) 176 } else if (!strcmp(name, "include"))
177 parse_configfile(value, config_cb); 177 parse_configfile(value, config_cb);
178} 178}
179 179
180static void querystring_cb(const char *name, const char *value) 180static void querystring_cb(const char *name, const char *value)
181{ 181{
182 if (!value) 182 if (!value)
183 value = ""; 183 value = "";
184 184
185 if (!strcmp(name,"r")) { 185 if (!strcmp(name,"r")) {
186 ctx.qry.repo = xstrdup(value); 186 ctx.qry.repo = xstrdup(value);
187 ctx.repo = cgit_get_repoinfo(value); 187 ctx.repo = cgit_get_repoinfo(value);
188 } else if (!strcmp(name, "p")) { 188 } else if (!strcmp(name, "p")) {
189 ctx.qry.page = xstrdup(value); 189 ctx.qry.page = xstrdup(value);
190 } else if (!strcmp(name, "url")) { 190 } else if (!strcmp(name, "url")) {
191 ctx.qry.url = xstrdup(value); 191 ctx.qry.url = xstrdup(value);
192 cgit_parse_url(value); 192 cgit_parse_url(value);
193 } else if (!strcmp(name, "qt")) { 193 } else if (!strcmp(name, "qt")) {
194 ctx.qry.grep = xstrdup(value); 194 ctx.qry.grep = xstrdup(value);
195 } else if (!strcmp(name, "q")) { 195 } else if (!strcmp(name, "q")) {
196 ctx.qry.search = xstrdup(value); 196 ctx.qry.search = xstrdup(value);
197 } else if (!strcmp(name, "h")) { 197 } else if (!strcmp(name, "h")) {
198 ctx.qry.head = xstrdup(value); 198 ctx.qry.head = xstrdup(value);
199 ctx.qry.has_symref = 1; 199 ctx.qry.has_symref = 1;
200 } else if (!strcmp(name, "id")) { 200 } else if (!strcmp(name, "id")) {
201 ctx.qry.sha1 = xstrdup(value); 201 ctx.qry.sha1 = xstrdup(value);
202 ctx.qry.has_sha1 = 1; 202 ctx.qry.has_sha1 = 1;
203 } else if (!strcmp(name, "id2")) { 203 } else if (!strcmp(name, "id2")) {
204 ctx.qry.sha2 = xstrdup(value); 204 ctx.qry.sha2 = xstrdup(value);
205 ctx.qry.has_sha1 = 1; 205 ctx.qry.has_sha1 = 1;
206 } else if (!strcmp(name, "ofs")) { 206 } else if (!strcmp(name, "ofs")) {
207 ctx.qry.ofs = atoi(value); 207 ctx.qry.ofs = atoi(value);
208 } else if (!strcmp(name, "path")) { 208 } else if (!strcmp(name, "path")) {
209 ctx.qry.path = trim_end(value, '/'); 209 ctx.qry.path = trim_end(value, '/');
210 } else if (!strcmp(name, "name")) { 210 } else if (!strcmp(name, "name")) {
211 ctx.qry.name = xstrdup(value); 211 ctx.qry.name = xstrdup(value);
212 } else if (!strcmp(name, "mimetype")) { 212 } else if (!strcmp(name, "mimetype")) {
213 ctx.qry.mimetype = xstrdup(value); 213 ctx.qry.mimetype = xstrdup(value);
214 } else if (!strcmp(name, "s")){ 214 } else if (!strcmp(name, "s")){
215 ctx.qry.sort = xstrdup(value); 215 ctx.qry.sort = xstrdup(value);
216 } else if (!strcmp(name, "showmsg")) { 216 } else if (!strcmp(name, "showmsg")) {
217 ctx.qry.showmsg = atoi(value); 217 ctx.qry.showmsg = atoi(value);
218 } else if (!strcmp(name, "period")) { 218 } else if (!strcmp(name, "period")) {
219 ctx.qry.period = xstrdup(value); 219 ctx.qry.period = xstrdup(value);
220 } 220 }
221} 221}
222 222
223char *xstrdupn(const char *str) 223char *xstrdupn(const char *str)
224{ 224{
225 return (str ? xstrdup(str) : NULL); 225 return (str ? xstrdup(str) : NULL);
226} 226}
227 227
228static void prepare_context(struct cgit_context *ctx) 228static void prepare_context(struct cgit_context *ctx)
229{ 229{
230 memset(ctx, 0, sizeof(ctx)); 230 memset(ctx, 0, sizeof(ctx));
231 ctx->cfg.agefile = "info/web/last-modified"; 231 ctx->cfg.agefile = "info/web/last-modified";
232 ctx->cfg.nocache = 0; 232 ctx->cfg.nocache = 0;
233 ctx->cfg.cache_size = 0; 233 ctx->cfg.cache_size = 0;
234 ctx->cfg.cache_dynamic_ttl = 5; 234 ctx->cfg.cache_dynamic_ttl = 5;
235 ctx->cfg.cache_max_create_time = 5; 235 ctx->cfg.cache_max_create_time = 5;
236 ctx->cfg.cache_repo_ttl = 5; 236 ctx->cfg.cache_repo_ttl = 5;
237 ctx->cfg.cache_root = CGIT_CACHE_ROOT; 237 ctx->cfg.cache_root = CGIT_CACHE_ROOT;
238 ctx->cfg.cache_root_ttl = 5; 238 ctx->cfg.cache_root_ttl = 5;
239 ctx->cfg.cache_static_ttl = -1; 239 ctx->cfg.cache_static_ttl = -1;
240 ctx->cfg.css = "/cgit.css"; 240 ctx->cfg.css = "/cgit.css";
241 ctx->cfg.logo = "/cgit.png"; 241 ctx->cfg.logo = "/cgit.png";
242 ctx->cfg.local_time = 0; 242 ctx->cfg.local_time = 0;
243 ctx->cfg.enable_tree_linenumbers = 1;
243 ctx->cfg.max_repo_count = 50; 244 ctx->cfg.max_repo_count = 50;
244 ctx->cfg.max_commit_count = 50; 245 ctx->cfg.max_commit_count = 50;
245 ctx->cfg.max_lock_attempts = 5; 246 ctx->cfg.max_lock_attempts = 5;
246 ctx->cfg.max_msg_len = 80; 247 ctx->cfg.max_msg_len = 80;
247 ctx->cfg.max_repodesc_len = 80; 248 ctx->cfg.max_repodesc_len = 80;
248 ctx->cfg.max_stats = 0; 249 ctx->cfg.max_stats = 0;
249 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s"; 250 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s";
250 ctx->cfg.renamelimit = -1; 251 ctx->cfg.renamelimit = -1;
251 ctx->cfg.robots = "index, nofollow"; 252 ctx->cfg.robots = "index, nofollow";
252 ctx->cfg.root_title = "Git repository browser"; 253 ctx->cfg.root_title = "Git repository browser";
253 ctx->cfg.root_desc = "a fast webinterface for the git dscm"; 254 ctx->cfg.root_desc = "a fast webinterface for the git dscm";
254 ctx->cfg.script_name = CGIT_SCRIPT_NAME; 255 ctx->cfg.script_name = CGIT_SCRIPT_NAME;
255 ctx->cfg.summary_branches = 10; 256 ctx->cfg.summary_branches = 10;
256 ctx->cfg.summary_log = 10; 257 ctx->cfg.summary_log = 10;
257 ctx->cfg.summary_tags = 10; 258 ctx->cfg.summary_tags = 10;
258 ctx->env.cgit_config = xstrdupn(getenv("CGIT_CONFIG")); 259 ctx->env.cgit_config = xstrdupn(getenv("CGIT_CONFIG"));
259 ctx->env.http_host = xstrdupn(getenv("HTTP_HOST")); 260 ctx->env.http_host = xstrdupn(getenv("HTTP_HOST"));
260 ctx->env.https = xstrdupn(getenv("HTTPS")); 261 ctx->env.https = xstrdupn(getenv("HTTPS"));
261 ctx->env.no_http = xstrdupn(getenv("NO_HTTP")); 262 ctx->env.no_http = xstrdupn(getenv("NO_HTTP"));
262 ctx->env.path_info = xstrdupn(getenv("PATH_INFO")); 263 ctx->env.path_info = xstrdupn(getenv("PATH_INFO"));
263 ctx->env.query_string = xstrdupn(getenv("QUERY_STRING")); 264 ctx->env.query_string = xstrdupn(getenv("QUERY_STRING"));
264 ctx->env.request_method = xstrdupn(getenv("REQUEST_METHOD")); 265 ctx->env.request_method = xstrdupn(getenv("REQUEST_METHOD"));
265 ctx->env.script_name = xstrdupn(getenv("SCRIPT_NAME")); 266 ctx->env.script_name = xstrdupn(getenv("SCRIPT_NAME"));
266 ctx->env.server_name = xstrdupn(getenv("SERVER_NAME")); 267 ctx->env.server_name = xstrdupn(getenv("SERVER_NAME"));
267 ctx->env.server_port = xstrdupn(getenv("SERVER_PORT")); 268 ctx->env.server_port = xstrdupn(getenv("SERVER_PORT"));
268 ctx->page.mimetype = "text/html"; 269 ctx->page.mimetype = "text/html";
269 ctx->page.charset = PAGE_ENCODING; 270 ctx->page.charset = PAGE_ENCODING;
270 ctx->page.filename = NULL; 271 ctx->page.filename = NULL;
271 ctx->page.size = 0; 272 ctx->page.size = 0;
272 ctx->page.modified = time(NULL); 273 ctx->page.modified = time(NULL);
273 ctx->page.expires = ctx->page.modified; 274 ctx->page.expires = ctx->page.modified;
274 ctx->page.etag = NULL; 275 ctx->page.etag = NULL;
275 memset(&ctx->cfg.mimetypes, 0, sizeof(struct string_list)); 276 memset(&ctx->cfg.mimetypes, 0, sizeof(struct string_list));
276 if (ctx->env.script_name) 277 if (ctx->env.script_name)
277 ctx->cfg.script_name = ctx->env.script_name; 278 ctx->cfg.script_name = ctx->env.script_name;
278 if (ctx->env.query_string) 279 if (ctx->env.query_string)
279 ctx->qry.raw = ctx->env.query_string; 280 ctx->qry.raw = ctx->env.query_string;
280 if (!ctx->env.cgit_config) 281 if (!ctx->env.cgit_config)
281 ctx->env.cgit_config = CGIT_CONFIG; 282 ctx->env.cgit_config = CGIT_CONFIG;
282} 283}
283 284
284struct refmatch { 285struct refmatch {
285 char *req_ref; 286 char *req_ref;
286 char *first_ref; 287 char *first_ref;
287 int match; 288 int match;
288}; 289};
289 290
290int find_current_ref(const char *refname, const unsigned char *sha1, 291int find_current_ref(const char *refname, const unsigned char *sha1,
291 int flags, void *cb_data) 292 int flags, void *cb_data)
292{ 293{
293 struct refmatch *info; 294 struct refmatch *info;
294 295
295 info = (struct refmatch *)cb_data; 296 info = (struct refmatch *)cb_data;
296 if (!strcmp(refname, info->req_ref)) 297 if (!strcmp(refname, info->req_ref))
297 info->match = 1; 298 info->match = 1;
298 if (!info->first_ref) 299 if (!info->first_ref)
299 info->first_ref = xstrdup(refname); 300 info->first_ref = xstrdup(refname);
300 return info->match; 301 return info->match;
301} 302}
302 303
303char *find_default_branch(struct cgit_repo *repo) 304char *find_default_branch(struct cgit_repo *repo)
304{ 305{
305 struct refmatch info; 306 struct refmatch info;
306 char *ref; 307 char *ref;
307 308
308 info.req_ref = repo->defbranch; 309 info.req_ref = repo->defbranch;
309 info.first_ref = NULL; 310 info.first_ref = NULL;
310 info.match = 0; 311 info.match = 0;
311 for_each_branch_ref(find_current_ref, &info); 312 for_each_branch_ref(find_current_ref, &info);
312 if (info.match) 313 if (info.match)
313 ref = info.req_ref; 314 ref = info.req_ref;
314 else 315 else
315 ref = info.first_ref; 316 ref = info.first_ref;
316 if (ref) 317 if (ref)
317 ref = xstrdup(ref); 318 ref = xstrdup(ref);
318 return ref; 319 return ref;
319} 320}
320 321
321static int prepare_repo_cmd(struct cgit_context *ctx) 322static int prepare_repo_cmd(struct cgit_context *ctx)
322{ 323{
323 char *tmp; 324 char *tmp;
324 unsigned char sha1[20]; 325 unsigned char sha1[20];
325 int nongit = 0; 326 int nongit = 0;
326 327
327 setenv("GIT_DIR", ctx->repo->path, 1); 328 setenv("GIT_DIR", ctx->repo->path, 1);
328 setup_git_directory_gently(&nongit); 329 setup_git_directory_gently(&nongit);
329 if (nongit) { 330 if (nongit) {
330 ctx->page.title = fmt("%s - %s", ctx->cfg.root_title, 331 ctx->page.title = fmt("%s - %s", ctx->cfg.root_title,
331 "config error"); 332 "config error");
332 tmp = fmt("Not a git repository: '%s'", ctx->repo->path); 333 tmp = fmt("Not a git repository: '%s'", ctx->repo->path);
333 ctx->repo = NULL; 334 ctx->repo = NULL;
334 cgit_print_http_headers(ctx); 335 cgit_print_http_headers(ctx);
335 cgit_print_docstart(ctx); 336 cgit_print_docstart(ctx);
336 cgit_print_pageheader(ctx); 337 cgit_print_pageheader(ctx);
337 cgit_print_error(tmp); 338 cgit_print_error(tmp);
338 cgit_print_docend(); 339 cgit_print_docend();
339 return 1; 340 return 1;
340 } 341 }
341 ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc); 342 ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc);
342 343
343 if (!ctx->qry.head) { 344 if (!ctx->qry.head) {
344 ctx->qry.nohead = 1; 345 ctx->qry.nohead = 1;
345 ctx->qry.head = find_default_branch(ctx->repo); 346 ctx->qry.head = find_default_branch(ctx->repo);
346 ctx->repo->defbranch = ctx->qry.head; 347 ctx->repo->defbranch = ctx->qry.head;
347 } 348 }
348 349
349 if (!ctx->qry.head) { 350 if (!ctx->qry.head) {
350 cgit_print_http_headers(ctx); 351 cgit_print_http_headers(ctx);
351 cgit_print_docstart(ctx); 352 cgit_print_docstart(ctx);
352 cgit_print_pageheader(ctx); 353 cgit_print_pageheader(ctx);
353 cgit_print_error("Repository seems to be empty"); 354 cgit_print_error("Repository seems to be empty");
354 cgit_print_docend(); 355 cgit_print_docend();
355 return 1; 356 return 1;
356 } 357 }
357 358
358 if (get_sha1(ctx->qry.head, sha1)) { 359 if (get_sha1(ctx->qry.head, sha1)) {
359 tmp = xstrdup(ctx->qry.head); 360 tmp = xstrdup(ctx->qry.head);
360 ctx->qry.head = ctx->repo->defbranch; 361 ctx->qry.head = ctx->repo->defbranch;
361 ctx->page.status = 404; 362 ctx->page.status = 404;
362 ctx->page.statusmsg = "not found"; 363 ctx->page.statusmsg = "not found";
363 cgit_print_http_headers(ctx); 364 cgit_print_http_headers(ctx);
364 cgit_print_docstart(ctx); 365 cgit_print_docstart(ctx);
365 cgit_print_pageheader(ctx); 366 cgit_print_pageheader(ctx);
366 cgit_print_error(fmt("Invalid branch: %s", tmp)); 367 cgit_print_error(fmt("Invalid branch: %s", tmp));
367 cgit_print_docend(); 368 cgit_print_docend();
368 return 1; 369 return 1;
369 } 370 }
370 return 0; 371 return 0;
371} 372}
372 373
373static void process_request(void *cbdata) 374static void process_request(void *cbdata)
374{ 375{
375 struct cgit_context *ctx = cbdata; 376 struct cgit_context *ctx = cbdata;
376 struct cgit_cmd *cmd; 377 struct cgit_cmd *cmd;
377 378
378 cmd = cgit_get_cmd(ctx); 379 cmd = cgit_get_cmd(ctx);
379 if (!cmd) { 380 if (!cmd) {
380 ctx->page.title = "cgit error"; 381 ctx->page.title = "cgit error";
381 cgit_print_http_headers(ctx); 382 cgit_print_http_headers(ctx);
382 cgit_print_docstart(ctx); 383 cgit_print_docstart(ctx);
383 cgit_print_pageheader(ctx); 384 cgit_print_pageheader(ctx);
384 cgit_print_error("Invalid request"); 385 cgit_print_error("Invalid request");
385 cgit_print_docend(); 386 cgit_print_docend();
386 return; 387 return;
387 } 388 }
388 389
389 if (cmd->want_repo && !ctx->repo) { 390 if (cmd->want_repo && !ctx->repo) {
390 cgit_print_http_headers(ctx); 391 cgit_print_http_headers(ctx);
391 cgit_print_docstart(ctx); 392 cgit_print_docstart(ctx);
392 cgit_print_pageheader(ctx); 393 cgit_print_pageheader(ctx);
393 cgit_print_error(fmt("No repository selected")); 394 cgit_print_error(fmt("No repository selected"));
394 cgit_print_docend(); 395 cgit_print_docend();
395 return; 396 return;
396 } 397 }
397 398
398 if (ctx->repo && prepare_repo_cmd(ctx)) 399 if (ctx->repo && prepare_repo_cmd(ctx))
399 return; 400 return;
400 401
401 if (cmd->want_layout) { 402 if (cmd->want_layout) {
402 cgit_print_http_headers(ctx); 403 cgit_print_http_headers(ctx);
403 cgit_print_docstart(ctx); 404 cgit_print_docstart(ctx);
404 cgit_print_pageheader(ctx); 405 cgit_print_pageheader(ctx);
405 } 406 }
406 407
407 cmd->fn(ctx); 408 cmd->fn(ctx);
408 409
409 if (cmd->want_layout) 410 if (cmd->want_layout)
410 cgit_print_docend(); 411 cgit_print_docend();
411} 412}
412 413
413int cmp_repos(const void *a, const void *b) 414int cmp_repos(const void *a, const void *b)
414{ 415{
415 const struct cgit_repo *ra = a, *rb = b; 416 const struct cgit_repo *ra = a, *rb = b;
416 return strcmp(ra->url, rb->url); 417 return strcmp(ra->url, rb->url);
417} 418}
418 419
419void print_repo(struct cgit_repo *repo) 420void print_repo(struct cgit_repo *repo)
420{ 421{
421 printf("repo.url=%s\n", repo->url); 422 printf("repo.url=%s\n", repo->url);
422 printf("repo.name=%s\n", repo->name); 423 printf("repo.name=%s\n", repo->name);
423 printf("repo.path=%s\n", repo->path); 424 printf("repo.path=%s\n", repo->path);
424 if (repo->owner) 425 if (repo->owner)
425 printf("repo.owner=%s\n", repo->owner); 426 printf("repo.owner=%s\n", repo->owner);
426 if (repo->desc) 427 if (repo->desc)
427 printf("repo.desc=%s\n", repo->desc); 428 printf("repo.desc=%s\n", repo->desc);
428 if (repo->readme) 429 if (repo->readme)
429 printf("repo.readme=%s\n", repo->readme); 430 printf("repo.readme=%s\n", repo->readme);
430 printf("\n"); 431 printf("\n");
431} 432}
432 433
433void print_repolist(struct cgit_repolist *list) 434void print_repolist(struct cgit_repolist *list)
434{ 435{
435 int i; 436 int i;
436 437
437 for(i = 0; i < list->count; i++) 438 for(i = 0; i < list->count; i++)
438 print_repo(&list->repos[i]); 439 print_repo(&list->repos[i]);
439} 440}
440 441
441 442
442static void cgit_parse_args(int argc, const char **argv) 443static void cgit_parse_args(int argc, const char **argv)
443{ 444{
444 int i; 445 int i;
445 int scan = 0; 446 int scan = 0;
446 447
447 for (i = 1; i < argc; i++) { 448 for (i = 1; i < argc; i++) {
448 if (!strncmp(argv[i], "--cache=", 8)) { 449 if (!strncmp(argv[i], "--cache=", 8)) {
449 ctx.cfg.cache_root = xstrdup(argv[i]+8); 450 ctx.cfg.cache_root = xstrdup(argv[i]+8);
450 } 451 }
451 if (!strcmp(argv[i], "--nocache")) { 452 if (!strcmp(argv[i], "--nocache")) {
452 ctx.cfg.nocache = 1; 453 ctx.cfg.nocache = 1;
453 } 454 }
454 if (!strcmp(argv[i], "--nohttp")) { 455 if (!strcmp(argv[i], "--nohttp")) {
455 ctx.env.no_http = "1"; 456 ctx.env.no_http = "1";
456 } 457 }
457 if (!strncmp(argv[i], "--query=", 8)) { 458 if (!strncmp(argv[i], "--query=", 8)) {
458 ctx.qry.raw = xstrdup(argv[i]+8); 459 ctx.qry.raw = xstrdup(argv[i]+8);
459 } 460 }
460 if (!strncmp(argv[i], "--repo=", 7)) { 461 if (!strncmp(argv[i], "--repo=", 7)) {
461 ctx.qry.repo = xstrdup(argv[i]+7); 462 ctx.qry.repo = xstrdup(argv[i]+7);
462 } 463 }
463 if (!strncmp(argv[i], "--page=", 7)) { 464 if (!strncmp(argv[i], "--page=", 7)) {
464 ctx.qry.page = xstrdup(argv[i]+7); 465 ctx.qry.page = xstrdup(argv[i]+7);
465 } 466 }
466 if (!strncmp(argv[i], "--head=", 7)) { 467 if (!strncmp(argv[i], "--head=", 7)) {
467 ctx.qry.head = xstrdup(argv[i]+7); 468 ctx.qry.head = xstrdup(argv[i]+7);
468 ctx.qry.has_symref = 1; 469 ctx.qry.has_symref = 1;
469 } 470 }
470 if (!strncmp(argv[i], "--sha1=", 7)) { 471 if (!strncmp(argv[i], "--sha1=", 7)) {
471 ctx.qry.sha1 = xstrdup(argv[i]+7); 472 ctx.qry.sha1 = xstrdup(argv[i]+7);
472 ctx.qry.has_sha1 = 1; 473 ctx.qry.has_sha1 = 1;
473 } 474 }
474 if (!strncmp(argv[i], "--ofs=", 6)) { 475 if (!strncmp(argv[i], "--ofs=", 6)) {
475 ctx.qry.ofs = atoi(argv[i]+6); 476 ctx.qry.ofs = atoi(argv[i]+6);
476 } 477 }
477 if (!strncmp(argv[i], "--scan-tree=", 12)) { 478 if (!strncmp(argv[i], "--scan-tree=", 12)) {
478 scan++; 479 scan++;
479 scan_tree(argv[i] + 12); 480 scan_tree(argv[i] + 12);
480 } 481 }
481 } 482 }
482 if (scan) { 483 if (scan) {
483 qsort(cgit_repolist.repos, cgit_repolist.count, 484 qsort(cgit_repolist.repos, cgit_repolist.count,
484 sizeof(struct cgit_repo), cmp_repos); 485 sizeof(struct cgit_repo), cmp_repos);
485 print_repolist(&cgit_repolist); 486 print_repolist(&cgit_repolist);
486 exit(0); 487 exit(0);
487 } 488 }
488} 489}
489 490
490static int calc_ttl() 491static int calc_ttl()
491{ 492{
492 if (!ctx.repo) 493 if (!ctx.repo)
493 return ctx.cfg.cache_root_ttl; 494 return ctx.cfg.cache_root_ttl;
494 495
495 if (!ctx.qry.page) 496 if (!ctx.qry.page)
496 return ctx.cfg.cache_repo_ttl; 497 return ctx.cfg.cache_repo_ttl;
497 498
498 if (ctx.qry.has_symref) 499 if (ctx.qry.has_symref)