summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--Makefile2
-rw-r--r--cgit.c124
-rw-r--r--cgit.h14
-rw-r--r--cmd.c101
-rw-r--r--cmd.h15
-rw-r--r--parsing.c2
-rw-r--r--shared.c13
7 files changed, 165 insertions, 106 deletions
diff --git a/Makefile b/Makefile
index 7102908..d9ff7d8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,67 +1,67 @@
1CGIT_VERSION = v0.7.2 1CGIT_VERSION = v0.7.2
2CGIT_SCRIPT_NAME = cgit.cgi 2CGIT_SCRIPT_NAME = cgit.cgi
3CGIT_SCRIPT_PATH = /var/www/htdocs/cgit 3CGIT_SCRIPT_PATH = /var/www/htdocs/cgit
4CGIT_CONFIG = /etc/cgitrc 4CGIT_CONFIG = /etc/cgitrc
5CACHE_ROOT = /var/cache/cgit 5CACHE_ROOT = /var/cache/cgit
6SHA1_HEADER = <openssl/sha.h> 6SHA1_HEADER = <openssl/sha.h>
7GIT_VER = 1.5.4.1 7GIT_VER = 1.5.4.1
8GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2 8GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2
9 9
10# 10#
11# Let the user override the above settings. 11# Let the user override the above settings.
12# 12#
13-include cgit.conf 13-include cgit.conf
14 14
15 15
16EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lcrypto 16EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lcrypto
17OBJECTS = shared.o cache.o parsing.o html.o ui-shared.o ui-repolist.o \ 17OBJECTS = shared.o cache.o parsing.o html.o ui-shared.o ui-repolist.o \
18 ui-summary.o ui-log.o ui-tree.o ui-commit.o ui-diff.o \ 18 ui-summary.o ui-log.o ui-tree.o ui-commit.o ui-diff.o \
19 ui-snapshot.o ui-blob.o ui-tag.o ui-refs.o ui-patch.o 19 ui-snapshot.o ui-blob.o ui-tag.o ui-refs.o ui-patch.o cmd.o
20 20
21 21
22ifdef NEEDS_LIBICONV 22ifdef NEEDS_LIBICONV
23 EXTLIBS += -liconv 23 EXTLIBS += -liconv
24endif 24endif
25 25
26 26
27.PHONY: all git test install clean distclean emptycache force-version get-git 27.PHONY: all git test install clean distclean emptycache force-version get-git
28 28
29all: cgit git 29all: cgit git
30 30
31VERSION: force-version 31VERSION: force-version
32 @./gen-version.sh "$(CGIT_VERSION)" 32 @./gen-version.sh "$(CGIT_VERSION)"
33-include VERSION 33-include VERSION
34 34
35 35
36CFLAGS += -g -Wall -Igit 36CFLAGS += -g -Wall -Igit
37CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)' 37CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)'
38CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"' 38CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"'
39CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"' 39CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"'
40CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"' 40CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"'
41CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"' 41CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"'
42 42
43 43
44cgit: cgit.c $(OBJECTS) 44cgit: cgit.c $(OBJECTS)
45 $(CC) $(CFLAGS) cgit.c -o cgit $(OBJECTS) $(EXTLIBS) 45 $(CC) $(CFLAGS) cgit.c -o cgit $(OBJECTS) $(EXTLIBS)
46 46
47$(OBJECTS): cgit.h git/xdiff/lib.a git/libgit.a VERSION 47$(OBJECTS): cgit.h git/xdiff/lib.a git/libgit.a VERSION
48 48
49git/xdiff/lib.a: | git 49git/xdiff/lib.a: | git
50 50
51git/libgit.a: | git 51git/libgit.a: | git
52 52
53git: 53git:
54 cd git && $(MAKE) xdiff/lib.a 54 cd git && $(MAKE) xdiff/lib.a
55 cd git && $(MAKE) libgit.a 55 cd git && $(MAKE) libgit.a
56 56
57test: all 57test: all
58 $(MAKE) -C tests 58 $(MAKE) -C tests
59 59
60install: all 60install: all
61 mkdir -p $(DESTDIR)$(CGIT_SCRIPT_PATH) 61 mkdir -p $(DESTDIR)$(CGIT_SCRIPT_PATH)
62 install cgit $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) 62 install cgit $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)
63 install cgit.css $(DESTDIR)$(CGIT_SCRIPT_PATH)/cgit.css 63 install cgit.css $(DESTDIR)$(CGIT_SCRIPT_PATH)/cgit.css
64 install cgit.png $(DESTDIR)$(CGIT_SCRIPT_PATH)/cgit.png 64 install cgit.png $(DESTDIR)$(CGIT_SCRIPT_PATH)/cgit.png
65 65
66uninstall: 66uninstall:
67 rm -f $(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) 67 rm -f $(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)
diff --git a/cgit.c b/cgit.c
index a83f0be..79e0e43 100644
--- a/cgit.c
+++ b/cgit.c
@@ -36,228 +36,198 @@ static int cgit_prepare_cache(struct cacheitem *item)
36 } else { 36 } else {
37 item->name = xstrdup(fmt("%s/%s/%s/%s.html", ctx.cfg.cache_root, 37 item->name = xstrdup(fmt("%s/%s/%s/%s.html", ctx.cfg.cache_root,
38 cache_safe_filename(ctx.repo->url), 38 cache_safe_filename(ctx.repo->url),
39 ctx.qry.page, 39 ctx.qry.page,
40 cache_safe_filename(ctx.qry.raw))); 40 cache_safe_filename(ctx.qry.raw)));
41 if (ctx.qry.has_symref) 41 if (ctx.qry.has_symref)
42 item->ttl = ctx.cfg.cache_dynamic_ttl; 42 item->ttl = ctx.cfg.cache_dynamic_ttl;
43 else if (ctx.qry.has_sha1) 43 else if (ctx.qry.has_sha1)
44 item->ttl = ctx.cfg.cache_static_ttl; 44 item->ttl = ctx.cfg.cache_static_ttl;
45 else 45 else
46 item->ttl = ctx.cfg.cache_repo_ttl; 46 item->ttl = ctx.cfg.cache_repo_ttl;
47 } 47 }
48 return 1; 48 return 1;
49} 49}
50 50
51struct refmatch { 51struct refmatch {
52 char *req_ref; 52 char *req_ref;
53 char *first_ref; 53 char *first_ref;
54 int match; 54 int match;
55}; 55};
56 56
57int find_current_ref(const char *refname, const unsigned char *sha1, 57int find_current_ref(const char *refname, const unsigned char *sha1,
58 int flags, void *cb_data) 58 int flags, void *cb_data)
59{ 59{
60 struct refmatch *info; 60 struct refmatch *info;
61 61
62 info = (struct refmatch *)cb_data; 62 info = (struct refmatch *)cb_data;
63 if (!strcmp(refname, info->req_ref)) 63 if (!strcmp(refname, info->req_ref))
64 info->match = 1; 64 info->match = 1;
65 if (!info->first_ref) 65 if (!info->first_ref)
66 info->first_ref = xstrdup(refname); 66 info->first_ref = xstrdup(refname);
67 return info->match; 67 return info->match;
68} 68}
69 69
70char *find_default_branch(struct cgit_repo *repo) 70char *find_default_branch(struct cgit_repo *repo)
71{ 71{
72 struct refmatch info; 72 struct refmatch info;
73 73
74 info.req_ref = repo->defbranch; 74 info.req_ref = repo->defbranch;
75 info.first_ref = NULL; 75 info.first_ref = NULL;
76 info.match = 0; 76 info.match = 0;
77 for_each_branch_ref(find_current_ref, &info); 77 for_each_branch_ref(find_current_ref, &info);
78 if (info.match) 78 if (info.match)
79 return info.req_ref; 79 return info.req_ref;
80 else 80 else
81 return info.first_ref; 81 return info.first_ref;
82} 82}
83 83
84static void cgit_print_repo_page() 84static int prepare_repo_cmd(struct cgit_context *ctx)
85{ 85{
86 char *tmp; 86 char *tmp;
87 int show_search;
88 unsigned char sha1[20]; 87 unsigned char sha1[20];
89 int nongit = 0; 88 int nongit = 0;
90 89
91 setenv("GIT_DIR", ctx.repo->path, 1); 90 setenv("GIT_DIR", ctx->repo->path, 1);
92 setup_git_directory_gently(&nongit); 91 setup_git_directory_gently(&nongit);
93 if (nongit) { 92 if (nongit) {
94 ctx.page.title = fmt("%s - %s", ctx.cfg.root_title, 93 ctx->page.title = fmt("%s - %s", ctx->cfg.root_title,
95 "config error"); 94 "config error");
96 tmp = fmt("Not a git repository: '%s'", ctx.repo->path); 95 tmp = fmt("Not a git repository: '%s'", ctx->repo->path);
97 ctx.repo = NULL; 96 ctx->repo = NULL;
98 cgit_print_http_headers(&ctx); 97 cgit_print_http_headers(ctx);
99 cgit_print_docstart(&ctx); 98 cgit_print_docstart(ctx);
100 cgit_print_pageheader(&ctx); 99 cgit_print_pageheader(ctx);
101 cgit_print_error(tmp); 100 cgit_print_error(tmp);
102 cgit_print_docend(); 101 cgit_print_docend();
103 return; 102 return 1;
104 } 103 }
104 ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc);
105 105
106 ctx.page.title = fmt("%s - %s", ctx.repo->name, ctx.repo->desc); 106 if (!ctx->qry.head) {
107 show_search = 0; 107 ctx->qry.head = xstrdup(find_default_branch(ctx->repo));
108 108 ctx->repo->defbranch = ctx->qry.head;
109 if (!ctx.qry.head) {
110 ctx.qry.head = xstrdup(find_default_branch(ctx.repo));
111 ctx.repo->defbranch = ctx.qry.head;
112 } 109 }
113 110
114 if (!ctx.qry.head) { 111 if (!ctx->qry.head) {
115 cgit_print_http_headers(&ctx); 112 cgit_print_http_headers(ctx);
116 cgit_print_docstart(&ctx); 113 cgit_print_docstart(ctx);
117 cgit_print_pageheader(&ctx); 114 cgit_print_pageheader(ctx);
118 cgit_print_error("Repository seems to be empty"); 115 cgit_print_error("Repository seems to be empty");
119 cgit_print_docend(); 116 cgit_print_docend();
120 return; 117 return 1;
121 } 118 }
122 119
123 if (get_sha1(ctx.qry.head, sha1)) { 120 if (get_sha1(ctx->qry.head, sha1)) {
124 tmp = xstrdup(ctx.qry.head); 121 tmp = xstrdup(ctx->qry.head);
125 ctx.qry.head = ctx.repo->defbranch; 122 ctx->qry.head = ctx->repo->defbranch;
126 cgit_print_http_headers(&ctx); 123 cgit_print_http_headers(ctx);
127 cgit_print_docstart(&ctx); 124 cgit_print_docstart(ctx);
128 cgit_print_pageheader(&ctx); 125 cgit_print_pageheader(ctx);
129 cgit_print_error(fmt("Invalid branch: %s", tmp)); 126 cgit_print_error(fmt("Invalid branch: %s", tmp));
130 cgit_print_docend(); 127 cgit_print_docend();
131 return; 128 return 1;
132 } 129 }
133 130 return 0;
134 if ((cgit_cmd == CMD_SNAPSHOT) && ctx.repo->snapshots) {
135 cgit_print_snapshot(ctx.qry.head, ctx.qry.sha1,
136 cgit_repobasename(ctx.repo->url),
137 ctx.qry.path,
138 ctx.repo->snapshots );
139 return;
140 } 131 }
141 132
142 if (cgit_cmd == CMD_PATCH) { 133static void process_request(struct cgit_context *ctx)
143 cgit_print_patch(ctx.qry.sha1); 134{
135 struct cgit_cmd *cmd;
136
137 cmd = cgit_get_cmd(ctx);
138 if (!cmd) {
139 ctx->page.title = "cgit error";
140 ctx->repo = NULL;
141 cgit_print_http_headers(ctx);
142 cgit_print_docstart(ctx);
143 cgit_print_pageheader(ctx);
144 cgit_print_error("Invalid request");
145 cgit_print_docend();
144 return; 146 return;
145 } 147 }
146 148
147 if (cgit_cmd == CMD_BLOB) { 149 if (cmd->want_repo && prepare_repo_cmd(ctx))
148 cgit_print_blob(ctx.qry.sha1, ctx.qry.path);
149 return; 150 return;
150 }
151 151
152 show_search = (cgit_cmd == CMD_LOG); 152 if (cmd->want_layout) {
153 cgit_print_http_headers(&ctx); 153 cgit_print_http_headers(ctx);
154 cgit_print_docstart(&ctx); 154 cgit_print_docstart(ctx);
155 if (!cgit_cmd) { 155 cgit_print_pageheader(ctx);
156 cgit_print_pageheader(&ctx);
157 cgit_print_summary();
158 cgit_print_docend();
159 return;
160 } 156 }
161 157
162 cgit_print_pageheader(&ctx); 158 cmd->fn(ctx);
163 159
164 switch(cgit_cmd) { 160 if (cmd->want_layout)
165 case CMD_LOG:
166 cgit_print_log(ctx.qry.sha1, ctx.qry.ofs,
167 ctx.cfg.max_commit_count, ctx.qry.grep, ctx.qry.search,
168 ctx.qry.path, 1);
169 break;
170 case CMD_TREE:
171 cgit_print_tree(ctx.qry.sha1, ctx.qry.path);
172 break;
173 case CMD_COMMIT:
174 cgit_print_commit(ctx.qry.sha1);
175 break;
176 case CMD_REFS:
177 cgit_print_refs();
178 break;
179 case CMD_TAG:
180 cgit_print_tag(ctx.qry.sha1);
181 break;
182 case CMD_DIFF:
183 cgit_print_diff(ctx.qry.sha1, ctx.qry.sha2, ctx.qry.path);
184 break;
185 default:
186 cgit_print_error("Invalid request");
187 }
188 cgit_print_docend(); 161 cgit_print_docend();
189} 162}
190 163
191static long ttl_seconds(long ttl) 164static long ttl_seconds(long ttl)
192{ 165{
193 if (ttl<0) 166 if (ttl<0)
194 return 60 * 60 * 24 * 365; 167 return 60 * 60 * 24 * 365;
195 else 168 else
196 return ttl * 60; 169 return ttl * 60;
197} 170}
198 171
199static void cgit_fill_cache(struct cacheitem *item, int use_cache) 172static void cgit_fill_cache(struct cacheitem *item, int use_cache)
200{ 173{
201 int stdout2; 174 int stdout2;
202 175
203 if (use_cache) { 176 if (use_cache) {
204 stdout2 = chk_positive(dup(STDOUT_FILENO), 177 stdout2 = chk_positive(dup(STDOUT_FILENO),
205 "Preserving STDOUT"); 178 "Preserving STDOUT");
206 chk_zero(close(STDOUT_FILENO), "Closing STDOUT"); 179 chk_zero(close(STDOUT_FILENO), "Closing STDOUT");
207 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)"); 180 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)");
208 } 181 }
209 182
210 ctx.page.modified = time(NULL); 183 ctx.page.modified = time(NULL);
211 ctx.page.expires = ctx.page.modified + ttl_seconds(item->ttl); 184 ctx.page.expires = ctx.page.modified + ttl_seconds(item->ttl);
212 if (ctx.repo) 185 process_request(&ctx);
213 cgit_print_repo_page();
214 else
215 cgit_print_repolist();
216 186
217 if (use_cache) { 187 if (use_cache) {
218 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT"); 188 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT");
219 chk_positive(dup2(stdout2, STDOUT_FILENO), 189 chk_positive(dup2(stdout2, STDOUT_FILENO),
220 "Restoring original STDOUT"); 190 "Restoring original STDOUT");
221 chk_zero(close(stdout2), "Closing temporary STDOUT"); 191 chk_zero(close(stdout2), "Closing temporary STDOUT");
222 } 192 }
223} 193}
224 194
225static void cgit_check_cache(struct cacheitem *item) 195static void cgit_check_cache(struct cacheitem *item)
226{ 196{
227 int i = 0; 197 int i = 0;
228 198
229 top: 199 top:
230 if (++i > ctx.cfg.max_lock_attempts) { 200 if (++i > ctx.cfg.max_lock_attempts) {
231 die("cgit_refresh_cache: unable to lock %s: %s", 201 die("cgit_refresh_cache: unable to lock %s: %s",
232 item->name, strerror(errno)); 202 item->name, strerror(errno));
233 } 203 }
234 if (!cache_exist(item)) { 204 if (!cache_exist(item)) {
235 if (!cache_lock(item)) { 205 if (!cache_lock(item)) {
236 sleep(1); 206 sleep(1);
237 goto top; 207 goto top;
238 } 208 }
239 if (!cache_exist(item)) { 209 if (!cache_exist(item)) {
240 cgit_fill_cache(item, 1); 210 cgit_fill_cache(item, 1);
241 cache_unlock(item); 211 cache_unlock(item);
242 } else { 212 } else {
243 cache_cancel_lock(item); 213 cache_cancel_lock(item);
244 } 214 }
245 } else if (cache_expired(item) && cache_lock(item)) { 215 } else if (cache_expired(item) && cache_lock(item)) {
246 if (cache_expired(item)) { 216 if (cache_expired(item)) {
247 cgit_fill_cache(item, 1); 217 cgit_fill_cache(item, 1);
248 cache_unlock(item); 218 cache_unlock(item);
249 } else { 219 } else {
250 cache_cancel_lock(item); 220 cache_cancel_lock(item);
251 } 221 }
252 } 222 }
253} 223}
254 224
255static void cgit_print_cache(struct cacheitem *item) 225static void cgit_print_cache(struct cacheitem *item)
256{ 226{
257 static char buf[4096]; 227 static char buf[4096];
258 ssize_t i; 228 ssize_t i;
259 229
260 int fd = open(item->name, O_RDONLY); 230 int fd = open(item->name, O_RDONLY);
261 if (fd<0) 231 if (fd<0)
262 die("Unable to open cached file %s", item->name); 232 die("Unable to open cached file %s", item->name);
263 233
diff --git a/cgit.h b/cgit.h
index 40e2d40..295441b 100644
--- a/cgit.h
+++ b/cgit.h
@@ -1,83 +1,70 @@
1#ifndef CGIT_H 1#ifndef CGIT_H
2#define CGIT_H 2#define CGIT_H
3 3
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 <xdiff/xdiff.h> 18#include <xdiff/xdiff.h>
19#include <utf8.h> 19#include <utf8.h>
20 20
21 21
22/* 22/*
23 * The valid cgit repo-commands
24 */
25#define CMD_LOG 1
26#define CMD_COMMIT 2
27#define CMD_DIFF 3
28#define CMD_TREE 4
29#define CMD_BLOB 5
30#define CMD_SNAPSHOT 6
31#define CMD_TAG 7
32#define CMD_REFS 8
33#define CMD_PATCH 9
34
35/*
36 * Dateformats used on misc. pages 23 * Dateformats used on misc. pages
37 */ 24 */
38#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S" 25#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S"
39#define FMT_SHORTDATE "%Y-%m-%d" 26#define FMT_SHORTDATE "%Y-%m-%d"
40 27
41 28
42/* 29/*
43 * Limits used for relative dates 30 * Limits used for relative dates
44 */ 31 */
45#define TM_MIN 60 32#define TM_MIN 60
46#define TM_HOUR (TM_MIN * 60) 33#define TM_HOUR (TM_MIN * 60)
47#define TM_DAY (TM_HOUR * 24) 34#define TM_DAY (TM_HOUR * 24)
48#define TM_WEEK (TM_DAY * 7) 35#define TM_WEEK (TM_DAY * 7)
49#define TM_YEAR (TM_DAY * 365) 36#define TM_YEAR (TM_DAY * 365)
50#define TM_MONTH (TM_YEAR / 12.0) 37#define TM_MONTH (TM_YEAR / 12.0)
51 38
52 39
53/* 40/*
54 * Default encoding 41 * Default encoding
55 */ 42 */
56#define PAGE_ENCODING "UTF-8" 43#define PAGE_ENCODING "UTF-8"
57 44
58typedef void (*configfn)(const char *name, const char *value); 45typedef void (*configfn)(const char *name, const char *value);
59typedef void (*filepair_fn)(struct diff_filepair *pair); 46typedef void (*filepair_fn)(struct diff_filepair *pair);
60typedef void (*linediff_fn)(char *line, int len); 47typedef void (*linediff_fn)(char *line, int len);
61 48
62struct cacheitem { 49struct cacheitem {
63 char *name; 50 char *name;
64 struct stat st; 51 struct stat st;
65 int ttl; 52 int ttl;
66 int fd; 53 int fd;
67}; 54};
68 55
69struct cgit_repo { 56struct cgit_repo {
70 char *url; 57 char *url;
71 char *name; 58 char *name;
72 char *path; 59 char *path;
73 char *desc; 60 char *desc;
74 char *owner; 61 char *owner;
75 char *defbranch; 62 char *defbranch;
76 char *group; 63 char *group;
77 char *module_link; 64 char *module_link;
78 char *readme; 65 char *readme;
79 char *clone_url; 66 char *clone_url;
80 int snapshots; 67 int snapshots;
81 int enable_log_filecount; 68 int enable_log_filecount;
82 int enable_log_linecount; 69 int enable_log_linecount;
83}; 70};
@@ -152,97 +139,96 @@ struct cgit_config {
152 char *repo_group; 139 char *repo_group;
153 char *robots; 140 char *robots;
154 char *root_title; 141 char *root_title;
155 char *script_name; 142 char *script_name;
156 char *virtual_root; 143 char *virtual_root;
157 int cache_dynamic_ttl; 144 int cache_dynamic_ttl;
158 int cache_max_create_time; 145 int cache_max_create_time;
159 int cache_repo_ttl; 146 int cache_repo_ttl;
160 int cache_root_ttl; 147 int cache_root_ttl;
161 int cache_static_ttl; 148 int cache_static_ttl;
162 int enable_index_links; 149 int enable_index_links;
163 int enable_log_filecount; 150 int enable_log_filecount;
164 int enable_log_linecount; 151 int enable_log_linecount;
165 int max_commit_count; 152 int max_commit_count;
166 int max_lock_attempts; 153 int max_lock_attempts;
167 int max_msg_len; 154 int max_msg_len;
168 int max_repodesc_len; 155 int max_repodesc_len;
169 int nocache; 156 int nocache;
170 int renamelimit; 157 int renamelimit;
171 int snapshots; 158 int snapshots;
172 int summary_branches; 159 int summary_branches;
173 int summary_log; 160 int summary_log;
174 int summary_tags; 161 int summary_tags;
175}; 162};
176 163
177struct cgit_page { 164struct cgit_page {
178 time_t modified; 165 time_t modified;
179 time_t expires; 166 time_t expires;
180 char *mimetype; 167 char *mimetype;
181 char *charset; 168 char *charset;
182 char *filename; 169 char *filename;
183 char *title; 170 char *title;
184}; 171};
185 172
186struct cgit_context { 173struct cgit_context {
187 struct cgit_query qry; 174 struct cgit_query qry;
188 struct cgit_config cfg; 175 struct cgit_config cfg;
189 struct cgit_repo *repo; 176 struct cgit_repo *repo;
190 struct cgit_page page; 177 struct cgit_page page;
191}; 178};
192 179
193extern const char *cgit_version; 180extern const char *cgit_version;
194 181
195extern struct cgit_repolist cgit_repolist; 182extern struct cgit_repolist cgit_repolist;
196extern struct cgit_context ctx; 183extern struct cgit_context ctx;
197extern int cgit_cmd; 184extern int cgit_cmd;
198 185
199extern void cgit_prepare_context(struct cgit_context *ctx); 186extern void cgit_prepare_context(struct cgit_context *ctx);
200extern int cgit_get_cmd_index(const char *cmd);
201extern struct cgit_repo *cgit_get_repoinfo(const char *url); 187extern struct cgit_repo *cgit_get_repoinfo(const char *url);
202extern void cgit_global_config_cb(const char *name, const char *value); 188extern void cgit_global_config_cb(const char *name, const char *value);
203extern void cgit_repo_config_cb(const char *name, const char *value); 189extern void cgit_repo_config_cb(const char *name, const char *value);
204extern void cgit_querystring_cb(const char *name, const char *value); 190extern void cgit_querystring_cb(const char *name, const char *value);
205 191
206extern int chk_zero(int result, char *msg); 192extern int chk_zero(int result, char *msg);
207extern int chk_positive(int result, char *msg); 193extern int chk_positive(int result, char *msg);
208extern int chk_non_negative(int result, char *msg); 194extern int chk_non_negative(int result, char *msg);
209 195
210extern int hextoint(char c); 196extern int hextoint(char c);
211extern char *trim_end(const char *str, char c); 197extern char *trim_end(const char *str, char c);
212extern char *strlpart(char *txt, int maxlen); 198extern char *strlpart(char *txt, int maxlen);
213extern char *strrpart(char *txt, int maxlen); 199extern char *strrpart(char *txt, int maxlen);
214 200
215extern void cgit_add_ref(struct reflist *list, struct refinfo *ref); 201extern void cgit_add_ref(struct reflist *list, struct refinfo *ref);
216extern int cgit_refs_cb(const char *refname, const unsigned char *sha1, 202extern int cgit_refs_cb(const char *refname, const unsigned char *sha1,
217 int flags, void *cb_data); 203 int flags, void *cb_data);
218 204
219extern void *cgit_free_commitinfo(struct commitinfo *info); 205extern void *cgit_free_commitinfo(struct commitinfo *info);
220 206
221extern int cgit_diff_files(const unsigned char *old_sha1, 207extern int cgit_diff_files(const unsigned char *old_sha1,
222 const unsigned char *new_sha1, 208 const unsigned char *new_sha1,
223 linediff_fn fn); 209 linediff_fn fn);
224 210
225extern void cgit_diff_tree(const unsigned char *old_sha1, 211extern void cgit_diff_tree(const unsigned char *old_sha1,
226 const unsigned char *new_sha1, 212 const unsigned char *new_sha1,
227 filepair_fn fn, const char *prefix); 213 filepair_fn fn, const char *prefix);
228 214
229extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); 215extern void cgit_diff_commit(struct commit *commit, filepair_fn fn);
230 216
231extern char *fmt(const char *format,...); 217extern char *fmt(const char *format,...);
232 218
233extern int cgit_read_config(const char *filename, configfn fn); 219extern int cgit_read_config(const char *filename, configfn fn);
234extern int cgit_parse_query(char *txt, configfn fn); 220extern int cgit_parse_query(char *txt, configfn fn);
235extern struct commitinfo *cgit_parse_commit(struct commit *commit); 221extern struct commitinfo *cgit_parse_commit(struct commit *commit);
236extern struct taginfo *cgit_parse_tag(struct tag *tag); 222extern struct taginfo *cgit_parse_tag(struct tag *tag);
237extern void cgit_parse_url(const char *url); 223extern void cgit_parse_url(const char *url);
238 224
239extern char *cache_safe_filename(const char *unsafe); 225extern char *cache_safe_filename(const char *unsafe);
240extern int cache_lock(struct cacheitem *item); 226extern int cache_lock(struct cacheitem *item);
241extern int cache_unlock(struct cacheitem *item); 227extern int cache_unlock(struct cacheitem *item);
242extern int cache_cancel_lock(struct cacheitem *item); 228extern int cache_cancel_lock(struct cacheitem *item);
243extern int cache_exist(struct cacheitem *item); 229extern int cache_exist(struct cacheitem *item);
244extern int cache_expired(struct cacheitem *item); 230extern int cache_expired(struct cacheitem *item);
245 231
246extern char *cgit_repourl(const char *reponame); 232extern char *cgit_repourl(const char *reponame);
247extern char *cgit_fileurl(const char *reponame, const char *pagename, 233extern char *cgit_fileurl(const char *reponame, const char *pagename,
248 const char *filename, const char *query); 234 const char *filename, const char *query);
diff --git a/cmd.c b/cmd.c
new file mode 100644
index 0000000..489a11c
--- a/dev/null
+++ b/cmd.c
@@ -0,0 +1,101 @@
1/* cmd.c: the cgit command dispatcher
2 *
3 * Copyright (C) 2008 Lars Hjemli
4 *
5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text)
7 */
8
9#include "cgit.h"
10#include "cmd.h"
11
12static void blob_fn(struct cgit_context *ctx)
13{
14 cgit_print_blob(ctx->qry.sha1, ctx->qry.path);
15}
16
17static void commit_fn(struct cgit_context *ctx)
18{
19 cgit_print_commit(ctx->qry.sha1);
20}
21
22static void diff_fn(struct cgit_context *ctx)
23{
24 cgit_print_diff(ctx->qry.sha1, ctx->qry.sha2, ctx->qry.path);
25}
26
27static void repolist_fn(struct cgit_context *ctx)
28{
29 cgit_print_repolist();
30}
31
32static void log_fn(struct cgit_context *ctx)
33{
34 cgit_print_log(ctx->qry.sha1, ctx->qry.ofs, ctx->cfg.max_commit_count,
35 ctx->qry.grep, ctx->qry.search, ctx->qry.path, 1);
36}
37
38static void patch_fn(struct cgit_context *ctx)
39{
40 cgit_print_patch(ctx->qry.sha1);
41}
42
43static void refs_fn(struct cgit_context *ctx)
44{
45 cgit_print_refs();
46}
47
48static void snapshot_fn(struct cgit_context *ctx)
49{
50 cgit_print_snapshot(ctx->qry.head, ctx->qry.sha1,
51 cgit_repobasename(ctx->repo->url), ctx->qry.path,
52 ctx->repo->snapshots);
53}
54
55static void summary_fn(struct cgit_context *ctx)
56{
57 cgit_print_summary();
58}
59
60static void tag_fn(struct cgit_context *ctx)
61{
62 cgit_print_tag(ctx->qry.sha1);
63}
64
65static void tree_fn(struct cgit_context *ctx)
66{
67 cgit_print_tree(ctx->qry.sha1, ctx->qry.path);
68}
69
70#define def_cmd(name, want_repo, want_layout) \
71 {#name, name##_fn, want_repo, want_layout}
72
73struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx)
74{
75 static struct cgit_cmd cmds[] = {
76 def_cmd(blob, 1, 0),
77 def_cmd(commit, 1, 1),
78 def_cmd(diff, 1, 1),
79 def_cmd(log, 1, 1),
80 def_cmd(patch, 1, 0),
81 def_cmd(refs, 1, 1),
82 def_cmd(repolist, 0, 0),
83 def_cmd(snapshot, 1, 0),
84 def_cmd(summary, 1, 1),
85 def_cmd(tag, 1, 1),
86 def_cmd(tree, 1, 1),
87 };
88 int i;
89
90 if (ctx->qry.page == NULL) {
91 if (ctx->repo)
92 ctx->qry.page = "summary";
93 else
94 ctx->qry.page = "repolist";
95 }
96
97 for(i = 0; i < sizeof(cmds)/sizeof(*cmds); i++)
98 if (!strcmp(ctx->qry.page, cmds[i].name))
99 return &cmds[i];
100 return NULL;
101}
diff --git a/cmd.h b/cmd.h
new file mode 100644
index 0000000..ec9e691
--- a/dev/null
+++ b/cmd.h
@@ -0,0 +1,15 @@
1#ifndef CMD_H
2#define CMD_H
3
4typedef void (*cgit_cmd_fn)(struct cgit_context *ctx);
5
6struct cgit_cmd {
7 const char *name;
8 cgit_cmd_fn fn;
9 unsigned int want_repo:1,
10 want_layout:1;
11};
12
13extern struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx);
14
15#endif /* CMD_H */
diff --git a/parsing.c b/parsing.c
index 027f06b..8dce488 100644
--- a/parsing.c
+++ b/parsing.c
@@ -125,97 +125,97 @@ int cgit_parse_query(char *txt, configfn fn)
125 txt = t+1; 125 txt = t+1;
126 value = NULL; 126 value = NULL;
127 } 127 }
128 t++; 128 t++;
129 } 129 }
130 if (t!=txt) 130 if (t!=txt)
131 (*fn)(txt, value); 131 (*fn)(txt, value);
132 return 0; 132 return 0;
133} 133}
134 134
135/* 135/*
136 * url syntax: [repo ['/' cmd [ '/' path]]] 136 * url syntax: [repo ['/' cmd [ '/' path]]]
137 * repo: any valid repo url, may contain '/' 137 * repo: any valid repo url, may contain '/'
138 * cmd: log | commit | diff | tree | view | blob | snapshot 138 * cmd: log | commit | diff | tree | view | blob | snapshot
139 * path: any valid path, may contain '/' 139 * path: any valid path, may contain '/'
140 * 140 *
141 */ 141 */
142void cgit_parse_url(const char *url) 142void cgit_parse_url(const char *url)
143{ 143{
144 char *cmd, *p; 144 char *cmd, *p;
145 145
146 ctx.repo = NULL; 146 ctx.repo = NULL;
147 if (!url || url[0] == '\0') 147 if (!url || url[0] == '\0')
148 return; 148 return;
149 149
150 ctx.repo = cgit_get_repoinfo(url); 150 ctx.repo = cgit_get_repoinfo(url);
151 if (ctx.repo) { 151 if (ctx.repo) {
152 ctx.qry.repo = ctx.repo->url; 152 ctx.qry.repo = ctx.repo->url;
153 return; 153 return;
154 } 154 }
155 155
156 cmd = strchr(url, '/'); 156 cmd = strchr(url, '/');
157 while (!ctx.repo && cmd) { 157 while (!ctx.repo && cmd) {
158 cmd[0] = '\0'; 158 cmd[0] = '\0';
159 ctx.repo = cgit_get_repoinfo(url); 159 ctx.repo = cgit_get_repoinfo(url);
160 if (ctx.repo == NULL) { 160 if (ctx.repo == NULL) {
161 cmd[0] = '/'; 161 cmd[0] = '/';
162 cmd = strchr(cmd + 1, '/'); 162 cmd = strchr(cmd + 1, '/');
163 continue; 163 continue;
164 } 164 }
165 165
166 ctx.qry.repo = ctx.repo->url; 166 ctx.qry.repo = ctx.repo->url;
167 p = strchr(cmd + 1, '/'); 167 p = strchr(cmd + 1, '/');
168 if (p) { 168 if (p) {
169 p[0] = '\0'; 169 p[0] = '\0';
170 if (p[1]) 170 if (p[1])
171 ctx.qry.path = trim_end(p + 1, '/'); 171 ctx.qry.path = trim_end(p + 1, '/');
172 } 172 }
173 cgit_cmd = cgit_get_cmd_index(cmd + 1); 173 if (cmd[1])
174 ctx.qry.page = xstrdup(cmd + 1); 174 ctx.qry.page = xstrdup(cmd + 1);
175 return; 175 return;
176 } 176 }
177} 177}
178 178
179char *substr(const char *head, const char *tail) 179char *substr(const char *head, const char *tail)
180{ 180{
181 char *buf; 181 char *buf;
182 182
183 buf = xmalloc(tail - head + 1); 183 buf = xmalloc(tail - head + 1);
184 strncpy(buf, head, tail - head); 184 strncpy(buf, head, tail - head);
185 buf[tail - head] = '\0'; 185 buf[tail - head] = '\0';
186 return buf; 186 return buf;
187} 187}
188 188
189struct commitinfo *cgit_parse_commit(struct commit *commit) 189struct commitinfo *cgit_parse_commit(struct commit *commit)
190{ 190{
191 struct commitinfo *ret; 191 struct commitinfo *ret;
192 char *p = commit->buffer, *t = commit->buffer; 192 char *p = commit->buffer, *t = commit->buffer;
193 193
194 ret = xmalloc(sizeof(*ret)); 194 ret = xmalloc(sizeof(*ret));
195 ret->commit = commit; 195 ret->commit = commit;
196 ret->author = NULL; 196 ret->author = NULL;
197 ret->author_email = NULL; 197 ret->author_email = NULL;
198 ret->committer = NULL; 198 ret->committer = NULL;
199 ret->committer_email = NULL; 199 ret->committer_email = NULL;
200 ret->subject = NULL; 200 ret->subject = NULL;
201 ret->msg = NULL; 201 ret->msg = NULL;
202 ret->msg_encoding = NULL; 202 ret->msg_encoding = NULL;
203 203
204 if (p == NULL) 204 if (p == NULL)
205 return ret; 205 return ret;
206 206
207 if (strncmp(p, "tree ", 5)) 207 if (strncmp(p, "tree ", 5))
208 die("Bad commit: %s", sha1_to_hex(commit->object.sha1)); 208 die("Bad commit: %s", sha1_to_hex(commit->object.sha1));
209 else 209 else
210 p += 46; // "tree " + hex[40] + "\n" 210 p += 46; // "tree " + hex[40] + "\n"
211 211
212 while (!strncmp(p, "parent ", 7)) 212 while (!strncmp(p, "parent ", 7))
213 p += 48; // "parent " + hex[40] + "\n" 213 p += 48; // "parent " + hex[40] + "\n"
214 214
215 if (!strncmp(p, "author ", 7)) { 215 if (!strncmp(p, "author ", 7)) {
216 p += 7; 216 p += 7;
217 t = strchr(p, '<') - 1; 217 t = strchr(p, '<') - 1;
218 ret->author = substr(p, t); 218 ret->author = substr(p, t);
219 p = t; 219 p = t;
220 t = strchr(t, '>') + 1; 220 t = strchr(t, '>') + 1;
221 ret->author_email = substr(p, t); 221 ret->author_email = substr(p, t);
diff --git a/shared.c b/shared.c
index 539d533..67eb67b 100644
--- a/shared.c
+++ b/shared.c
@@ -1,102 +1,90 @@
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
15const char *cgit_version = CGIT_VERSION; 15const char *cgit_version = CGIT_VERSION;
16 16
17void cgit_prepare_context(struct cgit_context *ctx) 17void cgit_prepare_context(struct cgit_context *ctx)
18{ 18{
19 memset(ctx, 0, sizeof(ctx)); 19 memset(ctx, 0, sizeof(ctx));
20 ctx->cfg.agefile = "info/web/last-modified"; 20 ctx->cfg.agefile = "info/web/last-modified";
21 ctx->cfg.cache_dynamic_ttl = 5; 21 ctx->cfg.cache_dynamic_ttl = 5;
22 ctx->cfg.cache_max_create_time = 5; 22 ctx->cfg.cache_max_create_time = 5;
23 ctx->cfg.cache_repo_ttl = 5; 23 ctx->cfg.cache_repo_ttl = 5;
24 ctx->cfg.cache_root = CGIT_CACHE_ROOT; 24 ctx->cfg.cache_root = CGIT_CACHE_ROOT;
25 ctx->cfg.cache_root_ttl = 5; 25 ctx->cfg.cache_root_ttl = 5;
26 ctx->cfg.cache_static_ttl = -1; 26 ctx->cfg.cache_static_ttl = -1;
27 ctx->cfg.css = "/cgit.css"; 27 ctx->cfg.css = "/cgit.css";
28 ctx->cfg.logo = "/git-logo.png"; 28 ctx->cfg.logo = "/git-logo.png";
29 ctx->cfg.max_commit_count = 50; 29 ctx->cfg.max_commit_count = 50;
30 ctx->cfg.max_lock_attempts = 5; 30 ctx->cfg.max_lock_attempts = 5;
31 ctx->cfg.max_msg_len = 60; 31 ctx->cfg.max_msg_len = 60;
32 ctx->cfg.max_repodesc_len = 60; 32 ctx->cfg.max_repodesc_len = 60;
33 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s"; 33 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s";
34 ctx->cfg.renamelimit = -1; 34 ctx->cfg.renamelimit = -1;
35 ctx->cfg.robots = "index, nofollow"; 35 ctx->cfg.robots = "index, nofollow";
36 ctx->cfg.root_title = "Git repository browser"; 36 ctx->cfg.root_title = "Git repository browser";
37 ctx->cfg.script_name = CGIT_SCRIPT_NAME; 37 ctx->cfg.script_name = CGIT_SCRIPT_NAME;
38 ctx->page.mimetype = "text/html"; 38 ctx->page.mimetype = "text/html";
39 ctx->page.charset = PAGE_ENCODING; 39 ctx->page.charset = PAGE_ENCODING;
40 ctx->page.filename = NULL; 40 ctx->page.filename = NULL;
41} 41}
42 42
43int cgit_get_cmd_index(const char *cmd)
44{
45 static char *cmds[] = {"log", "commit", "diff", "tree", "blob",
46 "snapshot", "tag", "refs", "patch", NULL};
47 int i;
48
49 for(i = 0; cmds[i]; i++)
50 if (!strcmp(cmd, cmds[i]))
51 return i + 1;
52 return 0;
53}
54
55int chk_zero(int result, char *msg) 43int chk_zero(int result, char *msg)
56{ 44{
57 if (result != 0) 45 if (result != 0)
58 die("%s: %s", msg, strerror(errno)); 46 die("%s: %s", msg, strerror(errno));
59 return result; 47 return result;
60} 48}
61 49
62int chk_positive(int result, char *msg) 50int chk_positive(int result, char *msg)
63{ 51{
64 if (result <= 0) 52 if (result <= 0)
65 die("%s: %s", msg, strerror(errno)); 53 die("%s: %s", msg, strerror(errno));
66 return result; 54 return result;
67} 55}
68 56
69int chk_non_negative(int result, char *msg) 57int chk_non_negative(int result, char *msg)
70{ 58{
71 if (result < 0) 59 if (result < 0)
72 die("%s: %s",msg, strerror(errno)); 60 die("%s: %s",msg, strerror(errno));
73 return result; 61 return result;
74} 62}
75 63
76struct cgit_repo *add_repo(const char *url) 64struct cgit_repo *add_repo(const char *url)
77{ 65{
78 struct cgit_repo *ret; 66 struct cgit_repo *ret;
79 67
80 if (++cgit_repolist.count > cgit_repolist.length) { 68 if (++cgit_repolist.count > cgit_repolist.length) {
81 if (cgit_repolist.length == 0) 69 if (cgit_repolist.length == 0)
82 cgit_repolist.length = 8; 70 cgit_repolist.length = 8;
83 else 71 else
84 cgit_repolist.length *= 2; 72 cgit_repolist.length *= 2;
85 cgit_repolist.repos = xrealloc(cgit_repolist.repos, 73 cgit_repolist.repos = xrealloc(cgit_repolist.repos,
86 cgit_repolist.length * 74 cgit_repolist.length *
87 sizeof(struct cgit_repo)); 75 sizeof(struct cgit_repo));
88 } 76 }
89 77
90 ret = &cgit_repolist.repos[cgit_repolist.count-1]; 78 ret = &cgit_repolist.repos[cgit_repolist.count-1];
91 ret->url = trim_end(url, '/'); 79 ret->url = trim_end(url, '/');
92 ret->name = ret->url; 80 ret->name = ret->url;
93 ret->path = NULL; 81 ret->path = NULL;
94 ret->desc = "[no description]"; 82 ret->desc = "[no description]";
95 ret->owner = NULL; 83 ret->owner = NULL;
96 ret->group = ctx.cfg.repo_group; 84 ret->group = ctx.cfg.repo_group;
97 ret->defbranch = "master"; 85 ret->defbranch = "master";
98 ret->snapshots = ctx.cfg.snapshots; 86 ret->snapshots = ctx.cfg.snapshots;
99 ret->enable_log_filecount = ctx.cfg.enable_log_filecount; 87 ret->enable_log_filecount = ctx.cfg.enable_log_filecount;
100 ret->enable_log_linecount = ctx.cfg.enable_log_linecount; 88 ret->enable_log_linecount = ctx.cfg.enable_log_linecount;
101 ret->module_link = ctx.cfg.module_link; 89 ret->module_link = ctx.cfg.module_link;
102 ret->readme = NULL; 90 ret->readme = NULL;
@@ -171,97 +159,96 @@ void cgit_global_config_cb(const char *name, const char *value)
171 else if (!strcmp(name, "agefile")) 159 else if (!strcmp(name, "agefile"))
172 ctx.cfg.agefile = xstrdup(value); 160 ctx.cfg.agefile = xstrdup(value);
173 else if (!strcmp(name, "renamelimit")) 161 else if (!strcmp(name, "renamelimit"))
174 ctx.cfg.renamelimit = atoi(value); 162 ctx.cfg.renamelimit = atoi(value);
175 else if (!strcmp(name, "robots")) 163 else if (!strcmp(name, "robots"))
176 ctx.cfg.robots = xstrdup(value); 164 ctx.cfg.robots = xstrdup(value);
177 else if (!strcmp(name, "clone-prefix")) 165 else if (!strcmp(name, "clone-prefix"))
178 ctx.cfg.clone_prefix = xstrdup(value); 166 ctx.cfg.clone_prefix = xstrdup(value);
179 else if (!strcmp(name, "repo.group")) 167 else if (!strcmp(name, "repo.group"))
180 ctx.cfg.repo_group = xstrdup(value); 168 ctx.cfg.repo_group = xstrdup(value);
181 else if (!strcmp(name, "repo.url")) 169 else if (!strcmp(name, "repo.url"))
182 ctx.repo = add_repo(value); 170 ctx.repo = add_repo(value);
183 else if (!strcmp(name, "repo.name")) 171 else if (!strcmp(name, "repo.name"))
184 ctx.repo->name = xstrdup(value); 172 ctx.repo->name = xstrdup(value);
185 else if (ctx.repo && !strcmp(name, "repo.path")) 173 else if (ctx.repo && !strcmp(name, "repo.path"))
186 ctx.repo->path = trim_end(value, '/'); 174 ctx.repo->path = trim_end(value, '/');
187 else if (ctx.repo && !strcmp(name, "repo.clone-url")) 175 else if (ctx.repo && !strcmp(name, "repo.clone-url"))
188 ctx.repo->clone_url = xstrdup(value); 176 ctx.repo->clone_url = xstrdup(value);
189 else if (ctx.repo && !strcmp(name, "repo.desc")) 177 else if (ctx.repo && !strcmp(name, "repo.desc"))
190 ctx.repo->desc = xstrdup(value); 178 ctx.repo->desc = xstrdup(value);
191 else if (ctx.repo && !strcmp(name, "repo.owner")) 179 else if (ctx.repo && !strcmp(name, "repo.owner"))
192 ctx.repo->owner = xstrdup(value); 180 ctx.repo->owner = xstrdup(value);
193 else if (ctx.repo && !strcmp(name, "repo.defbranch")) 181 else if (ctx.repo && !strcmp(name, "repo.defbranch"))
194 ctx.repo->defbranch = xstrdup(value); 182 ctx.repo->defbranch = xstrdup(value);
195 else if (ctx.repo && !strcmp(name, "repo.snapshots")) 183 else if (ctx.repo && !strcmp(name, "repo.snapshots"))
196 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */ 184 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */
197 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount")) 185 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount"))
198 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value); 186 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value);
199 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount")) 187 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount"))
200 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); 188 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value);
201 else if (ctx.repo && !strcmp(name, "repo.module-link")) 189 else if (ctx.repo && !strcmp(name, "repo.module-link"))
202 ctx.repo->module_link= xstrdup(value); 190 ctx.repo->module_link= xstrdup(value);
203 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) { 191 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) {
204 if (*value == '/') 192 if (*value == '/')
205 ctx.repo->readme = xstrdup(value); 193 ctx.repo->readme = xstrdup(value);
206 else 194 else
207 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value)); 195 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value));
208 } else if (!strcmp(name, "include")) 196 } else if (!strcmp(name, "include"))
209 cgit_read_config(value, cgit_global_config_cb); 197 cgit_read_config(value, cgit_global_config_cb);
210} 198}
211 199
212void cgit_querystring_cb(const char *name, const char *value) 200void cgit_querystring_cb(const char *name, const char *value)
213{ 201{
214 if (!strcmp(name,"r")) { 202 if (!strcmp(name,"r")) {
215 ctx.qry.repo = xstrdup(value); 203 ctx.qry.repo = xstrdup(value);
216 ctx.repo = cgit_get_repoinfo(value); 204 ctx.repo = cgit_get_repoinfo(value);
217 } else if (!strcmp(name, "p")) { 205 } else if (!strcmp(name, "p")) {
218 ctx.qry.page = xstrdup(value); 206 ctx.qry.page = xstrdup(value);
219 cgit_cmd = cgit_get_cmd_index(value);
220 } else if (!strcmp(name, "url")) { 207 } else if (!strcmp(name, "url")) {
221 cgit_parse_url(value); 208 cgit_parse_url(value);
222 } else if (!strcmp(name, "qt")) { 209 } else if (!strcmp(name, "qt")) {
223 ctx.qry.grep = xstrdup(value); 210 ctx.qry.grep = xstrdup(value);
224 } else if (!strcmp(name, "q")) { 211 } else if (!strcmp(name, "q")) {
225 ctx.qry.search = xstrdup(value); 212 ctx.qry.search = xstrdup(value);
226 } else if (!strcmp(name, "h")) { 213 } else if (!strcmp(name, "h")) {
227 ctx.qry.head = xstrdup(value); 214 ctx.qry.head = xstrdup(value);
228 ctx.qry.has_symref = 1; 215 ctx.qry.has_symref = 1;
229 } else if (!strcmp(name, "id")) { 216 } else if (!strcmp(name, "id")) {
230 ctx.qry.sha1 = xstrdup(value); 217 ctx.qry.sha1 = xstrdup(value);
231 ctx.qry.has_sha1 = 1; 218 ctx.qry.has_sha1 = 1;
232 } else if (!strcmp(name, "id2")) { 219 } else if (!strcmp(name, "id2")) {
233 ctx.qry.sha2 = xstrdup(value); 220 ctx.qry.sha2 = xstrdup(value);
234 ctx.qry.has_sha1 = 1; 221 ctx.qry.has_sha1 = 1;
235 } else if (!strcmp(name, "ofs")) { 222 } else if (!strcmp(name, "ofs")) {
236 ctx.qry.ofs = atoi(value); 223 ctx.qry.ofs = atoi(value);
237 } else if (!strcmp(name, "path")) { 224 } else if (!strcmp(name, "path")) {
238 ctx.qry.path = trim_end(value, '/'); 225 ctx.qry.path = trim_end(value, '/');
239 } else if (!strcmp(name, "name")) { 226 } else if (!strcmp(name, "name")) {
240 ctx.qry.name = xstrdup(value); 227 ctx.qry.name = xstrdup(value);
241 } 228 }
242} 229}
243 230
244void *cgit_free_commitinfo(struct commitinfo *info) 231void *cgit_free_commitinfo(struct commitinfo *info)
245{ 232{
246 free(info->author); 233 free(info->author);
247 free(info->author_email); 234 free(info->author_email);
248 free(info->committer); 235 free(info->committer);
249 free(info->committer_email); 236 free(info->committer_email);
250 free(info->subject); 237 free(info->subject);
251 free(info->msg); 238 free(info->msg);
252 free(info->msg_encoding); 239 free(info->msg_encoding);
253 free(info); 240 free(info);
254 return NULL; 241 return NULL;
255} 242}
256 243
257int hextoint(char c) 244int hextoint(char c)
258{ 245{
259 if (c >= 'a' && c <= 'f') 246 if (c >= 'a' && c <= 'f')
260 return 10 + c - 'a'; 247 return 10 + c - 'a';
261 else if (c >= 'A' && c <= 'F') 248 else if (c >= 'A' && c <= 'F')
262 return 10 + c - 'A'; 249 return 10 + c - 'A';
263 else if (c >= '0' && c <= '9') 250 else if (c >= '0' && c <= '9')
264 return c - '0'; 251 return c - '0';
265 else 252 else
266 return -1; 253 return -1;
267} 254}