summaryrefslogtreecommitdiffabout
path: root/cgit.c
authorLars Hjemli <hjemli@gmail.com>2008-12-06 16:38:19 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2008-12-06 16:38:19 (UTC)
commitf86a23ff537258d36bf8f1876fa7a4bede6673d8 (patch) (unidiff)
tree8328d415416058cdc5b0fd2c6564ddcab5766c7a /cgit.c
parent140012d7a8e51df5a9f9c556696778b86ade4fc9 (diff)
downloadcgit-f86a23ff537258d36bf8f1876fa7a4bede6673d8.zip
cgit-f86a23ff537258d36bf8f1876fa7a4bede6673d8.tar.gz
cgit-f86a23ff537258d36bf8f1876fa7a4bede6673d8.tar.bz2
Add a 'stats' page to each repo
This new page, which is disabled by default, can be used to print some statistics about the number of commits per period in the repository, where period can be either weeks, months, quarters or years. The function can be activated globally by setting 'enable-stats=1' in cgitrc and disabled for individual repos by setting 'repo.enable-stats=0'. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'cgit.c') (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/cgit.c b/cgit.c
index c82587b..22b6d7c 100644
--- a/cgit.c
+++ b/cgit.c
@@ -9,196 +9,202 @@
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 "scan-tree.h" 15#include "scan-tree.h"
16 16
17const char *cgit_version = CGIT_VERSION; 17const char *cgit_version = CGIT_VERSION;
18 18
19void config_cb(const char *name, const char *value) 19void config_cb(const char *name, const char *value)
20{ 20{
21 if (!strcmp(name, "root-title")) 21 if (!strcmp(name, "root-title"))
22 ctx.cfg.root_title = xstrdup(value); 22 ctx.cfg.root_title = xstrdup(value);
23 else if (!strcmp(name, "root-desc")) 23 else if (!strcmp(name, "root-desc"))
24 ctx.cfg.root_desc = xstrdup(value); 24 ctx.cfg.root_desc = xstrdup(value);
25 else if (!strcmp(name, "root-readme")) 25 else if (!strcmp(name, "root-readme"))
26 ctx.cfg.root_readme = xstrdup(value); 26 ctx.cfg.root_readme = xstrdup(value);
27 else if (!strcmp(name, "css")) 27 else if (!strcmp(name, "css"))
28 ctx.cfg.css = xstrdup(value); 28 ctx.cfg.css = xstrdup(value);
29 else if (!strcmp(name, "favicon")) 29 else if (!strcmp(name, "favicon"))
30 ctx.cfg.favicon = xstrdup(value); 30 ctx.cfg.favicon = xstrdup(value);
31 else if (!strcmp(name, "footer")) 31 else if (!strcmp(name, "footer"))
32 ctx.cfg.footer = xstrdup(value); 32 ctx.cfg.footer = xstrdup(value);
33 else if (!strcmp(name, "logo")) 33 else if (!strcmp(name, "logo"))
34 ctx.cfg.logo = xstrdup(value); 34 ctx.cfg.logo = xstrdup(value);
35 else if (!strcmp(name, "index-header")) 35 else if (!strcmp(name, "index-header"))
36 ctx.cfg.index_header = xstrdup(value); 36 ctx.cfg.index_header = xstrdup(value);
37 else if (!strcmp(name, "index-info")) 37 else if (!strcmp(name, "index-info"))
38 ctx.cfg.index_info = xstrdup(value); 38 ctx.cfg.index_info = xstrdup(value);
39 else if (!strcmp(name, "logo-link")) 39 else if (!strcmp(name, "logo-link"))
40 ctx.cfg.logo_link = xstrdup(value); 40 ctx.cfg.logo_link = xstrdup(value);
41 else if (!strcmp(name, "module-link")) 41 else if (!strcmp(name, "module-link"))
42 ctx.cfg.module_link = xstrdup(value); 42 ctx.cfg.module_link = xstrdup(value);
43 else if (!strcmp(name, "virtual-root")) { 43 else if (!strcmp(name, "virtual-root")) {
44 ctx.cfg.virtual_root = trim_end(value, '/'); 44 ctx.cfg.virtual_root = trim_end(value, '/');
45 if (!ctx.cfg.virtual_root && (!strcmp(value, "/"))) 45 if (!ctx.cfg.virtual_root && (!strcmp(value, "/")))
46 ctx.cfg.virtual_root = ""; 46 ctx.cfg.virtual_root = "";
47 } else if (!strcmp(name, "nocache")) 47 } else if (!strcmp(name, "nocache"))
48 ctx.cfg.nocache = atoi(value); 48 ctx.cfg.nocache = atoi(value);
49 else if (!strcmp(name, "snapshots")) 49 else if (!strcmp(name, "snapshots"))
50 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); 50 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);
51 else if (!strcmp(name, "enable-index-links")) 51 else if (!strcmp(name, "enable-index-links"))
52 ctx.cfg.enable_index_links = atoi(value); 52 ctx.cfg.enable_index_links = atoi(value);
53 else if (!strcmp(name, "enable-log-filecount")) 53 else if (!strcmp(name, "enable-log-filecount"))
54 ctx.cfg.enable_log_filecount = atoi(value); 54 ctx.cfg.enable_log_filecount = atoi(value);
55 else if (!strcmp(name, "enable-log-linecount")) 55 else if (!strcmp(name, "enable-log-linecount"))
56 ctx.cfg.enable_log_linecount = atoi(value); 56 ctx.cfg.enable_log_linecount = atoi(value);
57 else if (!strcmp(name, "enable-stats"))
58 ctx.cfg.enable_stats = atoi(value);
57 else if (!strcmp(name, "cache-size")) 59 else if (!strcmp(name, "cache-size"))
58 ctx.cfg.cache_size = atoi(value); 60 ctx.cfg.cache_size = atoi(value);
59 else if (!strcmp(name, "cache-root")) 61 else if (!strcmp(name, "cache-root"))
60 ctx.cfg.cache_root = xstrdup(value); 62 ctx.cfg.cache_root = xstrdup(value);
61 else if (!strcmp(name, "cache-root-ttl")) 63 else if (!strcmp(name, "cache-root-ttl"))
62 ctx.cfg.cache_root_ttl = atoi(value); 64 ctx.cfg.cache_root_ttl = atoi(value);
63 else if (!strcmp(name, "cache-repo-ttl")) 65 else if (!strcmp(name, "cache-repo-ttl"))
64 ctx.cfg.cache_repo_ttl = atoi(value); 66 ctx.cfg.cache_repo_ttl = atoi(value);
65 else if (!strcmp(name, "cache-static-ttl")) 67 else if (!strcmp(name, "cache-static-ttl"))
66 ctx.cfg.cache_static_ttl = atoi(value); 68 ctx.cfg.cache_static_ttl = atoi(value);
67 else if (!strcmp(name, "cache-dynamic-ttl")) 69 else if (!strcmp(name, "cache-dynamic-ttl"))
68 ctx.cfg.cache_dynamic_ttl = atoi(value); 70 ctx.cfg.cache_dynamic_ttl = atoi(value);
69 else if (!strcmp(name, "max-message-length")) 71 else if (!strcmp(name, "max-message-length"))
70 ctx.cfg.max_msg_len = atoi(value); 72 ctx.cfg.max_msg_len = atoi(value);
71 else if (!strcmp(name, "max-repodesc-length")) 73 else if (!strcmp(name, "max-repodesc-length"))
72 ctx.cfg.max_repodesc_len = atoi(value); 74 ctx.cfg.max_repodesc_len = atoi(value);
73 else if (!strcmp(name, "max-repo-count")) 75 else if (!strcmp(name, "max-repo-count"))
74 ctx.cfg.max_repo_count = atoi(value); 76 ctx.cfg.max_repo_count = atoi(value);
75 else if (!strcmp(name, "max-commit-count")) 77 else if (!strcmp(name, "max-commit-count"))
76 ctx.cfg.max_commit_count = atoi(value); 78 ctx.cfg.max_commit_count = atoi(value);
77 else if (!strcmp(name, "summary-log")) 79 else if (!strcmp(name, "summary-log"))
78 ctx.cfg.summary_log = atoi(value); 80 ctx.cfg.summary_log = atoi(value);
79 else if (!strcmp(name, "summary-branches")) 81 else if (!strcmp(name, "summary-branches"))
80 ctx.cfg.summary_branches = atoi(value); 82 ctx.cfg.summary_branches = atoi(value);
81 else if (!strcmp(name, "summary-tags")) 83 else if (!strcmp(name, "summary-tags"))
82 ctx.cfg.summary_tags = atoi(value); 84 ctx.cfg.summary_tags = atoi(value);
83 else if (!strcmp(name, "agefile")) 85 else if (!strcmp(name, "agefile"))
84 ctx.cfg.agefile = xstrdup(value); 86 ctx.cfg.agefile = xstrdup(value);
85 else if (!strcmp(name, "renamelimit")) 87 else if (!strcmp(name, "renamelimit"))
86 ctx.cfg.renamelimit = atoi(value); 88 ctx.cfg.renamelimit = atoi(value);
87 else if (!strcmp(name, "robots")) 89 else if (!strcmp(name, "robots"))
88 ctx.cfg.robots = xstrdup(value); 90 ctx.cfg.robots = xstrdup(value);
89 else if (!strcmp(name, "clone-prefix")) 91 else if (!strcmp(name, "clone-prefix"))
90 ctx.cfg.clone_prefix = xstrdup(value); 92 ctx.cfg.clone_prefix = xstrdup(value);
91 else if (!strcmp(name, "local-time")) 93 else if (!strcmp(name, "local-time"))
92 ctx.cfg.local_time = atoi(value); 94 ctx.cfg.local_time = atoi(value);
93 else if (!strcmp(name, "repo.group")) 95 else if (!strcmp(name, "repo.group"))
94 ctx.cfg.repo_group = xstrdup(value); 96 ctx.cfg.repo_group = xstrdup(value);
95 else if (!strcmp(name, "repo.url")) 97 else if (!strcmp(name, "repo.url"))
96 ctx.repo = cgit_add_repo(value); 98 ctx.repo = cgit_add_repo(value);
97 else if (!strcmp(name, "repo.name")) 99 else if (!strcmp(name, "repo.name"))
98 ctx.repo->name = xstrdup(value); 100 ctx.repo->name = xstrdup(value);
99 else if (ctx.repo && !strcmp(name, "repo.path")) 101 else if (ctx.repo && !strcmp(name, "repo.path"))
100 ctx.repo->path = trim_end(value, '/'); 102 ctx.repo->path = trim_end(value, '/');
101 else if (ctx.repo && !strcmp(name, "repo.clone-url")) 103 else if (ctx.repo && !strcmp(name, "repo.clone-url"))
102 ctx.repo->clone_url = xstrdup(value); 104 ctx.repo->clone_url = xstrdup(value);
103 else if (ctx.repo && !strcmp(name, "repo.desc")) 105 else if (ctx.repo && !strcmp(name, "repo.desc"))
104 ctx.repo->desc = xstrdup(value); 106 ctx.repo->desc = xstrdup(value);
105 else if (ctx.repo && !strcmp(name, "repo.owner")) 107 else if (ctx.repo && !strcmp(name, "repo.owner"))
106 ctx.repo->owner = xstrdup(value); 108 ctx.repo->owner = xstrdup(value);
107 else if (ctx.repo && !strcmp(name, "repo.defbranch")) 109 else if (ctx.repo && !strcmp(name, "repo.defbranch"))
108 ctx.repo->defbranch = xstrdup(value); 110 ctx.repo->defbranch = xstrdup(value);
109 else if (ctx.repo && !strcmp(name, "repo.snapshots")) 111 else if (ctx.repo && !strcmp(name, "repo.snapshots"))
110 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */ 112 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */
111 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount")) 113 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount"))
112 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value); 114 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value);
113 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount")) 115 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount"))
114 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); 116 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value);
117 else if (ctx.repo && !strcmp(name, "repo.enable-stats"))
118 ctx.repo->enable_stats = ctx.cfg.enable_stats && atoi(value);
115 else if (ctx.repo && !strcmp(name, "repo.module-link")) 119 else if (ctx.repo && !strcmp(name, "repo.module-link"))
116 ctx.repo->module_link= xstrdup(value); 120 ctx.repo->module_link= xstrdup(value);
117 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) { 121 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) {
118 if (*value == '/') 122 if (*value == '/')
119 ctx.repo->readme = xstrdup(value); 123 ctx.repo->readme = xstrdup(value);
120 else 124 else
121 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value)); 125 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value));
122 } else if (!strcmp(name, "include")) 126 } else if (!strcmp(name, "include"))
123 parse_configfile(value, config_cb); 127 parse_configfile(value, config_cb);
124} 128}
125 129
126static void querystring_cb(const char *name, const char *value) 130static void querystring_cb(const char *name, const char *value)
127{ 131{
128 if (!strcmp(name,"r")) { 132 if (!strcmp(name,"r")) {
129 ctx.qry.repo = xstrdup(value); 133 ctx.qry.repo = xstrdup(value);
130 ctx.repo = cgit_get_repoinfo(value); 134 ctx.repo = cgit_get_repoinfo(value);
131 } else if (!strcmp(name, "p")) { 135 } else if (!strcmp(name, "p")) {
132 ctx.qry.page = xstrdup(value); 136 ctx.qry.page = xstrdup(value);
133 } else if (!strcmp(name, "url")) { 137 } else if (!strcmp(name, "url")) {
134 ctx.qry.url = xstrdup(value); 138 ctx.qry.url = xstrdup(value);
135 cgit_parse_url(value); 139 cgit_parse_url(value);
136 } else if (!strcmp(name, "qt")) { 140 } else if (!strcmp(name, "qt")) {
137 ctx.qry.grep = xstrdup(value); 141 ctx.qry.grep = xstrdup(value);
138 } else if (!strcmp(name, "q")) { 142 } else if (!strcmp(name, "q")) {
139 ctx.qry.search = xstrdup(value); 143 ctx.qry.search = xstrdup(value);
140 } else if (!strcmp(name, "h")) { 144 } else if (!strcmp(name, "h")) {
141 ctx.qry.head = xstrdup(value); 145 ctx.qry.head = xstrdup(value);
142 ctx.qry.has_symref = 1; 146 ctx.qry.has_symref = 1;
143 } else if (!strcmp(name, "id")) { 147 } else if (!strcmp(name, "id")) {
144 ctx.qry.sha1 = xstrdup(value); 148 ctx.qry.sha1 = xstrdup(value);
145 ctx.qry.has_sha1 = 1; 149 ctx.qry.has_sha1 = 1;
146 } else if (!strcmp(name, "id2")) { 150 } else if (!strcmp(name, "id2")) {
147 ctx.qry.sha2 = xstrdup(value); 151 ctx.qry.sha2 = xstrdup(value);
148 ctx.qry.has_sha1 = 1; 152 ctx.qry.has_sha1 = 1;
149 } else if (!strcmp(name, "ofs")) { 153 } else if (!strcmp(name, "ofs")) {
150 ctx.qry.ofs = atoi(value); 154 ctx.qry.ofs = atoi(value);
151 } else if (!strcmp(name, "path")) { 155 } else if (!strcmp(name, "path")) {
152 ctx.qry.path = trim_end(value, '/'); 156 ctx.qry.path = trim_end(value, '/');
153 } else if (!strcmp(name, "name")) { 157 } else if (!strcmp(name, "name")) {
154 ctx.qry.name = xstrdup(value); 158 ctx.qry.name = xstrdup(value);
155 } else if (!strcmp(name, "mimetype")) { 159 } else if (!strcmp(name, "mimetype")) {
156 ctx.qry.mimetype = xstrdup(value); 160 ctx.qry.mimetype = xstrdup(value);
161 } else if (!strcmp(name, "period")) {
162 ctx.qry.period = xstrdup(value);
157 } 163 }
158} 164}
159 165
160static void prepare_context(struct cgit_context *ctx) 166static void prepare_context(struct cgit_context *ctx)
161{ 167{
162 memset(ctx, 0, sizeof(ctx)); 168 memset(ctx, 0, sizeof(ctx));
163 ctx->cfg.agefile = "info/web/last-modified"; 169 ctx->cfg.agefile = "info/web/last-modified";
164 ctx->cfg.nocache = 0; 170 ctx->cfg.nocache = 0;
165 ctx->cfg.cache_size = 0; 171 ctx->cfg.cache_size = 0;
166 ctx->cfg.cache_dynamic_ttl = 5; 172 ctx->cfg.cache_dynamic_ttl = 5;
167 ctx->cfg.cache_max_create_time = 5; 173 ctx->cfg.cache_max_create_time = 5;
168 ctx->cfg.cache_repo_ttl = 5; 174 ctx->cfg.cache_repo_ttl = 5;
169 ctx->cfg.cache_root = CGIT_CACHE_ROOT; 175 ctx->cfg.cache_root = CGIT_CACHE_ROOT;
170 ctx->cfg.cache_root_ttl = 5; 176 ctx->cfg.cache_root_ttl = 5;
171 ctx->cfg.cache_static_ttl = -1; 177 ctx->cfg.cache_static_ttl = -1;
172 ctx->cfg.css = "/cgit.css"; 178 ctx->cfg.css = "/cgit.css";
173 ctx->cfg.logo = "/git-logo.png"; 179 ctx->cfg.logo = "/git-logo.png";
174 ctx->cfg.local_time = 0; 180 ctx->cfg.local_time = 0;
175 ctx->cfg.max_repo_count = 50; 181 ctx->cfg.max_repo_count = 50;
176 ctx->cfg.max_commit_count = 50; 182 ctx->cfg.max_commit_count = 50;
177 ctx->cfg.max_lock_attempts = 5; 183 ctx->cfg.max_lock_attempts = 5;
178 ctx->cfg.max_msg_len = 80; 184 ctx->cfg.max_msg_len = 80;
179 ctx->cfg.max_repodesc_len = 80; 185 ctx->cfg.max_repodesc_len = 80;
180 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s"; 186 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s";
181 ctx->cfg.renamelimit = -1; 187 ctx->cfg.renamelimit = -1;
182 ctx->cfg.robots = "index, nofollow"; 188 ctx->cfg.robots = "index, nofollow";
183 ctx->cfg.root_title = "Git repository browser"; 189 ctx->cfg.root_title = "Git repository browser";
184 ctx->cfg.root_desc = "a fast webinterface for the git dscm"; 190 ctx->cfg.root_desc = "a fast webinterface for the git dscm";
185 ctx->cfg.script_name = CGIT_SCRIPT_NAME; 191 ctx->cfg.script_name = CGIT_SCRIPT_NAME;
186 ctx->cfg.summary_branches = 10; 192 ctx->cfg.summary_branches = 10;
187 ctx->cfg.summary_log = 10; 193 ctx->cfg.summary_log = 10;
188 ctx->cfg.summary_tags = 10; 194 ctx->cfg.summary_tags = 10;
189 ctx->page.mimetype = "text/html"; 195 ctx->page.mimetype = "text/html";
190 ctx->page.charset = PAGE_ENCODING; 196 ctx->page.charset = PAGE_ENCODING;
191 ctx->page.filename = NULL; 197 ctx->page.filename = NULL;
192 ctx->page.size = 0; 198 ctx->page.size = 0;
193 ctx->page.modified = time(NULL); 199 ctx->page.modified = time(NULL);
194 ctx->page.expires = ctx->page.modified; 200 ctx->page.expires = ctx->page.modified;
195} 201}
196 202
197struct refmatch { 203struct refmatch {
198 char *req_ref; 204 char *req_ref;
199 char *first_ref; 205 char *first_ref;
200 int match; 206 int match;
201}; 207};
202 208
203int find_current_ref(const char *refname, const unsigned char *sha1, 209int find_current_ref(const char *refname, const unsigned char *sha1,
204 int flags, void *cb_data) 210 int flags, void *cb_data)