summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2009-07-25 10:04:08 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2009-07-25 10:04:08 (UTC)
commit542f6a433034935a1aa895f7ef3273968915a5d1 (patch) (unidiff)
tree8fc123b3d9f014f31b5b160a9456c85b6c19aa0d
parent681fdc45473143de3f3c5f69fbc7b94f5d6b0b75 (diff)
parentf618e8f7174011e1e793df2c67fb9d1341652054 (diff)
downloadcgit-542f6a433034935a1aa895f7ef3273968915a5d1.zip
cgit-542f6a433034935a1aa895f7ef3273968915a5d1.tar.gz
cgit-542f6a433034935a1aa895f7ef3273968915a5d1.tar.bz2
Merge branch 'ml/head-include'
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c2
-rw-r--r--cgit.h1
-rw-r--r--cgitrc.5.txt4
-rw-r--r--ui-shared.c4
4 files changed, 10 insertions, 1 deletions
diff --git a/cgit.c b/cgit.c
index ae20257..513ea12 100644
--- a/cgit.c
+++ b/cgit.c
@@ -1,129 +1,131 @@
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 config_cb(const char *name, const char *value) 20void config_cb(const char *name, const char *value)
21{ 21{
22 if (!strcmp(name, "root-title")) 22 if (!strcmp(name, "root-title"))
23 ctx.cfg.root_title = xstrdup(value); 23 ctx.cfg.root_title = xstrdup(value);
24 else if (!strcmp(name, "root-desc")) 24 else if (!strcmp(name, "root-desc"))
25 ctx.cfg.root_desc = xstrdup(value); 25 ctx.cfg.root_desc = xstrdup(value);
26 else if (!strcmp(name, "root-readme")) 26 else if (!strcmp(name, "root-readme"))
27 ctx.cfg.root_readme = xstrdup(value); 27 ctx.cfg.root_readme = xstrdup(value);
28 else if (!strcmp(name, "css")) 28 else if (!strcmp(name, "css"))
29 ctx.cfg.css = xstrdup(value); 29 ctx.cfg.css = xstrdup(value);
30 else if (!strcmp(name, "favicon")) 30 else if (!strcmp(name, "favicon"))
31 ctx.cfg.favicon = xstrdup(value); 31 ctx.cfg.favicon = xstrdup(value);
32 else if (!strcmp(name, "footer")) 32 else if (!strcmp(name, "footer"))
33 ctx.cfg.footer = xstrdup(value); 33 ctx.cfg.footer = xstrdup(value);
34 else if (!strcmp(name, "head-include"))
35 ctx.cfg.head_include = xstrdup(value);
34 else if (!strcmp(name, "header")) 36 else if (!strcmp(name, "header"))
35 ctx.cfg.header = xstrdup(value); 37 ctx.cfg.header = xstrdup(value);
36 else if (!strcmp(name, "logo")) 38 else if (!strcmp(name, "logo"))
37 ctx.cfg.logo = xstrdup(value); 39 ctx.cfg.logo = xstrdup(value);
38 else if (!strcmp(name, "index-header")) 40 else if (!strcmp(name, "index-header"))
39 ctx.cfg.index_header = xstrdup(value); 41 ctx.cfg.index_header = xstrdup(value);
40 else if (!strcmp(name, "index-info")) 42 else if (!strcmp(name, "index-info"))
41 ctx.cfg.index_info = xstrdup(value); 43 ctx.cfg.index_info = xstrdup(value);
42 else if (!strcmp(name, "logo-link")) 44 else if (!strcmp(name, "logo-link"))
43 ctx.cfg.logo_link = xstrdup(value); 45 ctx.cfg.logo_link = xstrdup(value);
44 else if (!strcmp(name, "module-link")) 46 else if (!strcmp(name, "module-link"))
45 ctx.cfg.module_link = xstrdup(value); 47 ctx.cfg.module_link = xstrdup(value);
46 else if (!strcmp(name, "virtual-root")) { 48 else if (!strcmp(name, "virtual-root")) {
47 ctx.cfg.virtual_root = trim_end(value, '/'); 49 ctx.cfg.virtual_root = trim_end(value, '/');
48 if (!ctx.cfg.virtual_root && (!strcmp(value, "/"))) 50 if (!ctx.cfg.virtual_root && (!strcmp(value, "/")))
49 ctx.cfg.virtual_root = ""; 51 ctx.cfg.virtual_root = "";
50 } else if (!strcmp(name, "nocache")) 52 } else if (!strcmp(name, "nocache"))
51 ctx.cfg.nocache = atoi(value); 53 ctx.cfg.nocache = atoi(value);
52 else if (!strcmp(name, "snapshots")) 54 else if (!strcmp(name, "snapshots"))
53 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); 55 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);
54 else if (!strcmp(name, "enable-index-links")) 56 else if (!strcmp(name, "enable-index-links"))
55 ctx.cfg.enable_index_links = atoi(value); 57 ctx.cfg.enable_index_links = atoi(value);
56 else if (!strcmp(name, "enable-log-filecount")) 58 else if (!strcmp(name, "enable-log-filecount"))
57 ctx.cfg.enable_log_filecount = atoi(value); 59 ctx.cfg.enable_log_filecount = atoi(value);
58 else if (!strcmp(name, "enable-log-linecount")) 60 else if (!strcmp(name, "enable-log-linecount"))
59 ctx.cfg.enable_log_linecount = atoi(value); 61 ctx.cfg.enable_log_linecount = atoi(value);
60 else if (!strcmp(name, "max-stats")) 62 else if (!strcmp(name, "max-stats"))
61 ctx.cfg.max_stats = cgit_find_stats_period(value, NULL); 63 ctx.cfg.max_stats = cgit_find_stats_period(value, NULL);
62 else if (!strcmp(name, "cache-size")) 64 else if (!strcmp(name, "cache-size"))
63 ctx.cfg.cache_size = atoi(value); 65 ctx.cfg.cache_size = atoi(value);
64 else if (!strcmp(name, "cache-root")) 66 else if (!strcmp(name, "cache-root"))
65 ctx.cfg.cache_root = xstrdup(value); 67 ctx.cfg.cache_root = xstrdup(value);
66 else if (!strcmp(name, "cache-root-ttl")) 68 else if (!strcmp(name, "cache-root-ttl"))
67 ctx.cfg.cache_root_ttl = atoi(value); 69 ctx.cfg.cache_root_ttl = atoi(value);
68 else if (!strcmp(name, "cache-repo-ttl")) 70 else if (!strcmp(name, "cache-repo-ttl"))
69 ctx.cfg.cache_repo_ttl = atoi(value); 71 ctx.cfg.cache_repo_ttl = atoi(value);
70 else if (!strcmp(name, "cache-static-ttl")) 72 else if (!strcmp(name, "cache-static-ttl"))
71 ctx.cfg.cache_static_ttl = atoi(value); 73 ctx.cfg.cache_static_ttl = atoi(value);
72 else if (!strcmp(name, "cache-dynamic-ttl")) 74 else if (!strcmp(name, "cache-dynamic-ttl"))
73 ctx.cfg.cache_dynamic_ttl = atoi(value); 75 ctx.cfg.cache_dynamic_ttl = atoi(value);
74 else if (!strcmp(name, "max-message-length")) 76 else if (!strcmp(name, "max-message-length"))
75 ctx.cfg.max_msg_len = atoi(value); 77 ctx.cfg.max_msg_len = atoi(value);
76 else if (!strcmp(name, "max-repodesc-length")) 78 else if (!strcmp(name, "max-repodesc-length"))
77 ctx.cfg.max_repodesc_len = atoi(value); 79 ctx.cfg.max_repodesc_len = atoi(value);
78 else if (!strcmp(name, "max-repo-count")) 80 else if (!strcmp(name, "max-repo-count"))
79 ctx.cfg.max_repo_count = atoi(value); 81 ctx.cfg.max_repo_count = atoi(value);
80 else if (!strcmp(name, "max-commit-count")) 82 else if (!strcmp(name, "max-commit-count"))
81 ctx.cfg.max_commit_count = atoi(value); 83 ctx.cfg.max_commit_count = atoi(value);
82 else if (!strcmp(name, "summary-log")) 84 else if (!strcmp(name, "summary-log"))
83 ctx.cfg.summary_log = atoi(value); 85 ctx.cfg.summary_log = atoi(value);
84 else if (!strcmp(name, "summary-branches")) 86 else if (!strcmp(name, "summary-branches"))
85 ctx.cfg.summary_branches = atoi(value); 87 ctx.cfg.summary_branches = atoi(value);
86 else if (!strcmp(name, "summary-tags")) 88 else if (!strcmp(name, "summary-tags"))
87 ctx.cfg.summary_tags = atoi(value); 89 ctx.cfg.summary_tags = atoi(value);
88 else if (!strcmp(name, "agefile")) 90 else if (!strcmp(name, "agefile"))
89 ctx.cfg.agefile = xstrdup(value); 91 ctx.cfg.agefile = xstrdup(value);
90 else if (!strcmp(name, "renamelimit")) 92 else if (!strcmp(name, "renamelimit"))
91 ctx.cfg.renamelimit = atoi(value); 93 ctx.cfg.renamelimit = atoi(value);
92 else if (!strcmp(name, "robots")) 94 else if (!strcmp(name, "robots"))
93 ctx.cfg.robots = xstrdup(value); 95 ctx.cfg.robots = xstrdup(value);
94 else if (!strcmp(name, "clone-prefix")) 96 else if (!strcmp(name, "clone-prefix"))
95 ctx.cfg.clone_prefix = xstrdup(value); 97 ctx.cfg.clone_prefix = xstrdup(value);
96 else if (!strcmp(name, "local-time")) 98 else if (!strcmp(name, "local-time"))
97 ctx.cfg.local_time = atoi(value); 99 ctx.cfg.local_time = atoi(value);
98 else if (!strcmp(name, "repo.group")) 100 else if (!strcmp(name, "repo.group"))
99 ctx.cfg.repo_group = xstrdup(value); 101 ctx.cfg.repo_group = xstrdup(value);
100 else if (!strcmp(name, "repo.url")) 102 else if (!strcmp(name, "repo.url"))
101 ctx.repo = cgit_add_repo(value); 103 ctx.repo = cgit_add_repo(value);
102 else if (!strcmp(name, "repo.name")) 104 else if (!strcmp(name, "repo.name"))
103 ctx.repo->name = xstrdup(value); 105 ctx.repo->name = xstrdup(value);
104 else if (ctx.repo && !strcmp(name, "repo.path")) 106 else if (ctx.repo && !strcmp(name, "repo.path"))
105 ctx.repo->path = trim_end(value, '/'); 107 ctx.repo->path = trim_end(value, '/');
106 else if (ctx.repo && !strcmp(name, "repo.clone-url")) 108 else if (ctx.repo && !strcmp(name, "repo.clone-url"))
107 ctx.repo->clone_url = xstrdup(value); 109 ctx.repo->clone_url = xstrdup(value);
108 else if (ctx.repo && !strcmp(name, "repo.desc")) 110 else if (ctx.repo && !strcmp(name, "repo.desc"))
109 ctx.repo->desc = xstrdup(value); 111 ctx.repo->desc = xstrdup(value);
110 else if (ctx.repo && !strcmp(name, "repo.owner")) 112 else if (ctx.repo && !strcmp(name, "repo.owner"))
111 ctx.repo->owner = xstrdup(value); 113 ctx.repo->owner = xstrdup(value);
112 else if (ctx.repo && !strcmp(name, "repo.defbranch")) 114 else if (ctx.repo && !strcmp(name, "repo.defbranch"))
113 ctx.repo->defbranch = xstrdup(value); 115 ctx.repo->defbranch = xstrdup(value);
114 else if (ctx.repo && !strcmp(name, "repo.snapshots")) 116 else if (ctx.repo && !strcmp(name, "repo.snapshots"))
115 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */ 117 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */
116 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount")) 118 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount"))
117 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value); 119 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value);
118 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount")) 120 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount"))
119 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); 121 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value);
120 else if (ctx.repo && !strcmp(name, "repo.max-stats")) 122 else if (ctx.repo && !strcmp(name, "repo.max-stats"))
121 ctx.repo->max_stats = cgit_find_stats_period(value, NULL); 123 ctx.repo->max_stats = cgit_find_stats_period(value, NULL);
122 else if (ctx.repo && !strcmp(name, "repo.module-link")) 124 else if (ctx.repo && !strcmp(name, "repo.module-link"))
123 ctx.repo->module_link= xstrdup(value); 125 ctx.repo->module_link= xstrdup(value);
124 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) { 126 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) {
125 if (*value == '/') 127 if (*value == '/')
126 ctx.repo->readme = xstrdup(value); 128 ctx.repo->readme = xstrdup(value);
127 else 129 else
128 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value)); 130 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value));
129 } else if (!strcmp(name, "include")) 131 } else if (!strcmp(name, "include"))
diff --git a/cgit.h b/cgit.h
index 07a277a..78b30ba 100644
--- a/cgit.h
+++ b/cgit.h
@@ -43,192 +43,193 @@
43 * Default encoding 43 * Default encoding
44 */ 44 */
45#define PAGE_ENCODING "UTF-8" 45#define PAGE_ENCODING "UTF-8"
46 46
47typedef void (*configfn)(const char *name, const char *value); 47typedef void (*configfn)(const char *name, const char *value);
48typedef void (*filepair_fn)(struct diff_filepair *pair); 48typedef void (*filepair_fn)(struct diff_filepair *pair);
49typedef void (*linediff_fn)(char *line, int len); 49typedef void (*linediff_fn)(char *line, int len);
50 50
51struct cgit_repo { 51struct cgit_repo {
52 char *url; 52 char *url;
53 char *name; 53 char *name;
54 char *path; 54 char *path;
55 char *desc; 55 char *desc;
56 char *owner; 56 char *owner;
57 char *defbranch; 57 char *defbranch;
58 char *group; 58 char *group;
59 char *module_link; 59 char *module_link;
60 char *readme; 60 char *readme;
61 char *clone_url; 61 char *clone_url;
62 int snapshots; 62 int snapshots;
63 int enable_log_filecount; 63 int enable_log_filecount;
64 int enable_log_linecount; 64 int enable_log_linecount;
65 int max_stats; 65 int max_stats;
66 time_t mtime; 66 time_t mtime;
67}; 67};
68 68
69struct cgit_repolist { 69struct cgit_repolist {
70 int length; 70 int length;
71 int count; 71 int count;
72 struct cgit_repo *repos; 72 struct cgit_repo *repos;
73}; 73};
74 74
75struct commitinfo { 75struct commitinfo {
76 struct commit *commit; 76 struct commit *commit;
77 char *author; 77 char *author;
78 char *author_email; 78 char *author_email;
79 unsigned long author_date; 79 unsigned long author_date;
80 char *committer; 80 char *committer;
81 char *committer_email; 81 char *committer_email;
82 unsigned long committer_date; 82 unsigned long committer_date;
83 char *subject; 83 char *subject;
84 char *msg; 84 char *msg;
85 char *msg_encoding; 85 char *msg_encoding;
86}; 86};
87 87
88struct taginfo { 88struct taginfo {
89 char *tagger; 89 char *tagger;
90 char *tagger_email; 90 char *tagger_email;
91 unsigned long tagger_date; 91 unsigned long tagger_date;
92 char *msg; 92 char *msg;
93}; 93};
94 94
95struct refinfo { 95struct refinfo {
96 const char *refname; 96 const char *refname;
97 struct object *object; 97 struct object *object;
98 union { 98 union {
99 struct taginfo *tag; 99 struct taginfo *tag;
100 struct commitinfo *commit; 100 struct commitinfo *commit;
101 }; 101 };
102}; 102};
103 103
104struct reflist { 104struct reflist {
105 struct refinfo **refs; 105 struct refinfo **refs;
106 int alloc; 106 int alloc;
107 int count; 107 int count;
108}; 108};
109 109
110struct cgit_query { 110struct cgit_query {
111 int has_symref; 111 int has_symref;
112 int has_sha1; 112 int has_sha1;
113 char *raw; 113 char *raw;
114 char *repo; 114 char *repo;
115 char *page; 115 char *page;
116 char *search; 116 char *search;
117 char *grep; 117 char *grep;
118 char *head; 118 char *head;
119 char *sha1; 119 char *sha1;
120 char *sha2; 120 char *sha2;
121 char *path; 121 char *path;
122 char *name; 122 char *name;
123 char *mimetype; 123 char *mimetype;
124 char *url; 124 char *url;
125 char *period; 125 char *period;
126 int ofs; 126 int ofs;
127 int nohead; 127 int nohead;
128 char *sort; 128 char *sort;
129 int showmsg; 129 int showmsg;
130}; 130};
131 131
132struct cgit_config { 132struct cgit_config {
133 char *agefile; 133 char *agefile;
134 char *cache_root; 134 char *cache_root;
135 char *clone_prefix; 135 char *clone_prefix;
136 char *css; 136 char *css;
137 char *favicon; 137 char *favicon;
138 char *footer; 138 char *footer;
139 char *head_include;
139 char *header; 140 char *header;
140 char *index_header; 141 char *index_header;
141 char *index_info; 142 char *index_info;
142 char *logo; 143 char *logo;
143 char *logo_link; 144 char *logo_link;
144 char *module_link; 145 char *module_link;
145 char *repo_group; 146 char *repo_group;
146 char *robots; 147 char *robots;
147 char *root_title; 148 char *root_title;
148 char *root_desc; 149 char *root_desc;
149 char *root_readme; 150 char *root_readme;
150 char *script_name; 151 char *script_name;
151 char *virtual_root; 152 char *virtual_root;
152 int cache_size; 153 int cache_size;
153 int cache_dynamic_ttl; 154 int cache_dynamic_ttl;
154 int cache_max_create_time; 155 int cache_max_create_time;
155 int cache_repo_ttl; 156 int cache_repo_ttl;
156 int cache_root_ttl; 157 int cache_root_ttl;
157 int cache_static_ttl; 158 int cache_static_ttl;
158 int enable_index_links; 159 int enable_index_links;
159 int enable_log_filecount; 160 int enable_log_filecount;
160 int enable_log_linecount; 161 int enable_log_linecount;
161 int local_time; 162 int local_time;
162 int max_repo_count; 163 int max_repo_count;
163 int max_commit_count; 164 int max_commit_count;
164 int max_lock_attempts; 165 int max_lock_attempts;
165 int max_msg_len; 166 int max_msg_len;
166 int max_repodesc_len; 167 int max_repodesc_len;
167 int max_stats; 168 int max_stats;
168 int nocache; 169 int nocache;
169 int renamelimit; 170 int renamelimit;
170 int snapshots; 171 int snapshots;
171 int summary_branches; 172 int summary_branches;
172 int summary_log; 173 int summary_log;
173 int summary_tags; 174 int summary_tags;
174}; 175};
175 176
176struct cgit_page { 177struct cgit_page {
177 time_t modified; 178 time_t modified;
178 time_t expires; 179 time_t expires;
179 size_t size; 180 size_t size;
180 char *mimetype; 181 char *mimetype;
181 char *charset; 182 char *charset;
182 char *filename; 183 char *filename;
183 char *etag; 184 char *etag;
184 char *title; 185 char *title;
185 int status; 186 int status;
186 char *statusmsg; 187 char *statusmsg;
187}; 188};
188 189
189struct cgit_context { 190struct cgit_context {
190 struct cgit_query qry; 191 struct cgit_query qry;
191 struct cgit_config cfg; 192 struct cgit_config cfg;
192 struct cgit_repo *repo; 193 struct cgit_repo *repo;
193 struct cgit_page page; 194 struct cgit_page page;
194}; 195};
195 196
196struct cgit_snapshot_format { 197struct cgit_snapshot_format {
197 const char *suffix; 198 const char *suffix;
198 const char *mimetype; 199 const char *mimetype;
199 write_archive_fn_t write_func; 200 write_archive_fn_t write_func;
200 int bit; 201 int bit;
201}; 202};
202 203
203extern const char *cgit_version; 204extern const char *cgit_version;
204 205
205extern struct cgit_repolist cgit_repolist; 206extern struct cgit_repolist cgit_repolist;
206extern struct cgit_context ctx; 207extern struct cgit_context ctx;
207extern const struct cgit_snapshot_format cgit_snapshot_formats[]; 208extern const struct cgit_snapshot_format cgit_snapshot_formats[];
208 209
209extern struct cgit_repo *cgit_add_repo(const char *url); 210extern struct cgit_repo *cgit_add_repo(const char *url);
210extern struct cgit_repo *cgit_get_repoinfo(const char *url); 211extern struct cgit_repo *cgit_get_repoinfo(const char *url);
211extern void cgit_repo_config_cb(const char *name, const char *value); 212extern void cgit_repo_config_cb(const char *name, const char *value);
212 213
213extern int chk_zero(int result, char *msg); 214extern int chk_zero(int result, char *msg);
214extern int chk_positive(int result, char *msg); 215extern int chk_positive(int result, char *msg);
215extern int chk_non_negative(int result, char *msg); 216extern int chk_non_negative(int result, char *msg);
216 217
217extern char *trim_end(const char *str, char c); 218extern char *trim_end(const char *str, char c);
218extern char *strlpart(char *txt, int maxlen); 219extern char *strlpart(char *txt, int maxlen);
219extern char *strrpart(char *txt, int maxlen); 220extern char *strrpart(char *txt, int maxlen);
220 221
221extern void cgit_add_ref(struct reflist *list, struct refinfo *ref); 222extern void cgit_add_ref(struct reflist *list, struct refinfo *ref);
222extern int cgit_refs_cb(const char *refname, const unsigned char *sha1, 223extern int cgit_refs_cb(const char *refname, const unsigned char *sha1,
223 int flags, void *cb_data); 224 int flags, void *cb_data);
224 225
225extern void *cgit_free_commitinfo(struct commitinfo *info); 226extern void *cgit_free_commitinfo(struct commitinfo *info);
226 227
227extern int cgit_diff_files(const unsigned char *old_sha1, 228extern int cgit_diff_files(const unsigned char *old_sha1,
228 const unsigned char *new_sha1, 229 const unsigned char *new_sha1,
229 unsigned long *old_size, unsigned long *new_size, 230 unsigned long *old_size, unsigned long *new_size,
230 int *binary, linediff_fn fn); 231 int *binary, linediff_fn fn);
231 232
232extern void cgit_diff_tree(const unsigned char *old_sha1, 233extern void cgit_diff_tree(const unsigned char *old_sha1,
233 const unsigned char *new_sha1, 234 const unsigned char *new_sha1,
234 filepair_fn fn, const char *prefix); 235 filepair_fn fn, const char *prefix);
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 7879f75..683f3b5 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -1,182 +1,186 @@
1CGITRC(5) 1CGITRC(5)
2======== 2========
3 3
4 4
5NAME 5NAME
6---- 6----
7cgitrc - runtime configuration for cgit 7cgitrc - runtime configuration for cgit
8 8
9 9
10SYNOPSIS 10SYNOPSIS
11-------- 11--------
12Cgitrc contains all runtime settings for cgit, including the list of git 12Cgitrc contains all runtime settings for cgit, including the list of git
13repositories, formatted as a line-separated list of NAME=VALUE pairs. Blank 13repositories, formatted as a line-separated list of NAME=VALUE pairs. Blank
14lines, and lines starting with '#', are ignored. 14lines, and lines starting with '#', are ignored.
15 15
16 16
17GLOBAL SETTINGS 17GLOBAL SETTINGS
18--------------- 18---------------
19agefile:: 19agefile::
20 Specifies a path, relative to each repository path, which can be used 20 Specifies a path, relative to each repository path, which can be used
21 to specify the date and time of the youngest commit in the repository. 21 to specify the date and time of the youngest commit in the repository.
22 The first line in the file is used as input to the "parse_date" 22 The first line in the file is used as input to the "parse_date"
23 function in libgit. Recommended timestamp-format is "yyyy-mm-dd 23 function in libgit. Recommended timestamp-format is "yyyy-mm-dd
24 hh:mm:ss". Default value: "info/web/last-modified". 24 hh:mm:ss". Default value: "info/web/last-modified".
25 25
26cache-root:: 26cache-root::
27 Path used to store the cgit cache entries. Default value: 27 Path used to store the cgit cache entries. Default value:
28 "/var/cache/cgit". 28 "/var/cache/cgit".
29 29
30cache-dynamic-ttl:: 30cache-dynamic-ttl::
31 Number which specifies the time-to-live, in minutes, for the cached 31 Number which specifies the time-to-live, in minutes, for the cached
32 version of repository pages accessed without a fixed SHA1. Default 32 version of repository pages accessed without a fixed SHA1. Default
33 value: "5". 33 value: "5".
34 34
35cache-repo-ttl:: 35cache-repo-ttl::
36 Number which specifies the time-to-live, in minutes, for the cached 36 Number which specifies the time-to-live, in minutes, for the cached
37 version of the repository summary page. Default value: "5". 37 version of the repository summary page. Default value: "5".
38 38
39cache-root-ttl:: 39cache-root-ttl::
40 Number which specifies the time-to-live, in minutes, for the cached 40 Number which specifies the time-to-live, in minutes, for the cached
41 version of the repository index page. Default value: "5". 41 version of the repository index page. Default value: "5".
42 42
43cache-size:: 43cache-size::
44 The maximum number of entries in the cgit cache. Default value: "0" 44 The maximum number of entries in the cgit cache. Default value: "0"
45 (i.e. caching is disabled). 45 (i.e. caching is disabled).
46 46
47cache-static-ttl:: 47cache-static-ttl::
48 Number which specifies the time-to-live, in minutes, for the cached 48 Number which specifies the time-to-live, in minutes, for the cached
49 version of repository pages accessed with a fixed SHA1. Default value: 49 version of repository pages accessed with a fixed SHA1. Default value:
50 "5". 50 "5".
51 51
52clone-prefix:: 52clone-prefix::
53 Space-separated list of common prefixes which, when combined with a 53 Space-separated list of common prefixes which, when combined with a
54 repository url, generates valid clone urls for the repository. This 54 repository url, generates valid clone urls for the repository. This
55 setting is only used if `repo.clone-url` is unspecified. Default value: 55 setting is only used if `repo.clone-url` is unspecified. Default value:
56 none. 56 none.
57 57
58css:: 58css::
59 Url which specifies the css document to include in all cgit pages. 59 Url which specifies the css document to include in all cgit pages.
60 Default value: "/cgit.css". 60 Default value: "/cgit.css".
61 61
62enable-index-links:: 62enable-index-links::
63 Flag which, when set to "1", will make cgit generate extra links for 63 Flag which, when set to "1", will make cgit generate extra links for
64 each repo in the repository index (specifically, to the "summary", 64 each repo in the repository index (specifically, to the "summary",
65 "commit" and "tree" pages). Default value: "0". 65 "commit" and "tree" pages). Default value: "0".
66 66
67enable-log-filecount:: 67enable-log-filecount::
68 Flag which, when set to "1", will make cgit print the number of 68 Flag which, when set to "1", will make cgit print the number of
69 modified files for each commit on the repository log page. Default 69 modified files for each commit on the repository log page. Default
70 value: "0". 70 value: "0".
71 71
72enable-log-linecount:: 72enable-log-linecount::
73 Flag which, when set to "1", will make cgit print the number of added 73 Flag which, when set to "1", will make cgit print the number of added
74 and removed lines for each commit on the repository log page. Default 74 and removed lines for each commit on the repository log page. Default
75 value: "0". 75 value: "0".
76 76
77favicon:: 77favicon::
78 Url used as link to a shortcut icon for cgit. If specified, it is 78 Url used as link to a shortcut icon for cgit. If specified, it is
79 suggested to use the value "/favicon.ico" since certain browsers will 79 suggested to use the value "/favicon.ico" since certain browsers will
80 ignore other values. Default value: none. 80 ignore other values. Default value: none.
81 81
82footer:: 82footer::
83 The content of the file specified with this option will be included 83 The content of the file specified with this option will be included
84 verbatim at the bottom of all pages (i.e. it replaces the standard 84 verbatim at the bottom of all pages (i.e. it replaces the standard
85 "generated by..." message. Default value: none. 85 "generated by..." message. Default value: none.
86 86
87head-include::
88 The content of the file specified with this option will be included
89 verbatim in the html HEAD section on all pages. Default value: none.
90
87header:: 91header::
88 The content of the file specified with this option will be included 92 The content of the file specified with this option will be included
89 verbatim at the top of all pages. Default value: none. 93 verbatim at the top of all pages. Default value: none.
90 94
91include:: 95include::
92 Name of a configfile to include before the rest of the current config- 96 Name of a configfile to include before the rest of the current config-
93 file is parsed. Default value: none. 97 file is parsed. Default value: none.
94 98
95index-header:: 99index-header::
96 The content of the file specified with this option will be included 100 The content of the file specified with this option will be included
97 verbatim above the repository index. This setting is deprecated, and 101 verbatim above the repository index. This setting is deprecated, and
98 will not be supported by cgit-1.0 (use root-readme instead). Default 102 will not be supported by cgit-1.0 (use root-readme instead). Default
99 value: none. 103 value: none.
100 104
101index-info:: 105index-info::
102 The content of the file specified with this option will be included 106 The content of the file specified with this option will be included
103 verbatim below the heading on the repository index page. This setting 107 verbatim below the heading on the repository index page. This setting
104 is deprecated, and will not be supported by cgit-1.0 (use root-desc 108 is deprecated, and will not be supported by cgit-1.0 (use root-desc
105 instead). Default value: none. 109 instead). Default value: none.
106 110
107local-time:: 111local-time::
108 Flag which, if set to "1", makes cgit print commit and tag times in the 112 Flag which, if set to "1", makes cgit print commit and tag times in the
109 servers timezone. Default value: "0". 113 servers timezone. Default value: "0".
110 114
111logo:: 115logo::
112 Url which specifies the source of an image which will be used as a logo 116 Url which specifies the source of an image which will be used as a logo
113 on all cgit pages. 117 on all cgit pages.
114 118
115logo-link:: 119logo-link::
116 Url loaded when clicking on the cgit logo image. If unspecified the 120 Url loaded when clicking on the cgit logo image. If unspecified the
117 calculated url of the repository index page will be used. Default 121 calculated url of the repository index page will be used. Default
118 value: none. 122 value: none.
119 123
120max-commit-count:: 124max-commit-count::
121 Specifies the number of entries to list per page in "log" view. Default 125 Specifies the number of entries to list per page in "log" view. Default
122 value: "50". 126 value: "50".
123 127
124max-message-length:: 128max-message-length::
125 Specifies the maximum number of commit message characters to display in 129 Specifies the maximum number of commit message characters to display in
126 "log" view. Default value: "80". 130 "log" view. Default value: "80".
127 131
128max-repo-count:: 132max-repo-count::
129 Specifies the number of entries to list per page on therepository 133 Specifies the number of entries to list per page on therepository
130 index page. Default value: "50". 134 index page. Default value: "50".
131 135
132max-repodesc-length:: 136max-repodesc-length::
133 Specifies the maximum number of repo description characters to display 137 Specifies the maximum number of repo description characters to display
134 on the repository index page. Default value: "80". 138 on the repository index page. Default value: "80".
135 139
136max-stats:: 140max-stats::
137 Set the default maximum statistics period. Valid values are "week", 141 Set the default maximum statistics period. Valid values are "week",
138 "month", "quarter" and "year". If unspecified, statistics are 142 "month", "quarter" and "year". If unspecified, statistics are
139 disabled. Default value: none. See also: "repo.max-stats". 143 disabled. Default value: none. See also: "repo.max-stats".
140 144
141module-link:: 145module-link::
142 Text which will be used as the formatstring for a hyperlink when a 146 Text which will be used as the formatstring for a hyperlink when a
143 submodule is printed in a directory listing. The arguments for the 147 submodule is printed in a directory listing. The arguments for the
144 formatstring are the path and SHA1 of the submodule commit. Default 148 formatstring are the path and SHA1 of the submodule commit. Default
145 value: "./?repo=%s&page=commit&id=%s" 149 value: "./?repo=%s&page=commit&id=%s"
146 150
147nocache:: 151nocache::
148 If set to the value "1" caching will be disabled. This settings is 152 If set to the value "1" caching will be disabled. This settings is
149 deprecated, and will not be honored starting with cgit-1.0. Default 153 deprecated, and will not be honored starting with cgit-1.0. Default
150 value: "0". 154 value: "0".
151 155
152renamelimit:: 156renamelimit::
153 Maximum number of files to consider when detecting renames. The value 157 Maximum number of files to consider when detecting renames. The value
154 "-1" uses the compiletime value in git (for further info, look at 158 "-1" uses the compiletime value in git (for further info, look at
155 `man git-diff`). Default value: "-1". 159 `man git-diff`). Default value: "-1".
156 160
157repo.group:: 161repo.group::
158 A value for the current repository group, which all repositories 162 A value for the current repository group, which all repositories
159 specified after this setting will inherit. Default value: none. 163 specified after this setting will inherit. Default value: none.
160 164
161robots:: 165robots::
162 Text used as content for the "robots" meta-tag. Default value: 166 Text used as content for the "robots" meta-tag. Default value:
163 "index, nofollow". 167 "index, nofollow".
164 168
165root-desc:: 169root-desc::
166 Text printed below the heading on the repository index page. Default 170 Text printed below the heading on the repository index page. Default
167 value: "a fast webinterface for the git dscm". 171 value: "a fast webinterface for the git dscm".
168 172
169root-readme:: 173root-readme::
170 The content of the file specified with this option will be included 174 The content of the file specified with this option will be included
171 verbatim below the "about" link on the repository index page. Default 175 verbatim below the "about" link on the repository index page. Default
172 value: none. 176 value: none.
173 177
174root-title:: 178root-title::
175 Text printed as heading on the repository index page. Default value: 179 Text printed as heading on the repository index page. Default value:
176 "Git Repository Browser". 180 "Git Repository Browser".
177 181
178snapshots:: 182snapshots::
179 Text which specifies the default (and allowed) set of snapshot formats 183 Text which specifies the default (and allowed) set of snapshot formats
180 supported by cgit. The value is a space-separated list of zero or more 184 supported by cgit. The value is a space-separated list of zero or more
181 of the following values: 185 of the following values:
182 "tar" uncompressed tar-file 186 "tar" uncompressed tar-file
diff --git a/ui-shared.c b/ui-shared.c
index 10be3c0..66d5b82 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -423,194 +423,196 @@ void cgit_print_date(time_t secs, char *format, int local_time)
423} 423}
424 424
425void cgit_print_age(time_t t, time_t max_relative, char *format) 425void cgit_print_age(time_t t, time_t max_relative, char *format)
426{ 426{
427 time_t now, secs; 427 time_t now, secs;
428 428
429 if (!t) 429 if (!t)
430 return; 430 return;
431 time(&now); 431 time(&now);
432 secs = now - t; 432 secs = now - t;
433 433
434 if (secs > max_relative && max_relative >= 0) { 434 if (secs > max_relative && max_relative >= 0) {
435 cgit_print_date(t, format, ctx.cfg.local_time); 435 cgit_print_date(t, format, ctx.cfg.local_time);
436 return; 436 return;
437 } 437 }
438 438
439 if (secs < TM_HOUR * 2) { 439 if (secs < TM_HOUR * 2) {
440 htmlf("<span class='age-mins'>%.0f min.</span>", 440 htmlf("<span class='age-mins'>%.0f min.</span>",
441 secs * 1.0 / TM_MIN); 441 secs * 1.0 / TM_MIN);
442 return; 442 return;
443 } 443 }
444 if (secs < TM_DAY * 2) { 444 if (secs < TM_DAY * 2) {
445 htmlf("<span class='age-hours'>%.0f hours</span>", 445 htmlf("<span class='age-hours'>%.0f hours</span>",
446 secs * 1.0 / TM_HOUR); 446 secs * 1.0 / TM_HOUR);
447 return; 447 return;
448 } 448 }
449 if (secs < TM_WEEK * 2) { 449 if (secs < TM_WEEK * 2) {
450 htmlf("<span class='age-days'>%.0f days</span>", 450 htmlf("<span class='age-days'>%.0f days</span>",
451 secs * 1.0 / TM_DAY); 451 secs * 1.0 / TM_DAY);
452 return; 452 return;
453 } 453 }
454 if (secs < TM_MONTH * 2) { 454 if (secs < TM_MONTH * 2) {
455 htmlf("<span class='age-weeks'>%.0f weeks</span>", 455 htmlf("<span class='age-weeks'>%.0f weeks</span>",
456 secs * 1.0 / TM_WEEK); 456 secs * 1.0 / TM_WEEK);
457 return; 457 return;
458 } 458 }
459 if (secs < TM_YEAR * 2) { 459 if (secs < TM_YEAR * 2) {
460 htmlf("<span class='age-months'>%.0f months</span>", 460 htmlf("<span class='age-months'>%.0f months</span>",
461 secs * 1.0 / TM_MONTH); 461 secs * 1.0 / TM_MONTH);
462 return; 462 return;
463 } 463 }
464 htmlf("<span class='age-years'>%.0f years</span>", 464 htmlf("<span class='age-years'>%.0f years</span>",
465 secs * 1.0 / TM_YEAR); 465 secs * 1.0 / TM_YEAR);
466} 466}
467 467
468void cgit_print_http_headers(struct cgit_context *ctx) 468void cgit_print_http_headers(struct cgit_context *ctx)
469{ 469{
470 const char *method = getenv("REQUEST_METHOD"); 470 const char *method = getenv("REQUEST_METHOD");
471 471
472 if (ctx->page.status) 472 if (ctx->page.status)
473 htmlf("Status: %d %s\n", ctx->page.status, ctx->page.statusmsg); 473 htmlf("Status: %d %s\n", ctx->page.status, ctx->page.statusmsg);
474 if (ctx->page.mimetype && ctx->page.charset) 474 if (ctx->page.mimetype && ctx->page.charset)
475 htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype, 475 htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype,
476 ctx->page.charset); 476 ctx->page.charset);
477 else if (ctx->page.mimetype) 477 else if (ctx->page.mimetype)
478 htmlf("Content-Type: %s\n", ctx->page.mimetype); 478 htmlf("Content-Type: %s\n", ctx->page.mimetype);
479 if (ctx->page.size) 479 if (ctx->page.size)
480 htmlf("Content-Length: %ld\n", ctx->page.size); 480 htmlf("Content-Length: %ld\n", ctx->page.size);
481 if (ctx->page.filename) 481 if (ctx->page.filename)
482 htmlf("Content-Disposition: inline; filename=\"%s\"\n", 482 htmlf("Content-Disposition: inline; filename=\"%s\"\n",
483 ctx->page.filename); 483 ctx->page.filename);
484 htmlf("Last-Modified: %s\n", http_date(ctx->page.modified)); 484 htmlf("Last-Modified: %s\n", http_date(ctx->page.modified));
485 htmlf("Expires: %s\n", http_date(ctx->page.expires)); 485 htmlf("Expires: %s\n", http_date(ctx->page.expires));
486 if (ctx->page.etag) 486 if (ctx->page.etag)
487 htmlf("ETag: \"%s\"\n", ctx->page.etag); 487 htmlf("ETag: \"%s\"\n", ctx->page.etag);
488 html("\n"); 488 html("\n");
489 if (method && !strcmp(method, "HEAD")) 489 if (method && !strcmp(method, "HEAD"))
490 exit(0); 490 exit(0);
491} 491}
492 492
493void cgit_print_docstart(struct cgit_context *ctx) 493void cgit_print_docstart(struct cgit_context *ctx)
494{ 494{
495 char *host = cgit_hosturl(); 495 char *host = cgit_hosturl();
496 html(cgit_doctype); 496 html(cgit_doctype);
497 html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"); 497 html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n");
498 html("<head>\n"); 498 html("<head>\n");
499 html("<title>"); 499 html("<title>");
500 html_txt(ctx->page.title); 500 html_txt(ctx->page.title);
501 html("</title>\n"); 501 html("</title>\n");
502 htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version); 502 htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version);
503 if (ctx->cfg.robots && *ctx->cfg.robots) 503 if (ctx->cfg.robots && *ctx->cfg.robots)
504 htmlf("<meta name='robots' content='%s'/>\n", ctx->cfg.robots); 504 htmlf("<meta name='robots' content='%s'/>\n", ctx->cfg.robots);
505 html("<link rel='stylesheet' type='text/css' href='"); 505 html("<link rel='stylesheet' type='text/css' href='");
506 html_attr(ctx->cfg.css); 506 html_attr(ctx->cfg.css);
507 html("'/>\n"); 507 html("'/>\n");
508 if (ctx->cfg.favicon) { 508 if (ctx->cfg.favicon) {
509 html("<link rel='shortcut icon' href='"); 509 html("<link rel='shortcut icon' href='");
510 html_attr(ctx->cfg.favicon); 510 html_attr(ctx->cfg.favicon);
511 html("'/>\n"); 511 html("'/>\n");
512 } 512 }
513 if (host && ctx->repo) { 513 if (host && ctx->repo) {
514 html("<link rel='alternate' title='Atom feed' href='"); 514 html("<link rel='alternate' title='Atom feed' href='");
515 html(cgit_httpscheme()); 515 html(cgit_httpscheme());
516 html_attr(cgit_hosturl()); 516 html_attr(cgit_hosturl());
517 html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path, 517 html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path,
518 fmt("h=%s", ctx->qry.head))); 518 fmt("h=%s", ctx->qry.head)));
519 html("' type='application/atom+xml'/>"); 519 html("' type='application/atom+xml'/>\n");
520 } 520 }
521 if (ctx->cfg.head_include)
522 html_include(ctx->cfg.head_include);
521 html("</head>\n"); 523 html("</head>\n");
522 html("<body>\n"); 524 html("<body>\n");
523 if (ctx->cfg.header) 525 if (ctx->cfg.header)
524 html_include(ctx->cfg.header); 526 html_include(ctx->cfg.header);
525} 527}
526 528
527void cgit_print_docend() 529void cgit_print_docend()
528{ 530{
529 html("</div>"); 531 html("</div>");
530 if (ctx.cfg.footer) 532 if (ctx.cfg.footer)
531 html_include(ctx.cfg.footer); 533 html_include(ctx.cfg.footer);
532 else { 534 else {
533 htmlf("<div class='footer'>generated by cgit %s at ", 535 htmlf("<div class='footer'>generated by cgit %s at ",
534 cgit_version); 536 cgit_version);
535 cgit_print_date(time(NULL), FMT_LONGDATE, ctx.cfg.local_time); 537 cgit_print_date(time(NULL), FMT_LONGDATE, ctx.cfg.local_time);
536 html("</div>\n"); 538 html("</div>\n");
537 } 539 }
538 html("</body>\n</html>\n"); 540 html("</body>\n</html>\n");
539} 541}
540 542
541int print_branch_option(const char *refname, const unsigned char *sha1, 543int print_branch_option(const char *refname, const unsigned char *sha1,
542 int flags, void *cb_data) 544 int flags, void *cb_data)
543{ 545{
544 char *name = (char *)refname; 546 char *name = (char *)refname;
545 html_option(name, name, ctx.qry.head); 547 html_option(name, name, ctx.qry.head);
546 return 0; 548 return 0;
547} 549}
548 550
549int print_archive_ref(const char *refname, const unsigned char *sha1, 551int print_archive_ref(const char *refname, const unsigned char *sha1,
550 int flags, void *cb_data) 552 int flags, void *cb_data)
551{ 553{
552 struct tag *tag; 554 struct tag *tag;
553 struct taginfo *info; 555 struct taginfo *info;
554 struct object *obj; 556 struct object *obj;
555 char buf[256], *url; 557 char buf[256], *url;
556 unsigned char fileid[20]; 558 unsigned char fileid[20];
557 int *header = (int *)cb_data; 559 int *header = (int *)cb_data;
558 560
559 if (prefixcmp(refname, "refs/archives")) 561 if (prefixcmp(refname, "refs/archives"))
560 return 0; 562 return 0;
561 strncpy(buf, refname+14, sizeof(buf)); 563 strncpy(buf, refname+14, sizeof(buf));
562 obj = parse_object(sha1); 564 obj = parse_object(sha1);
563 if (!obj) 565 if (!obj)
564 return 1; 566 return 1;
565 if (obj->type == OBJ_TAG) { 567 if (obj->type == OBJ_TAG) {
566 tag = lookup_tag(sha1); 568 tag = lookup_tag(sha1);
567 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) 569 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
568 return 0; 570 return 0;
569 hashcpy(fileid, tag->tagged->sha1); 571 hashcpy(fileid, tag->tagged->sha1);
570 } else if (obj->type != OBJ_BLOB) { 572 } else if (obj->type != OBJ_BLOB) {
571 return 0; 573 return 0;
572 } else { 574 } else {
573 hashcpy(fileid, sha1); 575 hashcpy(fileid, sha1);
574 } 576 }
575 if (!*header) { 577 if (!*header) {
576 html("<h1>download</h1>\n"); 578 html("<h1>download</h1>\n");
577 *header = 1; 579 *header = 1;
578 } 580 }
579 url = cgit_pageurl(ctx.qry.repo, "blob", 581 url = cgit_pageurl(ctx.qry.repo, "blob",
580 fmt("id=%s&amp;path=%s", sha1_to_hex(fileid), 582 fmt("id=%s&amp;path=%s", sha1_to_hex(fileid),
581 buf)); 583 buf));
582 html_link_open(url, NULL, "menu"); 584 html_link_open(url, NULL, "menu");
583 html_txt(strlpart(buf, 20)); 585 html_txt(strlpart(buf, 20));
584 html_link_close(); 586 html_link_close();
585 return 0; 587 return 0;
586} 588}
587 589
588void cgit_add_hidden_formfields(int incl_head, int incl_search, char *page) 590void cgit_add_hidden_formfields(int incl_head, int incl_search, char *page)
589{ 591{
590 char *url; 592 char *url;
591 593
592 if (!ctx.cfg.virtual_root) { 594 if (!ctx.cfg.virtual_root) {
593 url = fmt("%s/%s", ctx.qry.repo, page); 595 url = fmt("%s/%s", ctx.qry.repo, page);
594 if (ctx.qry.path) 596 if (ctx.qry.path)
595 url = fmt("%s/%s", url, ctx.qry.path); 597 url = fmt("%s/%s", url, ctx.qry.path);
596 html_hidden("url", url); 598 html_hidden("url", url);
597 } 599 }
598 600
599 if (incl_head && ctx.qry.head && ctx.repo->defbranch && 601 if (incl_head && ctx.qry.head && ctx.repo->defbranch &&
600 strcmp(ctx.qry.head, ctx.repo->defbranch)) 602 strcmp(ctx.qry.head, ctx.repo->defbranch))
601 html_hidden("h", ctx.qry.head); 603 html_hidden("h", ctx.qry.head);
602 604
603 if (ctx.qry.sha1) 605 if (ctx.qry.sha1)
604 html_hidden("id", ctx.qry.sha1); 606 html_hidden("id", ctx.qry.sha1);
605 if (ctx.qry.sha2) 607 if (ctx.qry.sha2)
606 html_hidden("id2", ctx.qry.sha2); 608 html_hidden("id2", ctx.qry.sha2);
607 if (ctx.qry.showmsg) 609 if (ctx.qry.showmsg)
608 html_hidden("showmsg", "1"); 610 html_hidden("showmsg", "1");
609 611
610 if (incl_search) { 612 if (incl_search) {
611 if (ctx.qry.grep) 613 if (ctx.qry.grep)
612 html_hidden("qt", ctx.qry.grep); 614 html_hidden("qt", ctx.qry.grep);
613 if (ctx.qry.search) 615 if (ctx.qry.search)
614 html_hidden("q", ctx.qry.search); 616 html_hidden("q", ctx.qry.search);
615 } 617 }
616} 618}