summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2009-08-23 20:58:39 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2009-08-24 08:22:58 (UTC)
commite7af002d5c405c82652f739d08ced3908d1f57e7 (patch) (unidiff)
tree1e31e5dd8d33ca4a8392c4d6207b2ff6bf8a0d76
parent50d5af3adcdd90424b70e9472af24356ed50aa9b (diff)
downloadcgit-e7af002d5c405c82652f739d08ced3908d1f57e7.zip
cgit-e7af002d5c405c82652f739d08ced3908d1f57e7.tar.gz
cgit-e7af002d5c405c82652f739d08ced3908d1f57e7.tar.bz2
Introduce 'section' as canonical spelling for 'repo.group'
The 'repo.' prefix should be reserved for repo-specific options, but the option 'repo.group' must still be honored to stay backwards compatible. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c4
-rw-r--r--cgit.css2
-rw-r--r--cgit.h4
-rw-r--r--cgitrc.5.txt9
-rw-r--r--shared.c2
-rw-r--r--ui-repolist.c18
6 files changed, 22 insertions, 17 deletions
diff --git a/cgit.c b/cgit.c
index a792fe4..013a0fe 100644
--- a/cgit.c
+++ b/cgit.c
@@ -82,130 +82,130 @@ void config_cb(const char *name, const char *value)
82 ctx.cfg.noheader = atoi(value); 82 ctx.cfg.noheader = atoi(value);
83 else if (!strcmp(name, "snapshots")) 83 else if (!strcmp(name, "snapshots"))
84 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); 84 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);
85 else if (!strcmp(name, "enable-index-links")) 85 else if (!strcmp(name, "enable-index-links"))
86 ctx.cfg.enable_index_links = atoi(value); 86 ctx.cfg.enable_index_links = atoi(value);
87 else if (!strcmp(name, "enable-log-filecount")) 87 else if (!strcmp(name, "enable-log-filecount"))
88 ctx.cfg.enable_log_filecount = atoi(value); 88 ctx.cfg.enable_log_filecount = atoi(value);
89 else if (!strcmp(name, "enable-log-linecount")) 89 else if (!strcmp(name, "enable-log-linecount"))
90 ctx.cfg.enable_log_linecount = atoi(value); 90 ctx.cfg.enable_log_linecount = 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-scanrc-ttl")) 101 else if (!strcmp(name, "cache-scanrc-ttl"))
102 ctx.cfg.cache_scanrc_ttl = atoi(value); 102 ctx.cfg.cache_scanrc_ttl = atoi(value);
103 else if (!strcmp(name, "cache-static-ttl")) 103 else if (!strcmp(name, "cache-static-ttl"))
104 ctx.cfg.cache_static_ttl = atoi(value); 104 ctx.cfg.cache_static_ttl = atoi(value);
105 else if (!strcmp(name, "cache-dynamic-ttl")) 105 else if (!strcmp(name, "cache-dynamic-ttl"))
106 ctx.cfg.cache_dynamic_ttl = atoi(value); 106 ctx.cfg.cache_dynamic_ttl = atoi(value);
107 else if (!strcmp(name, "about-filter")) 107 else if (!strcmp(name, "about-filter"))
108 ctx.cfg.about_filter = new_filter(value, 0); 108 ctx.cfg.about_filter = new_filter(value, 0);
109 else if (!strcmp(name, "commit-filter")) 109 else if (!strcmp(name, "commit-filter"))
110 ctx.cfg.commit_filter = new_filter(value, 0); 110 ctx.cfg.commit_filter = new_filter(value, 0);
111 else if (!strcmp(name, "embedded")) 111 else if (!strcmp(name, "embedded"))
112 ctx.cfg.embedded = atoi(value); 112 ctx.cfg.embedded = atoi(value);
113 else if (!strcmp(name, "max-message-length")) 113 else if (!strcmp(name, "max-message-length"))
114 ctx.cfg.max_msg_len = atoi(value); 114 ctx.cfg.max_msg_len = atoi(value);
115 else if (!strcmp(name, "max-repodesc-length")) 115 else if (!strcmp(name, "max-repodesc-length"))
116 ctx.cfg.max_repodesc_len = atoi(value); 116 ctx.cfg.max_repodesc_len = atoi(value);
117 else if (!strcmp(name, "max-repo-count")) 117 else if (!strcmp(name, "max-repo-count"))
118 ctx.cfg.max_repo_count = atoi(value); 118 ctx.cfg.max_repo_count = atoi(value);
119 else if (!strcmp(name, "max-commit-count")) 119 else if (!strcmp(name, "max-commit-count"))
120 ctx.cfg.max_commit_count = atoi(value); 120 ctx.cfg.max_commit_count = atoi(value);
121 else if (!strcmp(name, "scan-path")) 121 else if (!strcmp(name, "scan-path"))
122 if (!ctx.cfg.nocache && ctx.cfg.cache_size) 122 if (!ctx.cfg.nocache && ctx.cfg.cache_size)
123 process_cached_repolist(value); 123 process_cached_repolist(value);
124 else 124 else
125 scan_tree(value); 125 scan_tree(value);
126 else if (!strcmp(name, "source-filter")) 126 else if (!strcmp(name, "source-filter"))
127 ctx.cfg.source_filter = new_filter(value, 1); 127 ctx.cfg.source_filter = new_filter(value, 1);
128 else if (!strcmp(name, "summary-log")) 128 else if (!strcmp(name, "summary-log"))
129 ctx.cfg.summary_log = atoi(value); 129 ctx.cfg.summary_log = atoi(value);
130 else if (!strcmp(name, "summary-branches")) 130 else if (!strcmp(name, "summary-branches"))
131 ctx.cfg.summary_branches = atoi(value); 131 ctx.cfg.summary_branches = atoi(value);
132 else if (!strcmp(name, "summary-tags")) 132 else if (!strcmp(name, "summary-tags"))
133 ctx.cfg.summary_tags = atoi(value); 133 ctx.cfg.summary_tags = atoi(value);
134 else if (!strcmp(name, "agefile")) 134 else if (!strcmp(name, "agefile"))
135 ctx.cfg.agefile = xstrdup(value); 135 ctx.cfg.agefile = xstrdup(value);
136 else if (!strcmp(name, "renamelimit")) 136 else if (!strcmp(name, "renamelimit"))
137 ctx.cfg.renamelimit = atoi(value); 137 ctx.cfg.renamelimit = atoi(value);
138 else if (!strcmp(name, "robots")) 138 else if (!strcmp(name, "robots"))
139 ctx.cfg.robots = xstrdup(value); 139 ctx.cfg.robots = xstrdup(value);
140 else if (!strcmp(name, "clone-prefix")) 140 else if (!strcmp(name, "clone-prefix"))
141 ctx.cfg.clone_prefix = xstrdup(value); 141 ctx.cfg.clone_prefix = xstrdup(value);
142 else if (!strcmp(name, "local-time")) 142 else if (!strcmp(name, "local-time"))
143 ctx.cfg.local_time = atoi(value); 143 ctx.cfg.local_time = atoi(value);
144 else if (!prefixcmp(name, "mimetype.")) 144 else if (!prefixcmp(name, "mimetype."))
145 add_mimetype(name + 9, value); 145 add_mimetype(name + 9, value);
146 else if (!strcmp(name, "repo.group")) 146 else if (!strcmp(name, "section") || !strcmp(name, "repo.group"))
147 ctx.cfg.repo_group = xstrdup(value); 147 ctx.cfg.section = xstrdup(value);
148 else if (!strcmp(name, "repo.url")) 148 else if (!strcmp(name, "repo.url"))
149 ctx.repo = cgit_add_repo(value); 149 ctx.repo = cgit_add_repo(value);
150 else if (!strcmp(name, "repo.name")) 150 else if (!strcmp(name, "repo.name"))
151 ctx.repo->name = xstrdup(value); 151 ctx.repo->name = xstrdup(value);
152 else if (ctx.repo && !strcmp(name, "repo.path")) 152 else if (ctx.repo && !strcmp(name, "repo.path"))
153 ctx.repo->path = trim_end(value, '/'); 153 ctx.repo->path = trim_end(value, '/');
154 else if (ctx.repo && !strcmp(name, "repo.clone-url")) 154 else if (ctx.repo && !strcmp(name, "repo.clone-url"))
155 ctx.repo->clone_url = xstrdup(value); 155 ctx.repo->clone_url = xstrdup(value);
156 else if (ctx.repo && !strcmp(name, "repo.desc")) 156 else if (ctx.repo && !strcmp(name, "repo.desc"))
157 ctx.repo->desc = xstrdup(value); 157 ctx.repo->desc = xstrdup(value);
158 else if (ctx.repo && !strcmp(name, "repo.owner")) 158 else if (ctx.repo && !strcmp(name, "repo.owner"))
159 ctx.repo->owner = xstrdup(value); 159 ctx.repo->owner = xstrdup(value);
160 else if (ctx.repo && !strcmp(name, "repo.defbranch")) 160 else if (ctx.repo && !strcmp(name, "repo.defbranch"))
161 ctx.repo->defbranch = xstrdup(value); 161 ctx.repo->defbranch = xstrdup(value);
162 else if (ctx.repo && !strcmp(name, "repo.snapshots")) 162 else if (ctx.repo && !strcmp(name, "repo.snapshots"))
163 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */ 163 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */
164 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount")) 164 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount"))
165 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value); 165 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value);
166 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount")) 166 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount"))
167 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); 167 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value);
168 else if (ctx.repo && !strcmp(name, "repo.max-stats")) 168 else if (ctx.repo && !strcmp(name, "repo.max-stats"))
169 ctx.repo->max_stats = cgit_find_stats_period(value, NULL); 169 ctx.repo->max_stats = cgit_find_stats_period(value, NULL);
170 else if (ctx.repo && !strcmp(name, "repo.module-link")) 170 else if (ctx.repo && !strcmp(name, "repo.module-link"))
171 ctx.repo->module_link= xstrdup(value); 171 ctx.repo->module_link= xstrdup(value);
172 else if (ctx.repo && !strcmp(name, "repo.about-filter")) 172 else if (ctx.repo && !strcmp(name, "repo.about-filter"))
173 ctx.repo->about_filter = new_filter(value, 0); 173 ctx.repo->about_filter = new_filter(value, 0);
174 else if (ctx.repo && !strcmp(name, "repo.commit-filter")) 174 else if (ctx.repo && !strcmp(name, "repo.commit-filter"))
175 ctx.repo->commit_filter = new_filter(value, 0); 175 ctx.repo->commit_filter = new_filter(value, 0);
176 else if (ctx.repo && !strcmp(name, "repo.source-filter")) 176 else if (ctx.repo && !strcmp(name, "repo.source-filter"))
177 ctx.repo->source_filter = new_filter(value, 1); 177 ctx.repo->source_filter = new_filter(value, 1);
178 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) { 178 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) {
179 if (*value == '/') 179 if (*value == '/')
180 ctx.repo->readme = xstrdup(value); 180 ctx.repo->readme = xstrdup(value);
181 else 181 else
182 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value)); 182 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value));
183 } else if (!strcmp(name, "include")) 183 } else if (!strcmp(name, "include"))
184 parse_configfile(value, config_cb); 184 parse_configfile(value, config_cb);
185} 185}
186 186
187static void querystring_cb(const char *name, const char *value) 187static void querystring_cb(const char *name, const char *value)
188{ 188{
189 if (!value) 189 if (!value)
190 value = ""; 190 value = "";
191 191
192 if (!strcmp(name,"r")) { 192 if (!strcmp(name,"r")) {
193 ctx.qry.repo = xstrdup(value); 193 ctx.qry.repo = xstrdup(value);
194 ctx.repo = cgit_get_repoinfo(value); 194 ctx.repo = cgit_get_repoinfo(value);
195 } else if (!strcmp(name, "p")) { 195 } else if (!strcmp(name, "p")) {
196 ctx.qry.page = xstrdup(value); 196 ctx.qry.page = xstrdup(value);
197 } else if (!strcmp(name, "url")) { 197 } else if (!strcmp(name, "url")) {
198 ctx.qry.url = xstrdup(value); 198 ctx.qry.url = xstrdup(value);
199 cgit_parse_url(value); 199 cgit_parse_url(value);
200 } else if (!strcmp(name, "qt")) { 200 } else if (!strcmp(name, "qt")) {
201 ctx.qry.grep = xstrdup(value); 201 ctx.qry.grep = xstrdup(value);
202 } else if (!strcmp(name, "q")) { 202 } else if (!strcmp(name, "q")) {
203 ctx.qry.search = xstrdup(value); 203 ctx.qry.search = xstrdup(value);
204 } else if (!strcmp(name, "h")) { 204 } else if (!strcmp(name, "h")) {
205 ctx.qry.head = xstrdup(value); 205 ctx.qry.head = xstrdup(value);
206 ctx.qry.has_symref = 1; 206 ctx.qry.has_symref = 1;
207 } else if (!strcmp(name, "id")) { 207 } else if (!strcmp(name, "id")) {
208 ctx.qry.sha1 = xstrdup(value); 208 ctx.qry.sha1 = xstrdup(value);
209 ctx.qry.has_sha1 = 1; 209 ctx.qry.has_sha1 = 1;
210 } else if (!strcmp(name, "id2")) { 210 } else if (!strcmp(name, "id2")) {
211 ctx.qry.sha2 = xstrdup(value); 211 ctx.qry.sha2 = xstrdup(value);
diff --git a/cgit.css b/cgit.css
index e3b32e7..3c65114 100644
--- a/cgit.css
+++ b/cgit.css
@@ -368,129 +368,129 @@ table.diffstat td.graph {
368 368
369table.diffstat td.graph table { 369table.diffstat td.graph table {
370 border: none; 370 border: none;
371} 371}
372 372
373table.diffstat td.graph td { 373table.diffstat td.graph td {
374 padding: 0px; 374 padding: 0px;
375 border: 0px; 375 border: 0px;
376 height: 7pt; 376 height: 7pt;
377} 377}
378 378
379table.diffstat td.graph td.add { 379table.diffstat td.graph td.add {
380 background-color: #5c5; 380 background-color: #5c5;
381} 381}
382 382
383table.diffstat td.graph td.rem { 383table.diffstat td.graph td.rem {
384 background-color: #c55; 384 background-color: #c55;
385} 385}
386 386
387div.diffstat-summary { 387div.diffstat-summary {
388 color: #888; 388 color: #888;
389 padding-top: 0.5em; 389 padding-top: 0.5em;
390} 390}
391 391
392table.diff { 392table.diff {
393 width: 100%; 393 width: 100%;
394} 394}
395 395
396table.diff td { 396table.diff td {
397 font-family: monospace; 397 font-family: monospace;
398 white-space: pre; 398 white-space: pre;
399} 399}
400 400
401table.diff td div.head { 401table.diff td div.head {
402 font-weight: bold; 402 font-weight: bold;
403 margin-top: 1em; 403 margin-top: 1em;
404 color: black; 404 color: black;
405} 405}
406 406
407table.diff td div.hunk { 407table.diff td div.hunk {
408 color: #009; 408 color: #009;
409} 409}
410 410
411table.diff td div.add { 411table.diff td div.add {
412 color: green; 412 color: green;
413} 413}
414 414
415table.diff td div.del { 415table.diff td div.del {
416 color: red; 416 color: red;
417} 417}
418 418
419.sha1 { 419.sha1 {
420 font-family: monospace; 420 font-family: monospace;
421 font-size: 90%; 421 font-size: 90%;
422} 422}
423 423
424.left { 424.left {
425 text-align: left; 425 text-align: left;
426} 426}
427 427
428.right { 428.right {
429 text-align: right; 429 text-align: right;
430} 430}
431 431
432table.list td.repogroup { 432table.list td.reposection {
433 font-style: italic; 433 font-style: italic;
434 color: #888; 434 color: #888;
435} 435}
436 436
437a.button { 437a.button {
438 font-size: 80%; 438 font-size: 80%;
439 padding: 0em 0.5em; 439 padding: 0em 0.5em;
440} 440}
441 441
442a.primary { 442a.primary {
443 font-size: 100%; 443 font-size: 100%;
444} 444}
445 445
446a.secondary { 446a.secondary {
447 font-size: 90%; 447 font-size: 90%;
448} 448}
449 449
450td.toplevel-repo { 450td.toplevel-repo {
451 451
452} 452}
453 453
454table.list td.sublevel-repo { 454table.list td.sublevel-repo {
455 padding-left: 1.5em; 455 padding-left: 1.5em;
456} 456}
457 457
458div.pager { 458div.pager {
459 text-align: center; 459 text-align: center;
460 margin: 1em 0em 0em 0em; 460 margin: 1em 0em 0em 0em;
461} 461}
462 462
463div.pager a { 463div.pager a {
464 color: #777; 464 color: #777;
465 margin: 0em 0.5em; 465 margin: 0em 0.5em;
466} 466}
467 467
468span.age-mins { 468span.age-mins {
469 font-weight: bold; 469 font-weight: bold;
470 color: #080; 470 color: #080;
471} 471}
472 472
473span.age-hours { 473span.age-hours {
474 color: #080; 474 color: #080;
475} 475}
476 476
477span.age-days { 477span.age-days {
478 color: #040; 478 color: #040;
479} 479}
480 480
481span.age-weeks { 481span.age-weeks {
482 color: #444; 482 color: #444;
483} 483}
484 484
485span.age-months { 485span.age-months {
486 color: #888; 486 color: #888;
487} 487}
488 488
489span.age-years { 489span.age-years {
490 color: #bbb; 490 color: #bbb;
491} 491}
492div.footer { 492div.footer {
493 margin-top: 0.5em; 493 margin-top: 0.5em;
494 text-align: center; 494 text-align: center;
495 font-size: 80%; 495 font-size: 80%;
496 color: #ccc; 496 color: #ccc;
diff --git a/cgit.h b/cgit.h
index 5659580..fc7c7d5 100644
--- a/cgit.h
+++ b/cgit.h
@@ -4,225 +4,225 @@
4 4
5#include <git-compat-util.h> 5#include <git-compat-util.h>
6#include <cache.h> 6#include <cache.h>
7#include <grep.h> 7#include <grep.h>
8#include <object.h> 8#include <object.h>
9#include <tree.h> 9#include <tree.h>
10#include <commit.h> 10#include <commit.h>
11#include <tag.h> 11#include <tag.h>
12#include <diff.h> 12#include <diff.h>
13#include <diffcore.h> 13#include <diffcore.h>
14#include <refs.h> 14#include <refs.h>
15#include <revision.h> 15#include <revision.h>
16#include <log-tree.h> 16#include <log-tree.h>
17#include <archive.h> 17#include <archive.h>
18#include <string-list.h> 18#include <string-list.h>
19#include <xdiff-interface.h> 19#include <xdiff-interface.h>
20#include <xdiff/xdiff.h> 20#include <xdiff/xdiff.h>
21#include <utf8.h> 21#include <utf8.h>
22 22
23 23
24/* 24/*
25 * Dateformats used on misc. pages 25 * Dateformats used on misc. pages
26 */ 26 */
27#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S (%Z)" 27#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S (%Z)"
28#define FMT_SHORTDATE "%Y-%m-%d" 28#define FMT_SHORTDATE "%Y-%m-%d"
29#define FMT_ATOMDATE "%Y-%m-%dT%H:%M:%SZ" 29#define FMT_ATOMDATE "%Y-%m-%dT%H:%M:%SZ"
30 30
31 31
32/* 32/*
33 * Limits used for relative dates 33 * Limits used for relative dates
34 */ 34 */
35#define TM_MIN 60 35#define TM_MIN 60
36#define TM_HOUR (TM_MIN * 60) 36#define TM_HOUR (TM_MIN * 60)
37#define TM_DAY (TM_HOUR * 24) 37#define TM_DAY (TM_HOUR * 24)
38#define TM_WEEK (TM_DAY * 7) 38#define TM_WEEK (TM_DAY * 7)
39#define TM_YEAR (TM_DAY * 365) 39#define TM_YEAR (TM_DAY * 365)
40#define TM_MONTH (TM_YEAR / 12.0) 40#define TM_MONTH (TM_YEAR / 12.0)
41 41
42 42
43/* 43/*
44 * Default encoding 44 * Default encoding
45 */ 45 */
46#define PAGE_ENCODING "UTF-8" 46#define PAGE_ENCODING "UTF-8"
47 47
48typedef void (*configfn)(const char *name, const char *value); 48typedef void (*configfn)(const char *name, const char *value);
49typedef void (*filepair_fn)(struct diff_filepair *pair); 49typedef void (*filepair_fn)(struct diff_filepair *pair);
50typedef void (*linediff_fn)(char *line, int len); 50typedef void (*linediff_fn)(char *line, int len);
51 51
52struct cgit_filter { 52struct cgit_filter {
53 char *cmd; 53 char *cmd;
54 char **argv; 54 char **argv;
55 int old_stdout; 55 int old_stdout;
56 int pipe_fh[2]; 56 int pipe_fh[2];
57 int pid; 57 int pid;
58 int exitstatus; 58 int exitstatus;
59}; 59};
60 60
61struct cgit_repo { 61struct cgit_repo {
62 char *url; 62 char *url;
63 char *name; 63 char *name;
64 char *path; 64 char *path;
65 char *desc; 65 char *desc;
66 char *owner; 66 char *owner;
67 char *defbranch; 67 char *defbranch;
68 char *group;
69 char *module_link; 68 char *module_link;
70 char *readme; 69 char *readme;
70 char *section;
71 char *clone_url; 71 char *clone_url;
72 int snapshots; 72 int snapshots;
73 int enable_log_filecount; 73 int enable_log_filecount;
74 int enable_log_linecount; 74 int enable_log_linecount;
75 int max_stats; 75 int max_stats;
76 time_t mtime; 76 time_t mtime;
77 struct cgit_filter *about_filter; 77 struct cgit_filter *about_filter;
78 struct cgit_filter *commit_filter; 78 struct cgit_filter *commit_filter;
79 struct cgit_filter *source_filter; 79 struct cgit_filter *source_filter;
80}; 80};
81 81
82struct cgit_repolist { 82struct cgit_repolist {
83 int length; 83 int length;
84 int count; 84 int count;
85 struct cgit_repo *repos; 85 struct cgit_repo *repos;
86}; 86};
87 87
88struct commitinfo { 88struct commitinfo {
89 struct commit *commit; 89 struct commit *commit;
90 char *author; 90 char *author;
91 char *author_email; 91 char *author_email;
92 unsigned long author_date; 92 unsigned long author_date;
93 char *committer; 93 char *committer;
94 char *committer_email; 94 char *committer_email;
95 unsigned long committer_date; 95 unsigned long committer_date;
96 char *subject; 96 char *subject;
97 char *msg; 97 char *msg;
98 char *msg_encoding; 98 char *msg_encoding;
99}; 99};
100 100
101struct taginfo { 101struct taginfo {
102 char *tagger; 102 char *tagger;
103 char *tagger_email; 103 char *tagger_email;
104 unsigned long tagger_date; 104 unsigned long tagger_date;
105 char *msg; 105 char *msg;
106}; 106};
107 107
108struct refinfo { 108struct refinfo {
109 const char *refname; 109 const char *refname;
110 struct object *object; 110 struct object *object;
111 union { 111 union {
112 struct taginfo *tag; 112 struct taginfo *tag;
113 struct commitinfo *commit; 113 struct commitinfo *commit;
114 }; 114 };
115}; 115};
116 116
117struct reflist { 117struct reflist {
118 struct refinfo **refs; 118 struct refinfo **refs;
119 int alloc; 119 int alloc;
120 int count; 120 int count;
121}; 121};
122 122
123struct cgit_query { 123struct cgit_query {
124 int has_symref; 124 int has_symref;
125 int has_sha1; 125 int has_sha1;
126 char *raw; 126 char *raw;
127 char *repo; 127 char *repo;
128 char *page; 128 char *page;
129 char *search; 129 char *search;
130 char *grep; 130 char *grep;
131 char *head; 131 char *head;
132 char *sha1; 132 char *sha1;
133 char *sha2; 133 char *sha2;
134 char *path; 134 char *path;
135 char *name; 135 char *name;
136 char *mimetype; 136 char *mimetype;
137 char *url; 137 char *url;
138 char *period; 138 char *period;
139 int ofs; 139 int ofs;
140 int nohead; 140 int nohead;
141 char *sort; 141 char *sort;
142 int showmsg; 142 int showmsg;
143}; 143};
144 144
145struct cgit_config { 145struct cgit_config {
146 char *agefile; 146 char *agefile;
147 char *cache_root; 147 char *cache_root;
148 char *clone_prefix; 148 char *clone_prefix;
149 char *css; 149 char *css;
150 char *favicon; 150 char *favicon;
151 char *footer; 151 char *footer;
152 char *head_include; 152 char *head_include;
153 char *header; 153 char *header;
154 char *index_header; 154 char *index_header;
155 char *index_info; 155 char *index_info;
156 char *logo; 156 char *logo;
157 char *logo_link; 157 char *logo_link;
158 char *module_link; 158 char *module_link;
159 char *repo_group;
160 char *robots; 159 char *robots;
161 char *root_title; 160 char *root_title;
162 char *root_desc; 161 char *root_desc;
163 char *root_readme; 162 char *root_readme;
164 char *script_name; 163 char *script_name;
164 char *section;
165 char *virtual_root; 165 char *virtual_root;
166 int cache_size; 166 int cache_size;
167 int cache_dynamic_ttl; 167 int cache_dynamic_ttl;
168 int cache_max_create_time; 168 int cache_max_create_time;
169 int cache_repo_ttl; 169 int cache_repo_ttl;
170 int cache_root_ttl; 170 int cache_root_ttl;
171 int cache_scanrc_ttl; 171 int cache_scanrc_ttl;
172 int cache_static_ttl; 172 int cache_static_ttl;
173 int embedded; 173 int embedded;
174 int enable_index_links; 174 int enable_index_links;
175 int enable_log_filecount; 175 int enable_log_filecount;
176 int enable_log_linecount; 176 int enable_log_linecount;
177 int local_time; 177 int local_time;
178 int max_repo_count; 178 int max_repo_count;
179 int max_commit_count; 179 int max_commit_count;
180 int max_lock_attempts; 180 int max_lock_attempts;
181 int max_msg_len; 181 int max_msg_len;
182 int max_repodesc_len; 182 int max_repodesc_len;
183 int max_stats; 183 int max_stats;
184 int nocache; 184 int nocache;
185 int noplainemail; 185 int noplainemail;
186 int noheader; 186 int noheader;
187 int renamelimit; 187 int renamelimit;
188 int snapshots; 188 int snapshots;
189 int summary_branches; 189 int summary_branches;
190 int summary_log; 190 int summary_log;
191 int summary_tags; 191 int summary_tags;
192 struct string_list mimetypes; 192 struct string_list mimetypes;
193 struct cgit_filter *about_filter; 193 struct cgit_filter *about_filter;
194 struct cgit_filter *commit_filter; 194 struct cgit_filter *commit_filter;
195 struct cgit_filter *source_filter; 195 struct cgit_filter *source_filter;
196}; 196};
197 197
198struct cgit_page { 198struct cgit_page {
199 time_t modified; 199 time_t modified;
200 time_t expires; 200 time_t expires;
201 size_t size; 201 size_t size;
202 char *mimetype; 202 char *mimetype;
203 char *charset; 203 char *charset;
204 char *filename; 204 char *filename;
205 char *etag; 205 char *etag;
206 char *title; 206 char *title;
207 int status; 207 int status;
208 char *statusmsg; 208 char *statusmsg;
209}; 209};
210 210
211struct cgit_environment { 211struct cgit_environment {
212 char *cgit_config; 212 char *cgit_config;
213 char *http_host; 213 char *http_host;
214 char *https; 214 char *https;
215 char *no_http; 215 char *no_http;
216 char *path_info; 216 char *path_info;
217 char *query_string; 217 char *query_string;
218 char *request_method; 218 char *request_method;
219 char *script_name; 219 char *script_name;
220 char *server_name; 220 char *server_name;
221 char *server_port; 221 char *server_port;
222}; 222};
223 223
224struct cgit_context { 224struct cgit_context {
225 struct cgit_environment env; 225 struct cgit_environment env;
226 struct cgit_query qry; 226 struct cgit_query qry;
227 struct cgit_config cfg; 227 struct cgit_config cfg;
228 struct cgit_repo *repo; 228 struct cgit_repo *repo;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 2abbd41..4d009f9 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -139,153 +139,158 @@ index-info::
139 139
140local-time:: 140local-time::
141 Flag which, if set to "1", makes cgit print commit and tag times in the 141 Flag which, if set to "1", makes cgit print commit and tag times in the
142 servers timezone. Default value: "0". 142 servers timezone. Default value: "0".
143 143
144logo:: 144logo::
145 Url which specifies the source of an image which will be used as a logo 145 Url which specifies the source of an image which will be used as a logo
146 on all cgit pages. Default value: "/cgit.png". 146 on all cgit pages. Default value: "/cgit.png".
147 147
148logo-link:: 148logo-link::
149 Url loaded when clicking on the cgit logo image. If unspecified the 149 Url loaded when clicking on the cgit logo image. If unspecified the
150 calculated url of the repository index page will be used. Default 150 calculated url of the repository index page will be used. Default
151 value: none. 151 value: none.
152 152
153max-commit-count:: 153max-commit-count::
154 Specifies the number of entries to list per page in "log" view. Default 154 Specifies the number of entries to list per page in "log" view. Default
155 value: "50". 155 value: "50".
156 156
157max-message-length:: 157max-message-length::
158 Specifies the maximum number of commit message characters to display in 158 Specifies the maximum number of commit message characters to display in
159 "log" view. Default value: "80". 159 "log" view. Default value: "80".
160 160
161max-repo-count:: 161max-repo-count::
162 Specifies the number of entries to list per page on therepository 162 Specifies the number of entries to list per page on therepository
163 index page. Default value: "50". 163 index page. Default value: "50".
164 164
165max-repodesc-length:: 165max-repodesc-length::
166 Specifies the maximum number of repo description characters to display 166 Specifies the maximum number of repo description characters to display
167 on the repository index page. Default value: "80". 167 on the repository index page. Default value: "80".
168 168
169max-stats:: 169max-stats::
170 Set the default maximum statistics period. Valid values are "week", 170 Set the default maximum statistics period. Valid values are "week",
171 "month", "quarter" and "year". If unspecified, statistics are 171 "month", "quarter" and "year". If unspecified, statistics are
172 disabled. Default value: none. See also: "repo.max-stats". 172 disabled. Default value: none. See also: "repo.max-stats".
173 173
174mimetype.<ext>:: 174mimetype.<ext>::
175 Set the mimetype for the specified filename extension. This is used 175 Set the mimetype for the specified filename extension. This is used
176 by the `plain` command when returning blob content. 176 by the `plain` command when returning blob content.
177 177
178module-link:: 178module-link::
179 Text which will be used as the formatstring for a hyperlink when a 179 Text which will be used as the formatstring for a hyperlink when a
180 submodule is printed in a directory listing. The arguments for the 180 submodule is printed in a directory listing. The arguments for the
181 formatstring are the path and SHA1 of the submodule commit. Default 181 formatstring are the path and SHA1 of the submodule commit. Default
182 value: "./?repo=%s&page=commit&id=%s" 182 value: "./?repo=%s&page=commit&id=%s"
183 183
184nocache:: 184nocache::
185 If set to the value "1" caching will be disabled. This settings is 185 If set to the value "1" caching will be disabled. This settings is
186 deprecated, and will not be honored starting with cgit-1.0. Default 186 deprecated, and will not be honored starting with cgit-1.0. Default
187 value: "0". 187 value: "0".
188 188
189noplainemail:: 189noplainemail::
190 If set to "1" showing full author email adresses will be disabled. 190 If set to "1" showing full author email adresses will be disabled.
191 Default value: "0". 191 Default value: "0".
192 192
193noheader:: 193noheader::
194 Flag which, when set to "1", will make cgit omit the standard header 194 Flag which, when set to "1", will make cgit omit the standard header
195 on all pages. Default value: none. See also: "embedded". 195 on all pages. Default value: none. See also: "embedded".
196 196
197renamelimit:: 197renamelimit::
198 Maximum number of files to consider when detecting renames. The value 198 Maximum number of files to consider when detecting renames. The value
199 "-1" uses the compiletime value in git (for further info, look at 199 "-1" uses the compiletime value in git (for further info, look at
200 `man git-diff`). Default value: "-1". 200 `man git-diff`). Default value: "-1".
201 201
202repo.group:: 202repo.group::
203 A value for the current repository group, which all repositories 203 Legacy alias for 'section' which will be deprecated starting with
204 specified after this setting will inherit. Default value: none. 204 cgit-1.0.
205 205
206robots:: 206robots::
207 Text used as content for the "robots" meta-tag. Default value: 207 Text used as content for the "robots" meta-tag. Default value:
208 "index, nofollow". 208 "index, nofollow".
209 209
210root-desc:: 210root-desc::
211 Text printed below the heading on the repository index page. Default 211 Text printed below the heading on the repository index page. Default
212 value: "a fast webinterface for the git dscm". 212 value: "a fast webinterface for the git dscm".
213 213
214root-readme:: 214root-readme::
215 The content of the file specified with this option will be included 215 The content of the file specified with this option will be included
216 verbatim below the "about" link on the repository index page. Default 216 verbatim below the "about" link on the repository index page. Default
217 value: none. 217 value: none.
218 218
219root-title:: 219root-title::
220 Text printed as heading on the repository index page. Default value: 220 Text printed as heading on the repository index page. Default value:
221 "Git Repository Browser". 221 "Git Repository Browser".
222 222
223scan-path:: 223scan-path::
224 A path which will be scanned for repositories. If caching is enabled, 224 A path which will be scanned for repositories. If caching is enabled,
225 the result will be cached as a cgitrc include-file in the cache 225 the result will be cached as a cgitrc include-file in the cache
226 directory. Default value: none. See also: cache-scanrc-ttl. 226 directory. Default value: none. See also: cache-scanrc-ttl.
227 227
228section:
229 The name of the current repository section - all repositories defined
230 after this option will inherit the current section name. Default value:
231 none.
232
228snapshots:: 233snapshots::
229 Text which specifies the default set of snapshot formats generated by 234 Text which specifies the default set of snapshot formats generated by
230 cgit. The value is a space-separated list of zero or more of the 235 cgit. The value is a space-separated list of zero or more of the
231 values "tar", "tar.gz", "tar.bz2" and "zip". Default value: none. 236 values "tar", "tar.gz", "tar.bz2" and "zip". Default value: none.
232 237
233source-filter:: 238source-filter::
234 Specifies a command which will be invoked to format plaintext blobs 239 Specifies a command which will be invoked to format plaintext blobs
235 in the tree view. The command will get the blob content on its STDIN 240 in the tree view. The command will get the blob content on its STDIN
236 and the name of the blob as its only command line argument. The STDOUT 241 and the name of the blob as its only command line argument. The STDOUT
237 from the command will be included verbatim as the blob contents, i.e. 242 from the command will be included verbatim as the blob contents, i.e.
238 this can be used to implement e.g. syntax highlighting. Default value: 243 this can be used to implement e.g. syntax highlighting. Default value:
239 none. 244 none.
240 245
241summary-branches:: 246summary-branches::
242 Specifies the number of branches to display in the repository "summary" 247 Specifies the number of branches to display in the repository "summary"
243 view. Default value: "10". 248 view. Default value: "10".
244 249
245summary-log:: 250summary-log::
246 Specifies the number of log entries to display in the repository 251 Specifies the number of log entries to display in the repository
247 "summary" view. Default value: "10". 252 "summary" view. Default value: "10".
248 253
249summary-tags:: 254summary-tags::
250 Specifies the number of tags to display in the repository "summary" 255 Specifies the number of tags to display in the repository "summary"
251 view. Default value: "10". 256 view. Default value: "10".
252 257
253virtual-root:: 258virtual-root::
254 Url which, if specified, will be used as root for all cgit links. It 259 Url which, if specified, will be used as root for all cgit links. It
255 will also cause cgit to generate 'virtual urls', i.e. urls like 260 will also cause cgit to generate 'virtual urls', i.e. urls like
256 '/cgit/tree/README' as opposed to '?r=cgit&p=tree&path=README'. Default 261 '/cgit/tree/README' as opposed to '?r=cgit&p=tree&path=README'. Default
257 value: none. 262 value: none.
258 NOTE: cgit has recently learned how to use PATH_INFO to achieve the 263 NOTE: cgit has recently learned how to use PATH_INFO to achieve the
259 same kind of virtual urls, so this option will probably be deprecated. 264 same kind of virtual urls, so this option will probably be deprecated.
260 265
261REPOSITORY SETTINGS 266REPOSITORY SETTINGS
262------------------- 267-------------------
263repo.about-filter:: 268repo.about-filter::
264 Override the default about-filter. Default value: <about-filter>. 269 Override the default about-filter. Default value: <about-filter>.
265 270
266repo.clone-url:: 271repo.clone-url::
267 A list of space-separated urls which can be used to clone this repo. 272 A list of space-separated urls which can be used to clone this repo.
268 Default value: none. 273 Default value: none.
269 274
270repo.commit-filter:: 275repo.commit-filter::
271 Override the default commit-filter. Default value: <commit-filter>. 276 Override the default commit-filter. Default value: <commit-filter>.
272 277
273repo.defbranch:: 278repo.defbranch::
274 The name of the default branch for this repository. If no such branch 279 The name of the default branch for this repository. If no such branch
275 exists in the repository, the first branch name (when sorted) is used 280 exists in the repository, the first branch name (when sorted) is used
276 as default instead. Default value: "master". 281 as default instead. Default value: "master".
277 282
278repo.desc:: 283repo.desc::
279 The value to show as repository description. Default value: none. 284 The value to show as repository description. Default value: none.
280 285
281repo.enable-log-filecount:: 286repo.enable-log-filecount::
282 A flag which can be used to disable the global setting 287 A flag which can be used to disable the global setting
283 `enable-log-filecount'. Default value: none. 288 `enable-log-filecount'. Default value: none.
284 289
285repo.enable-log-linecount:: 290repo.enable-log-linecount::
286 A flag which can be used to disable the global setting 291 A flag which can be used to disable the global setting
287 `enable-log-linecount'. Default value: none. 292 `enable-log-linecount'. Default value: none.
288 293
289repo.max-stats:: 294repo.max-stats::
290 Override the default maximum statistics period. Valid values are equal 295 Override the default maximum statistics period. Valid values are equal
291 to the values specified for the global "max-stats" setting. Default 296 to the values specified for the global "max-stats" setting. Default
diff --git a/shared.c b/shared.c
index 4cb9573..9475581 100644
--- a/shared.c
+++ b/shared.c
@@ -1,120 +1,120 @@
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 cgit_repolist cgit_repolist; 11struct cgit_repolist cgit_repolist;
12struct cgit_context ctx; 12struct cgit_context ctx;
13int cgit_cmd; 13int cgit_cmd;
14 14
15int chk_zero(int result, char *msg) 15int chk_zero(int result, char *msg)
16{ 16{
17 if (result != 0) 17 if (result != 0)
18 die("%s: %s", msg, strerror(errno)); 18 die("%s: %s", msg, strerror(errno));
19 return result; 19 return result;
20} 20}
21 21
22int chk_positive(int result, char *msg) 22int chk_positive(int result, char *msg)
23{ 23{
24 if (result <= 0) 24 if (result <= 0)
25 die("%s: %s", msg, strerror(errno)); 25 die("%s: %s", msg, strerror(errno));
26 return result; 26 return result;
27} 27}
28 28
29int chk_non_negative(int result, char *msg) 29int chk_non_negative(int result, char *msg)
30{ 30{
31 if (result < 0) 31 if (result < 0)
32 die("%s: %s",msg, strerror(errno)); 32 die("%s: %s",msg, strerror(errno));
33 return result; 33 return result;
34} 34}
35 35
36struct cgit_repo *cgit_add_repo(const char *url) 36struct cgit_repo *cgit_add_repo(const char *url)
37{ 37{
38 struct cgit_repo *ret; 38 struct cgit_repo *ret;
39 39
40 if (++cgit_repolist.count > cgit_repolist.length) { 40 if (++cgit_repolist.count > cgit_repolist.length) {
41 if (cgit_repolist.length == 0) 41 if (cgit_repolist.length == 0)
42 cgit_repolist.length = 8; 42 cgit_repolist.length = 8;
43 else 43 else
44 cgit_repolist.length *= 2; 44 cgit_repolist.length *= 2;
45 cgit_repolist.repos = xrealloc(cgit_repolist.repos, 45 cgit_repolist.repos = xrealloc(cgit_repolist.repos,
46 cgit_repolist.length * 46 cgit_repolist.length *
47 sizeof(struct cgit_repo)); 47 sizeof(struct cgit_repo));
48 } 48 }
49 49
50 ret = &cgit_repolist.repos[cgit_repolist.count-1]; 50 ret = &cgit_repolist.repos[cgit_repolist.count-1];
51 ret->url = trim_end(url, '/'); 51 ret->url = trim_end(url, '/');
52 ret->name = ret->url; 52 ret->name = ret->url;
53 ret->path = NULL; 53 ret->path = NULL;
54 ret->desc = "[no description]"; 54 ret->desc = "[no description]";
55 ret->owner = NULL; 55 ret->owner = NULL;
56 ret->group = ctx.cfg.repo_group; 56 ret->section = ctx.cfg.section;
57 ret->defbranch = "master"; 57 ret->defbranch = "master";
58 ret->snapshots = ctx.cfg.snapshots; 58 ret->snapshots = ctx.cfg.snapshots;
59 ret->enable_log_filecount = ctx.cfg.enable_log_filecount; 59 ret->enable_log_filecount = ctx.cfg.enable_log_filecount;
60 ret->enable_log_linecount = ctx.cfg.enable_log_linecount; 60 ret->enable_log_linecount = ctx.cfg.enable_log_linecount;
61 ret->max_stats = ctx.cfg.max_stats; 61 ret->max_stats = ctx.cfg.max_stats;
62 ret->module_link = ctx.cfg.module_link; 62 ret->module_link = ctx.cfg.module_link;
63 ret->readme = NULL; 63 ret->readme = NULL;
64 ret->mtime = -1; 64 ret->mtime = -1;
65 ret->about_filter = ctx.cfg.about_filter; 65 ret->about_filter = ctx.cfg.about_filter;
66 ret->commit_filter = ctx.cfg.commit_filter; 66 ret->commit_filter = ctx.cfg.commit_filter;
67 ret->source_filter = ctx.cfg.source_filter; 67 ret->source_filter = ctx.cfg.source_filter;
68 return ret; 68 return ret;
69} 69}
70 70
71struct cgit_repo *cgit_get_repoinfo(const char *url) 71struct cgit_repo *cgit_get_repoinfo(const char *url)
72{ 72{
73 int i; 73 int i;
74 struct cgit_repo *repo; 74 struct cgit_repo *repo;
75 75
76 for (i=0; i<cgit_repolist.count; i++) { 76 for (i=0; i<cgit_repolist.count; i++) {
77 repo = &cgit_repolist.repos[i]; 77 repo = &cgit_repolist.repos[i];
78 if (!strcmp(repo->url, url)) 78 if (!strcmp(repo->url, url))
79 return repo; 79 return repo;
80 } 80 }
81 return NULL; 81 return NULL;
82} 82}
83 83
84void *cgit_free_commitinfo(struct commitinfo *info) 84void *cgit_free_commitinfo(struct commitinfo *info)
85{ 85{
86 free(info->author); 86 free(info->author);
87 free(info->author_email); 87 free(info->author_email);
88 free(info->committer); 88 free(info->committer);
89 free(info->committer_email); 89 free(info->committer_email);
90 free(info->subject); 90 free(info->subject);
91 free(info->msg); 91 free(info->msg);
92 free(info->msg_encoding); 92 free(info->msg_encoding);
93 free(info); 93 free(info);
94 return NULL; 94 return NULL;
95} 95}
96 96
97char *trim_end(const char *str, char c) 97char *trim_end(const char *str, char c)
98{ 98{
99 int len; 99 int len;
100 char *s, *t; 100 char *s, *t;
101 101
102 if (str == NULL) 102 if (str == NULL)
103 return NULL; 103 return NULL;
104 t = (char *)str; 104 t = (char *)str;
105 len = strlen(t); 105 len = strlen(t);
106 while(len > 0 && t[len - 1] == c) 106 while(len > 0 && t[len - 1] == c)
107 len--; 107 len--;
108 108
109 if (len == 0) 109 if (len == 0)
110 return NULL; 110 return NULL;
111 111
112 c = t[len]; 112 c = t[len];
113 t[len] = '\0'; 113 t[len] = '\0';
114 s = xstrdup(t); 114 s = xstrdup(t);
115 t[len] = c; 115 t[len] = c;
116 return s; 116 return s;
117} 117}
118 118
119char *strlpart(char *txt, int maxlen) 119char *strlpart(char *txt, int maxlen)
120{ 120{
diff --git a/ui-repolist.c b/ui-repolist.c
index 7c7aa9b..4dea3b3 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -142,144 +142,144 @@ static int sort_name(const void *a, const void *b)
142 const struct cgit_repo *r2 = b; 142 const struct cgit_repo *r2 = b;
143 143
144 return cmp(r1->name, r2->name); 144 return cmp(r1->name, r2->name);
145} 145}
146 146
147static int sort_desc(const void *a, const void *b) 147static int sort_desc(const void *a, const void *b)
148{ 148{
149 const struct cgit_repo *r1 = a; 149 const struct cgit_repo *r1 = a;
150 const struct cgit_repo *r2 = b; 150 const struct cgit_repo *r2 = b;
151 151
152 return cmp(r1->desc, r2->desc); 152 return cmp(r1->desc, r2->desc);
153} 153}
154 154
155static int sort_owner(const void *a, const void *b) 155static int sort_owner(const void *a, const void *b)
156{ 156{
157 const struct cgit_repo *r1 = a; 157 const struct cgit_repo *r1 = a;
158 const struct cgit_repo *r2 = b; 158 const struct cgit_repo *r2 = b;
159 159
160 return cmp(r1->owner, r2->owner); 160 return cmp(r1->owner, r2->owner);
161} 161}
162 162
163static int sort_idle(const void *a, const void *b) 163static int sort_idle(const void *a, const void *b)
164{ 164{
165 const struct cgit_repo *r1 = a; 165 const struct cgit_repo *r1 = a;
166 const struct cgit_repo *r2 = b; 166 const struct cgit_repo *r2 = b;
167 time_t t1, t2; 167 time_t t1, t2;
168 168
169 t1 = t2 = 0; 169 t1 = t2 = 0;
170 get_repo_modtime(r1, &t1); 170 get_repo_modtime(r1, &t1);
171 get_repo_modtime(r2, &t2); 171 get_repo_modtime(r2, &t2);
172 return t2 - t1; 172 return t2 - t1;
173} 173}
174 174
175struct sortcolumn { 175struct sortcolumn {
176 const char *name; 176 const char *name;
177 int (*fn)(const void *a, const void *b); 177 int (*fn)(const void *a, const void *b);
178}; 178};
179 179
180struct sortcolumn sortcolumn[] = { 180struct sortcolumn sortcolumn[] = {
181 {"name", sort_name}, 181 {"name", sort_name},
182 {"desc", sort_desc}, 182 {"desc", sort_desc},
183 {"owner", sort_owner}, 183 {"owner", sort_owner},
184 {"idle", sort_idle}, 184 {"idle", sort_idle},
185 {NULL, NULL} 185 {NULL, NULL}
186}; 186};
187 187
188int sort_repolist(char *field) 188int sort_repolist(char *field)
189{ 189{
190 struct sortcolumn *column; 190 struct sortcolumn *column;
191 191
192 for (column = &sortcolumn[0]; column->name; column++) { 192 for (column = &sortcolumn[0]; column->name; column++) {
193 if (strcmp(field, column->name)) 193 if (strcmp(field, column->name))
194 continue; 194 continue;
195 qsort(cgit_repolist.repos, cgit_repolist.count, 195 qsort(cgit_repolist.repos, cgit_repolist.count,
196 sizeof(struct cgit_repo), column->fn); 196 sizeof(struct cgit_repo), column->fn);
197 return 1; 197 return 1;
198 } 198 }
199 return 0; 199 return 0;
200} 200}
201 201
202 202
203void cgit_print_repolist() 203void cgit_print_repolist()
204{ 204{
205 int i, columns = 4, hits = 0, header = 0; 205 int i, columns = 4, hits = 0, header = 0;
206 char *last_group = NULL; 206 char *last_section = NULL;
207 int sorted = 0; 207 int sorted = 0;
208 208
209 if (ctx.cfg.enable_index_links) 209 if (ctx.cfg.enable_index_links)
210 columns++; 210 columns++;
211 211
212 ctx.page.title = ctx.cfg.root_title; 212 ctx.page.title = ctx.cfg.root_title;
213 cgit_print_http_headers(&ctx); 213 cgit_print_http_headers(&ctx);
214 cgit_print_docstart(&ctx); 214 cgit_print_docstart(&ctx);
215 cgit_print_pageheader(&ctx); 215 cgit_print_pageheader(&ctx);
216 216
217 if (ctx.cfg.index_header) 217 if (ctx.cfg.index_header)
218 html_include(ctx.cfg.index_header); 218 html_include(ctx.cfg.index_header);
219 219
220 if(ctx.qry.sort) 220 if(ctx.qry.sort)
221 sorted = sort_repolist(ctx.qry.sort); 221 sorted = sort_repolist(ctx.qry.sort);
222 222
223 html("<table summary='repository list' class='list nowrap'>"); 223 html("<table summary='repository list' class='list nowrap'>");
224 for (i=0; i<cgit_repolist.count; i++) { 224 for (i=0; i<cgit_repolist.count; i++) {
225 ctx.repo = &cgit_repolist.repos[i]; 225 ctx.repo = &cgit_repolist.repos[i];
226 if (!(is_match(ctx.repo) && is_in_url(ctx.repo))) 226 if (!(is_match(ctx.repo) && is_in_url(ctx.repo)))
227 continue; 227 continue;
228 hits++; 228 hits++;
229 if (hits <= ctx.qry.ofs) 229 if (hits <= ctx.qry.ofs)
230 continue; 230 continue;
231 if (hits > ctx.qry.ofs + ctx.cfg.max_repo_count) 231 if (hits > ctx.qry.ofs + ctx.cfg.max_repo_count)
232 continue; 232 continue;
233 if (!header++) 233 if (!header++)
234 print_header(columns); 234 print_header(columns);
235 if (!sorted && 235 if (!sorted &&
236 ((last_group == NULL && ctx.repo->group != NULL) || 236 ((last_section == NULL && ctx.repo->section != NULL) ||
237 (last_group != NULL && ctx.repo->group == NULL) || 237 (last_section != NULL && ctx.repo->section == NULL) ||
238 (last_group != NULL && ctx.repo->group != NULL && 238 (last_section != NULL && ctx.repo->section != NULL &&
239 strcmp(ctx.repo->group, last_group)))) { 239 strcmp(ctx.repo->section, last_section)))) {
240 htmlf("<tr class='nohover'><td colspan='%d' class='repogroup'>", 240 htmlf("<tr class='nohover'><td colspan='%d' class='reposection'>",
241 columns); 241 columns);
242 html_txt(ctx.repo->group); 242 html_txt(ctx.repo->section);
243 html("</td></tr>"); 243 html("</td></tr>");
244 last_group = ctx.repo->group; 244 last_section = ctx.repo->section;
245 } 245 }
246 htmlf("<tr><td class='%s'>", 246 htmlf("<tr><td class='%s'>",
247 !sorted && ctx.repo->group ? "sublevel-repo" : "toplevel-repo"); 247 !sorted && ctx.repo->section ? "sublevel-repo" : "toplevel-repo");
248 cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL); 248 cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL);
249 html("</td><td>"); 249 html("</td><td>");
250 html_link_open(cgit_repourl(ctx.repo->url), NULL, NULL); 250 html_link_open(cgit_repourl(ctx.repo->url), NULL, NULL);
251 html_ntxt(ctx.cfg.max_repodesc_len, ctx.repo->desc); 251 html_ntxt(ctx.cfg.max_repodesc_len, ctx.repo->desc);
252 html_link_close(); 252 html_link_close();
253 html("</td><td>"); 253 html("</td><td>");
254 html_txt(ctx.repo->owner); 254 html_txt(ctx.repo->owner);
255 html("</td><td>"); 255 html("</td><td>");
256 print_modtime(ctx.repo); 256 print_modtime(ctx.repo);
257 html("</td>"); 257 html("</td>");
258 if (ctx.cfg.enable_index_links) { 258 if (ctx.cfg.enable_index_links) {
259 html("<td>"); 259 html("<td>");
260 cgit_summary_link("summary", NULL, "button", NULL); 260 cgit_summary_link("summary", NULL, "button", NULL);
261 cgit_log_link("log", NULL, "button", NULL, NULL, NULL, 261 cgit_log_link("log", NULL, "button", NULL, NULL, NULL,
262 0, NULL, NULL, ctx.qry.showmsg); 262 0, NULL, NULL, ctx.qry.showmsg);
263 cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL); 263 cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL);
264 html("</td>"); 264 html("</td>");
265 } 265 }
266 html("</tr>\n"); 266 html("</tr>\n");
267 } 267 }
268 html("</table>"); 268 html("</table>");
269 if (!hits) 269 if (!hits)
270 cgit_print_error("No repositories found"); 270 cgit_print_error("No repositories found");
271 else if (hits > ctx.cfg.max_repo_count) 271 else if (hits > ctx.cfg.max_repo_count)
272 print_pager(hits, ctx.cfg.max_repo_count, ctx.qry.search); 272 print_pager(hits, ctx.cfg.max_repo_count, ctx.qry.search);
273 cgit_print_docend(); 273 cgit_print_docend();
274} 274}
275 275
276void cgit_print_site_readme() 276void cgit_print_site_readme()
277{ 277{
278 if (!ctx.cfg.root_readme) 278 if (!ctx.cfg.root_readme)
279 return; 279 return;
280 if (ctx.cfg.about_filter) 280 if (ctx.cfg.about_filter)
281 cgit_open_filter(ctx.cfg.about_filter); 281 cgit_open_filter(ctx.cfg.about_filter);
282 html_include(ctx.cfg.root_readme); 282 html_include(ctx.cfg.root_readme);
283 if (ctx.cfg.about_filter) 283 if (ctx.cfg.about_filter)
284 cgit_close_filter(ctx.cfg.about_filter); 284 cgit_close_filter(ctx.cfg.about_filter);
285} 285}