summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.h1
-rw-r--r--cgitrc5
-rw-r--r--shared.c3
-rw-r--r--ui-shared.c2
4 files changed, 11 insertions, 0 deletions
diff --git a/cgit.h b/cgit.h
index 6291c58..ab0efeb 100644
--- a/cgit.h
+++ b/cgit.h
@@ -94,96 +94,97 @@ struct commitinfo {
94 char *committer; 94 char *committer;
95 char *committer_email; 95 char *committer_email;
96 unsigned long committer_date; 96 unsigned long committer_date;
97 char *subject; 97 char *subject;
98 char *msg; 98 char *msg;
99 char *msg_encoding; 99 char *msg_encoding;
100}; 100};
101 101
102struct taginfo { 102struct taginfo {
103 char *tagger; 103 char *tagger;
104 char *tagger_email; 104 char *tagger_email;
105 int tagger_date; 105 int tagger_date;
106 char *msg; 106 char *msg;
107}; 107};
108 108
109struct refinfo { 109struct refinfo {
110 const char *refname; 110 const char *refname;
111 struct object *object; 111 struct object *object;
112 union { 112 union {
113 struct taginfo *tag; 113 struct taginfo *tag;
114 struct commitinfo *commit; 114 struct commitinfo *commit;
115 }; 115 };
116}; 116};
117 117
118struct reflist { 118struct reflist {
119 struct refinfo **refs; 119 struct refinfo **refs;
120 int alloc; 120 int alloc;
121 int count; 121 int count;
122}; 122};
123 123
124extern const char *cgit_version; 124extern const char *cgit_version;
125 125
126extern struct repolist cgit_repolist; 126extern struct repolist cgit_repolist;
127extern struct repoinfo *cgit_repo; 127extern struct repoinfo *cgit_repo;
128extern int cgit_cmd; 128extern int cgit_cmd;
129 129
130extern char *cgit_root_title; 130extern char *cgit_root_title;
131extern char *cgit_css; 131extern char *cgit_css;
132extern char *cgit_logo; 132extern char *cgit_logo;
133extern char *cgit_index_header; 133extern char *cgit_index_header;
134extern char *cgit_index_info; 134extern char *cgit_index_info;
135extern char *cgit_logo_link; 135extern char *cgit_logo_link;
136extern char *cgit_module_link; 136extern char *cgit_module_link;
137extern char *cgit_agefile; 137extern char *cgit_agefile;
138extern char *cgit_virtual_root; 138extern char *cgit_virtual_root;
139extern char *cgit_script_name; 139extern char *cgit_script_name;
140extern char *cgit_cache_root; 140extern char *cgit_cache_root;
141extern char *cgit_repo_group; 141extern char *cgit_repo_group;
142extern char *cgit_robots;
142 143
143extern int cgit_nocache; 144extern int cgit_nocache;
144extern int cgit_snapshots; 145extern int cgit_snapshots;
145extern int cgit_enable_index_links; 146extern int cgit_enable_index_links;
146extern int cgit_enable_log_filecount; 147extern int cgit_enable_log_filecount;
147extern int cgit_enable_log_linecount; 148extern int cgit_enable_log_linecount;
148extern int cgit_max_lock_attempts; 149extern int cgit_max_lock_attempts;
149extern int cgit_cache_root_ttl; 150extern int cgit_cache_root_ttl;
150extern int cgit_cache_repo_ttl; 151extern int cgit_cache_repo_ttl;
151extern int cgit_cache_dynamic_ttl; 152extern int cgit_cache_dynamic_ttl;
152extern int cgit_cache_static_ttl; 153extern int cgit_cache_static_ttl;
153extern int cgit_cache_max_create_time; 154extern int cgit_cache_max_create_time;
154extern int cgit_summary_log; 155extern int cgit_summary_log;
155extern int cgit_summary_tags; 156extern int cgit_summary_tags;
156extern int cgit_summary_branches; 157extern int cgit_summary_branches;
157 158
158extern int cgit_max_msg_len; 159extern int cgit_max_msg_len;
159extern int cgit_max_repodesc_len; 160extern int cgit_max_repodesc_len;
160extern int cgit_max_commit_count; 161extern int cgit_max_commit_count;
161 162
162extern int cgit_query_has_symref; 163extern int cgit_query_has_symref;
163extern int cgit_query_has_sha1; 164extern int cgit_query_has_sha1;
164 165
165extern char *cgit_querystring; 166extern char *cgit_querystring;
166extern char *cgit_query_repo; 167extern char *cgit_query_repo;
167extern char *cgit_query_page; 168extern char *cgit_query_page;
168extern char *cgit_query_search; 169extern char *cgit_query_search;
169extern char *cgit_query_grep; 170extern char *cgit_query_grep;
170extern char *cgit_query_head; 171extern char *cgit_query_head;
171extern char *cgit_query_sha1; 172extern char *cgit_query_sha1;
172extern char *cgit_query_sha2; 173extern char *cgit_query_sha2;
173extern char *cgit_query_path; 174extern char *cgit_query_path;
174extern char *cgit_query_name; 175extern char *cgit_query_name;
175extern int cgit_query_ofs; 176extern int cgit_query_ofs;
176 177
177extern int htmlfd; 178extern int htmlfd;
178 179
179extern int cgit_get_cmd_index(const char *cmd); 180extern int cgit_get_cmd_index(const char *cmd);
180extern struct repoinfo *cgit_get_repoinfo(const char *url); 181extern struct repoinfo *cgit_get_repoinfo(const char *url);
181extern void cgit_global_config_cb(const char *name, const char *value); 182extern void cgit_global_config_cb(const char *name, const char *value);
182extern void cgit_repo_config_cb(const char *name, const char *value); 183extern void cgit_repo_config_cb(const char *name, const char *value);
183extern void cgit_querystring_cb(const char *name, const char *value); 184extern void cgit_querystring_cb(const char *name, const char *value);
184 185
185extern int chk_zero(int result, char *msg); 186extern int chk_zero(int result, char *msg);
186extern int chk_positive(int result, char *msg); 187extern int chk_positive(int result, char *msg);
187extern int chk_non_negative(int result, char *msg); 188extern int chk_non_negative(int result, char *msg);
188 189
189extern int hextoint(char c); 190extern int hextoint(char c);
diff --git a/cgitrc b/cgitrc
index 6363c9c..8c616e0 100644
--- a/cgitrc
+++ b/cgitrc
@@ -1,58 +1,63 @@
1## 1##
2## cgitrc: template for /etc/cgitrc 2## cgitrc: template for /etc/cgitrc
3## 3##
4 4
5 5
6## Uncomment and set to 1 to deactivate caching of generated pages. Mostly 6## Uncomment and set to 1 to deactivate caching of generated pages. Mostly
7## usefull for testing. 7## usefull for testing.
8#nocache=0 8#nocache=0
9 9
10 10
11## This variable can be used to override the default value for "robots"
12## meta-tag. If unset, the meta-tag isn't generated.
13#robots=index, nofollow
14
15
11## Set allowed snapshot types by default. Can be overridden per repo 16## Set allowed snapshot types by default. Can be overridden per repo
12# can be any combination of zip/tar.gz/tar.bz2/tar 17# can be any combination of zip/tar.gz/tar.bz2/tar
13#snapshots=0 18#snapshots=0
14 19
15 20
16## Enable/disable extra links to summary/log/tree per repo on index page 21## Enable/disable extra links to summary/log/tree per repo on index page
17#enable-index-links=0 22#enable-index-links=0
18 23
19 24
20## Enable/disable display of 'number of files changed' in log view 25## Enable/disable display of 'number of files changed' in log view
21#enable-log-filecount=0 26#enable-log-filecount=0
22 27
23 28
24## Enable/disable display of 'number of lines changed' in log view 29## Enable/disable display of 'number of lines changed' in log view
25#enable-log-linecount=0 30#enable-log-linecount=0
26 31
27 32
28## Enable/disable display of HEAD shortlog in summary view. Set it to maximum 33## Enable/disable display of HEAD shortlog in summary view. Set it to maximum
29## number of commits that should be displayed 34## number of commits that should be displayed
30#summary-log=0 35#summary-log=0
31 36
32 37
33## Restrict the number of branches printed in summary view. Set to 0 to 38## Restrict the number of branches printed in summary view. Set to 0 to
34## print all branches. 39## print all branches.
35#summary-branches=0 40#summary-branches=0
36 41
37 42
38## Restrict the number of tags printed in summary view. Set to 0 to 43## Restrict the number of tags printed in summary view. Set to 0 to
39## print all tags. 44## print all tags.
40#summary-tags=0 45#summary-tags=0
41 46
42 47
43## The "Idle" column on the repository index page can read a timestamp 48## The "Idle" column on the repository index page can read a timestamp
44## from the specified agefile (if this file cannot be found, the mtime 49## from the specified agefile (if this file cannot be found, the mtime
45## of HEAD is used). 50## of HEAD is used).
46## The cgit repo on hjemli.net uses the the following command in it's 51## The cgit repo on hjemli.net uses the the following command in it's
47## post-receive hook to update the age-file: 52## post-receive hook to update the age-file:
48## git-for-each-ref --format="%(committerdate)" --sort=-committerdate \ 53## git-for-each-ref --format="%(committerdate)" --sort=-committerdate \
49## --count=1 > $GIT_DIR/info/web/last-modifie 54## --count=1 > $GIT_DIR/info/web/last-modifie
50## 55##
51#agefile=info/web/last-modified 56#agefile=info/web/last-modified
52 57
53 58
54## Git detects renames, but with a limit on the number of files to 59## Git detects renames, but with a limit on the number of files to
55## consider. This option can be used to specify another limit (or -1 to 60## consider. This option can be used to specify another limit (or -1 to
56## use the default limit). 61## use the default limit).
57## 62##
58#renamelimit=-1 63#renamelimit=-1
diff --git a/shared.c b/shared.c
index 8cb4808..fd8b1e3 100644
--- a/shared.c
+++ b/shared.c
@@ -1,76 +1,77 @@
1/* shared.c: global vars + some callback functions 1/* shared.c: global vars + some callback functions
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 10
11struct repolist cgit_repolist; 11struct repolist cgit_repolist;
12struct repoinfo *cgit_repo; 12struct repoinfo *cgit_repo;
13int cgit_cmd; 13int cgit_cmd;
14 14
15const char *cgit_version = CGIT_VERSION; 15const char *cgit_version = CGIT_VERSION;
16 16
17char *cgit_root_title = "Git repository browser"; 17char *cgit_root_title = "Git repository browser";
18char *cgit_css = "/cgit.css"; 18char *cgit_css = "/cgit.css";
19char *cgit_logo = "/git-logo.png"; 19char *cgit_logo = "/git-logo.png";
20char *cgit_index_header = NULL; 20char *cgit_index_header = NULL;
21char *cgit_index_info = NULL; 21char *cgit_index_info = NULL;
22char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/"; 22char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/";
23char *cgit_module_link = "./?repo=%s&page=commit&id=%s"; 23char *cgit_module_link = "./?repo=%s&page=commit&id=%s";
24char *cgit_agefile = "info/web/last-modified"; 24char *cgit_agefile = "info/web/last-modified";
25char *cgit_virtual_root = NULL; 25char *cgit_virtual_root = NULL;
26char *cgit_script_name = CGIT_SCRIPT_NAME; 26char *cgit_script_name = CGIT_SCRIPT_NAME;
27char *cgit_cache_root = CGIT_CACHE_ROOT; 27char *cgit_cache_root = CGIT_CACHE_ROOT;
28char *cgit_repo_group = NULL; 28char *cgit_repo_group = NULL;
29char *cgit_robots = "index, nofollow";
29 30
30int cgit_nocache = 0; 31int cgit_nocache = 0;
31int cgit_snapshots = 0; 32int cgit_snapshots = 0;
32int cgit_enable_index_links = 0; 33int cgit_enable_index_links = 0;
33int cgit_enable_log_filecount = 0; 34int cgit_enable_log_filecount = 0;
34int cgit_enable_log_linecount = 0; 35int cgit_enable_log_linecount = 0;
35int cgit_max_lock_attempts = 5; 36int cgit_max_lock_attempts = 5;
36int cgit_cache_root_ttl = 5; 37int cgit_cache_root_ttl = 5;
37int cgit_cache_repo_ttl = 5; 38int cgit_cache_repo_ttl = 5;
38int cgit_cache_dynamic_ttl = 5; 39int cgit_cache_dynamic_ttl = 5;
39int cgit_cache_static_ttl = -1; 40int cgit_cache_static_ttl = -1;
40int cgit_cache_max_create_time = 5; 41int cgit_cache_max_create_time = 5;
41int cgit_summary_log = 0; 42int cgit_summary_log = 0;
42int cgit_summary_tags = 0; 43int cgit_summary_tags = 0;
43int cgit_summary_branches = 0; 44int cgit_summary_branches = 0;
44int cgit_renamelimit = -1; 45int cgit_renamelimit = -1;
45 46
46int cgit_max_msg_len = 60; 47int cgit_max_msg_len = 60;
47int cgit_max_repodesc_len = 60; 48int cgit_max_repodesc_len = 60;
48int cgit_max_commit_count = 50; 49int cgit_max_commit_count = 50;
49 50
50int cgit_query_has_symref = 0; 51int cgit_query_has_symref = 0;
51int cgit_query_has_sha1 = 0; 52int cgit_query_has_sha1 = 0;
52 53
53char *cgit_querystring = NULL; 54char *cgit_querystring = NULL;
54char *cgit_query_repo = NULL; 55char *cgit_query_repo = NULL;
55char *cgit_query_page = NULL; 56char *cgit_query_page = NULL;
56char *cgit_query_head = NULL; 57char *cgit_query_head = NULL;
57char *cgit_query_search = NULL; 58char *cgit_query_search = NULL;
58char *cgit_query_grep = NULL; 59char *cgit_query_grep = NULL;
59char *cgit_query_sha1 = NULL; 60char *cgit_query_sha1 = NULL;
60char *cgit_query_sha2 = NULL; 61char *cgit_query_sha2 = NULL;
61char *cgit_query_path = NULL; 62char *cgit_query_path = NULL;
62char *cgit_query_name = NULL; 63char *cgit_query_name = NULL;
63int cgit_query_ofs = 0; 64int cgit_query_ofs = 0;
64 65
65int htmlfd = 0; 66int htmlfd = 0;
66 67
67 68
68int cgit_get_cmd_index(const char *cmd) 69int cgit_get_cmd_index(const char *cmd)
69{ 70{
70 static char *cmds[] = {"log", "commit", "diff", "tree", "blob", 71 static char *cmds[] = {"log", "commit", "diff", "tree", "blob",
71 "snapshot", "tag", "refs", NULL}; 72 "snapshot", "tag", "refs", NULL};
72 int i; 73 int i;
73 74
74 for(i = 0; cmds[i]; i++) 75 for(i = 0; cmds[i]; i++)
75 if (!strcmp(cmd, cmds[i])) 76 if (!strcmp(cmd, cmds[i]))
76 return i + 1; 77 return i + 1;
@@ -152,96 +153,98 @@ void cgit_global_config_cb(const char *name, const char *value)
152 else if (!strcmp(name, "index-header")) 153 else if (!strcmp(name, "index-header"))
153 cgit_index_header = xstrdup(value); 154 cgit_index_header = xstrdup(value);
154 else if (!strcmp(name, "index-info")) 155 else if (!strcmp(name, "index-info"))
155 cgit_index_info = xstrdup(value); 156 cgit_index_info = xstrdup(value);
156 else if (!strcmp(name, "logo-link")) 157 else if (!strcmp(name, "logo-link"))
157 cgit_logo_link = xstrdup(value); 158 cgit_logo_link = xstrdup(value);
158 else if (!strcmp(name, "module-link")) 159 else if (!strcmp(name, "module-link"))
159 cgit_module_link = xstrdup(value); 160 cgit_module_link = xstrdup(value);
160 else if (!strcmp(name, "virtual-root")) { 161 else if (!strcmp(name, "virtual-root")) {
161 cgit_virtual_root = trim_end(value, '/'); 162 cgit_virtual_root = trim_end(value, '/');
162 if (!cgit_virtual_root && (!strcmp(value, "/"))) 163 if (!cgit_virtual_root && (!strcmp(value, "/")))
163 cgit_virtual_root = ""; 164 cgit_virtual_root = "";
164 } else if (!strcmp(name, "nocache")) 165 } else if (!strcmp(name, "nocache"))
165 cgit_nocache = atoi(value); 166 cgit_nocache = atoi(value);
166 else if (!strcmp(name, "snapshots")) 167 else if (!strcmp(name, "snapshots"))
167 cgit_snapshots = cgit_parse_snapshots_mask(value); 168 cgit_snapshots = cgit_parse_snapshots_mask(value);
168 else if (!strcmp(name, "enable-index-links")) 169 else if (!strcmp(name, "enable-index-links"))
169 cgit_enable_index_links = atoi(value); 170 cgit_enable_index_links = atoi(value);
170 else if (!strcmp(name, "enable-log-filecount")) 171 else if (!strcmp(name, "enable-log-filecount"))
171 cgit_enable_log_filecount = atoi(value); 172 cgit_enable_log_filecount = atoi(value);
172 else if (!strcmp(name, "enable-log-linecount")) 173 else if (!strcmp(name, "enable-log-linecount"))
173 cgit_enable_log_linecount = atoi(value); 174 cgit_enable_log_linecount = atoi(value);
174 else if (!strcmp(name, "cache-root")) 175 else if (!strcmp(name, "cache-root"))
175 cgit_cache_root = xstrdup(value); 176 cgit_cache_root = xstrdup(value);
176 else if (!strcmp(name, "cache-root-ttl")) 177 else if (!strcmp(name, "cache-root-ttl"))
177 cgit_cache_root_ttl = atoi(value); 178 cgit_cache_root_ttl = atoi(value);
178 else if (!strcmp(name, "cache-repo-ttl")) 179 else if (!strcmp(name, "cache-repo-ttl"))
179 cgit_cache_repo_ttl = atoi(value); 180 cgit_cache_repo_ttl = atoi(value);
180 else if (!strcmp(name, "cache-static-ttl")) 181 else if (!strcmp(name, "cache-static-ttl"))
181 cgit_cache_static_ttl = atoi(value); 182 cgit_cache_static_ttl = atoi(value);
182 else if (!strcmp(name, "cache-dynamic-ttl")) 183 else if (!strcmp(name, "cache-dynamic-ttl"))
183 cgit_cache_dynamic_ttl = atoi(value); 184 cgit_cache_dynamic_ttl = atoi(value);
184 else if (!strcmp(name, "max-message-length")) 185 else if (!strcmp(name, "max-message-length"))
185 cgit_max_msg_len = atoi(value); 186 cgit_max_msg_len = atoi(value);
186 else if (!strcmp(name, "max-repodesc-length")) 187 else if (!strcmp(name, "max-repodesc-length"))
187 cgit_max_repodesc_len = atoi(value); 188 cgit_max_repodesc_len = atoi(value);
188 else if (!strcmp(name, "max-commit-count")) 189 else if (!strcmp(name, "max-commit-count"))
189 cgit_max_commit_count = atoi(value); 190 cgit_max_commit_count = atoi(value);
190 else if (!strcmp(name, "summary-log")) 191 else if (!strcmp(name, "summary-log"))
191 cgit_summary_log = atoi(value); 192 cgit_summary_log = atoi(value);
192 else if (!strcmp(name, "summary-branches")) 193 else if (!strcmp(name, "summary-branches"))
193 cgit_summary_branches = atoi(value); 194 cgit_summary_branches = atoi(value);
194 else if (!strcmp(name, "summary-tags")) 195 else if (!strcmp(name, "summary-tags"))
195 cgit_summary_tags = atoi(value); 196 cgit_summary_tags = atoi(value);
196 else if (!strcmp(name, "agefile")) 197 else if (!strcmp(name, "agefile"))
197 cgit_agefile = xstrdup(value); 198 cgit_agefile = xstrdup(value);
198 else if (!strcmp(name, "renamelimit")) 199 else if (!strcmp(name, "renamelimit"))
199 cgit_renamelimit = atoi(value); 200 cgit_renamelimit = atoi(value);
201 else if (!strcmp(name, "robots"))
202 cgit_robots = xstrdup(value);
200 else if (!strcmp(name, "repo.group")) 203 else if (!strcmp(name, "repo.group"))
201 cgit_repo_group = xstrdup(value); 204 cgit_repo_group = xstrdup(value);
202 else if (!strcmp(name, "repo.url")) 205 else if (!strcmp(name, "repo.url"))
203 cgit_repo = add_repo(value); 206 cgit_repo = add_repo(value);
204 else if (!strcmp(name, "repo.name")) 207 else if (!strcmp(name, "repo.name"))
205 cgit_repo->name = xstrdup(value); 208 cgit_repo->name = xstrdup(value);
206 else if (cgit_repo && !strcmp(name, "repo.path")) 209 else if (cgit_repo && !strcmp(name, "repo.path"))
207 cgit_repo->path = trim_end(value, '/'); 210 cgit_repo->path = trim_end(value, '/');
208 else if (cgit_repo && !strcmp(name, "repo.desc")) 211 else if (cgit_repo && !strcmp(name, "repo.desc"))
209 cgit_repo->desc = xstrdup(value); 212 cgit_repo->desc = xstrdup(value);
210 else if (cgit_repo && !strcmp(name, "repo.owner")) 213 else if (cgit_repo && !strcmp(name, "repo.owner"))
211 cgit_repo->owner = xstrdup(value); 214 cgit_repo->owner = xstrdup(value);
212 else if (cgit_repo && !strcmp(name, "repo.defbranch")) 215 else if (cgit_repo && !strcmp(name, "repo.defbranch"))
213 cgit_repo->defbranch = xstrdup(value); 216 cgit_repo->defbranch = xstrdup(value);
214 else if (cgit_repo && !strcmp(name, "repo.snapshots")) 217 else if (cgit_repo && !strcmp(name, "repo.snapshots"))
215 cgit_repo->snapshots = cgit_snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */ 218 cgit_repo->snapshots = cgit_snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */
216 else if (cgit_repo && !strcmp(name, "repo.enable-log-filecount")) 219 else if (cgit_repo && !strcmp(name, "repo.enable-log-filecount"))
217 cgit_repo->enable_log_filecount = cgit_enable_log_filecount * atoi(value); 220 cgit_repo->enable_log_filecount = cgit_enable_log_filecount * atoi(value);
218 else if (cgit_repo && !strcmp(name, "repo.enable-log-linecount")) 221 else if (cgit_repo && !strcmp(name, "repo.enable-log-linecount"))
219 cgit_repo->enable_log_linecount = cgit_enable_log_linecount * atoi(value); 222 cgit_repo->enable_log_linecount = cgit_enable_log_linecount * atoi(value);
220 else if (cgit_repo && !strcmp(name, "repo.module-link")) 223 else if (cgit_repo && !strcmp(name, "repo.module-link"))
221 cgit_repo->module_link= xstrdup(value); 224 cgit_repo->module_link= xstrdup(value);
222 else if (cgit_repo && !strcmp(name, "repo.readme") && value != NULL) { 225 else if (cgit_repo && !strcmp(name, "repo.readme") && value != NULL) {
223 if (*value == '/') 226 if (*value == '/')
224 cgit_repo->readme = xstrdup(value); 227 cgit_repo->readme = xstrdup(value);
225 else 228 else
226 cgit_repo->readme = xstrdup(fmt("%s/%s", cgit_repo->path, value)); 229 cgit_repo->readme = xstrdup(fmt("%s/%s", cgit_repo->path, value));
227 } else if (!strcmp(name, "include")) 230 } else if (!strcmp(name, "include"))
228 cgit_read_config(value, cgit_global_config_cb); 231 cgit_read_config(value, cgit_global_config_cb);
229} 232}
230 233
231void cgit_querystring_cb(const char *name, const char *value) 234void cgit_querystring_cb(const char *name, const char *value)
232{ 235{
233 if (!strcmp(name,"r")) { 236 if (!strcmp(name,"r")) {
234 cgit_query_repo = xstrdup(value); 237 cgit_query_repo = xstrdup(value);
235 cgit_repo = cgit_get_repoinfo(value); 238 cgit_repo = cgit_get_repoinfo(value);
236 } else if (!strcmp(name, "p")) { 239 } else if (!strcmp(name, "p")) {
237 cgit_query_page = xstrdup(value); 240 cgit_query_page = xstrdup(value);
238 cgit_cmd = cgit_get_cmd_index(value); 241 cgit_cmd = cgit_get_cmd_index(value);
239 } else if (!strcmp(name, "url")) { 242 } else if (!strcmp(name, "url")) {
240 cgit_parse_url(value); 243 cgit_parse_url(value);
241 } else if (!strcmp(name, "qt")) { 244 } else if (!strcmp(name, "qt")) {
242 cgit_query_grep = xstrdup(value); 245 cgit_query_grep = xstrdup(value);
243 } else if (!strcmp(name, "q")) { 246 } else if (!strcmp(name, "q")) {
244 cgit_query_search = xstrdup(value); 247 cgit_query_search = xstrdup(value);
245 } else if (!strcmp(name, "h")) { 248 } else if (!strcmp(name, "h")) {
246 cgit_query_head = xstrdup(value); 249 cgit_query_head = xstrdup(value);
247 cgit_query_has_symref = 1; 250 cgit_query_has_symref = 1;
diff --git a/ui-shared.c b/ui-shared.c
index 5192800..2f771da 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -319,96 +319,98 @@ void cgit_print_age(time_t t, time_t max_relative, char *format)
319 if (secs > max_relative && max_relative >= 0) { 319 if (secs > max_relative && max_relative >= 0) {
320 cgit_print_date(t, format); 320 cgit_print_date(t, format);
321 return; 321 return;
322 } 322 }
323 323
324 if (secs < TM_HOUR * 2) { 324 if (secs < TM_HOUR * 2) {
325 htmlf("<span class='age-mins'>%.0f min.</span>", 325 htmlf("<span class='age-mins'>%.0f min.</span>",
326 secs * 1.0 / TM_MIN); 326 secs * 1.0 / TM_MIN);
327 return; 327 return;
328 } 328 }
329 if (secs < TM_DAY * 2) { 329 if (secs < TM_DAY * 2) {
330 htmlf("<span class='age-hours'>%.0f hours</span>", 330 htmlf("<span class='age-hours'>%.0f hours</span>",
331 secs * 1.0 / TM_HOUR); 331 secs * 1.0 / TM_HOUR);
332 return; 332 return;
333 } 333 }
334 if (secs < TM_WEEK * 2) { 334 if (secs < TM_WEEK * 2) {
335 htmlf("<span class='age-days'>%.0f days</span>", 335 htmlf("<span class='age-days'>%.0f days</span>",
336 secs * 1.0 / TM_DAY); 336 secs * 1.0 / TM_DAY);
337 return; 337 return;
338 } 338 }
339 if (secs < TM_MONTH * 2) { 339 if (secs < TM_MONTH * 2) {
340 htmlf("<span class='age-weeks'>%.0f weeks</span>", 340 htmlf("<span class='age-weeks'>%.0f weeks</span>",
341 secs * 1.0 / TM_WEEK); 341 secs * 1.0 / TM_WEEK);
342 return; 342 return;
343 } 343 }
344 if (secs < TM_YEAR * 2) { 344 if (secs < TM_YEAR * 2) {
345 htmlf("<span class='age-months'>%.0f months</span>", 345 htmlf("<span class='age-months'>%.0f months</span>",
346 secs * 1.0 / TM_MONTH); 346 secs * 1.0 / TM_MONTH);
347 return; 347 return;
348 } 348 }
349 htmlf("<span class='age-years'>%.0f years</span>", 349 htmlf("<span class='age-years'>%.0f years</span>",
350 secs * 1.0 / TM_YEAR); 350 secs * 1.0 / TM_YEAR);
351} 351}
352 352
353void cgit_print_docstart(char *title, struct cacheitem *item) 353void cgit_print_docstart(char *title, struct cacheitem *item)
354{ 354{
355 html("Content-Type: text/html; charset=" PAGE_ENCODING "\n"); 355 html("Content-Type: text/html; charset=" PAGE_ENCODING "\n");
356 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime)); 356 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime));
357 htmlf("Expires: %s\n", http_date(item->st.st_mtime + 357 htmlf("Expires: %s\n", http_date(item->st.st_mtime +
358 ttl_seconds(item->ttl))); 358 ttl_seconds(item->ttl)));
359 html("\n"); 359 html("\n");
360 html(cgit_doctype); 360 html(cgit_doctype);
361 html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"); 361 html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n");
362 html("<head>\n"); 362 html("<head>\n");
363 html("<title>"); 363 html("<title>");
364 html_txt(title); 364 html_txt(title);
365 html("</title>\n"); 365 html("</title>\n");
366 htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version); 366 htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version);
367 if (cgit_robots && *cgit_robots)
368 htmlf("<meta name='robots' content='%s'/>\n", cgit_robots);
367 html("<link rel='stylesheet' type='text/css' href='"); 369 html("<link rel='stylesheet' type='text/css' href='");
368 html_attr(cgit_css); 370 html_attr(cgit_css);
369 html("'/>\n"); 371 html("'/>\n");
370 html("</head>\n"); 372 html("</head>\n");
371 html("<body>\n"); 373 html("<body>\n");
372} 374}
373 375
374void cgit_print_docend() 376void cgit_print_docend()
375{ 377{
376 html("</td>\n</tr>\n</table>\n</body>\n</html>\n"); 378 html("</td>\n</tr>\n</table>\n</body>\n</html>\n");
377} 379}
378 380
379int print_branch_option(const char *refname, const unsigned char *sha1, 381int print_branch_option(const char *refname, const unsigned char *sha1,
380 int flags, void *cb_data) 382 int flags, void *cb_data)
381{ 383{
382 char *name = (char *)refname; 384 char *name = (char *)refname;
383 html_option(name, name, cgit_query_head); 385 html_option(name, name, cgit_query_head);
384 return 0; 386 return 0;
385} 387}
386 388
387int print_archive_ref(const char *refname, const unsigned char *sha1, 389int print_archive_ref(const char *refname, const unsigned char *sha1,
388 int flags, void *cb_data) 390 int flags, void *cb_data)
389{ 391{
390 struct tag *tag; 392 struct tag *tag;
391 struct taginfo *info; 393 struct taginfo *info;
392 struct object *obj; 394 struct object *obj;
393 char buf[256], *url; 395 char buf[256], *url;
394 unsigned char fileid[20]; 396 unsigned char fileid[20];
395 int *header = (int *)cb_data; 397 int *header = (int *)cb_data;
396 398
397 if (prefixcmp(refname, "refs/archives")) 399 if (prefixcmp(refname, "refs/archives"))
398 return 0; 400 return 0;
399 strncpy(buf, refname+14, sizeof(buf)); 401 strncpy(buf, refname+14, sizeof(buf));
400 obj = parse_object(sha1); 402 obj = parse_object(sha1);
401 if (!obj) 403 if (!obj)
402 return 1; 404 return 1;
403 if (obj->type == OBJ_TAG) { 405 if (obj->type == OBJ_TAG) {
404 tag = lookup_tag(sha1); 406 tag = lookup_tag(sha1);
405 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) 407 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
406 return 0; 408 return 0;
407 hashcpy(fileid, tag->tagged->sha1); 409 hashcpy(fileid, tag->tagged->sha1);
408 } else if (obj->type != OBJ_BLOB) { 410 } else if (obj->type != OBJ_BLOB) {
409 return 0; 411 return 0;
410 } else { 412 } else {
411 hashcpy(fileid, sha1); 413 hashcpy(fileid, sha1);
412 } 414 }
413 if (!*header) { 415 if (!*header) {
414 html("<h1>download</h1>\n"); 416 html("<h1>download</h1>\n");