summaryrefslogtreecommitdiffabout
path: root/cgit.c
Unidiff
Diffstat (limited to 'cgit.c') (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c50
1 files changed, 33 insertions, 17 deletions
diff --git a/cgit.c b/cgit.c
index e6b4526..d0f6905 100644
--- a/cgit.c
+++ b/cgit.c
@@ -1,28 +1,31 @@
1/* cgit.c: cgi for the git scm 1/* cgit.c: cgi for the git scm
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include "cmd.h"
10 11
11static int cgit_prepare_cache(struct cacheitem *item) 12static int cgit_prepare_cache(struct cacheitem *item)
12{ 13{
13 if (!ctx.repo && ctx.qry.repo) { 14 if (!ctx.repo && ctx.qry.repo) {
14 char *title = fmt("%s - %s", ctx.cfg.root_title, "Bad request"); 15 ctx.page.title = fmt("%s - %s", ctx.cfg.root_title,
15 cgit_print_docstart(title, item); 16 "Bad request");
16 cgit_print_pageheader(title, 0); 17 cgit_print_http_headers(&ctx);
18 cgit_print_docstart(&ctx);
19 cgit_print_pageheader(&ctx);
17 cgit_print_error(fmt("Unknown repo: %s", ctx.qry.repo)); 20 cgit_print_error(fmt("Unknown repo: %s", ctx.qry.repo));
18 cgit_print_docend(); 21 cgit_print_docend();
19 return 0; 22 return 0;
20 } 23 }
21 24
22 if (!ctx.repo) { 25 if (!ctx.repo) {
23 item->name = xstrdup(fmt("%s/index.html", ctx.cfg.cache_root)); 26 item->name = xstrdup(fmt("%s/index.html", ctx.cfg.cache_root));
24 item->ttl = ctx.cfg.cache_root_ttl; 27 item->ttl = ctx.cfg.cache_root_ttl;
25 return 1; 28 return 1;
26 } 29 }
27 30
28 if (!cgit_cmd) { 31 if (!cgit_cmd) {
@@ -71,96 +74,101 @@ char *find_default_branch(struct cgit_repo *repo)
71 info.req_ref = repo->defbranch; 74 info.req_ref = repo->defbranch;
72 info.first_ref = NULL; 75 info.first_ref = NULL;
73 info.match = 0; 76 info.match = 0;
74 for_each_branch_ref(find_current_ref, &info); 77 for_each_branch_ref(find_current_ref, &info);
75 if (info.match) 78 if (info.match)
76 return info.req_ref; 79 return info.req_ref;
77 else 80 else
78 return info.first_ref; 81 return info.first_ref;
79} 82}
80 83
81static void cgit_print_repo_page(struct cacheitem *item) 84static void cgit_print_repo_page(struct cacheitem *item)
82{ 85{
83 char *title, *tmp; 86 char *tmp;
84 int show_search; 87 int show_search;
85 unsigned char sha1[20]; 88 unsigned char sha1[20];
86 int nongit = 0; 89 int nongit = 0;
87 90
88 setenv("GIT_DIR", ctx.repo->path, 1); 91 setenv("GIT_DIR", ctx.repo->path, 1);
89 setup_git_directory_gently(&nongit); 92 setup_git_directory_gently(&nongit);
90 if (nongit) { 93 if (nongit) {
91 title = fmt("%s - %s", ctx.cfg.root_title, "config error"); 94 ctx.page.title = fmt("%s - %s", ctx.cfg.root_title,
95 "config error");
92 tmp = fmt("Not a git repository: '%s'", ctx.repo->path); 96 tmp = fmt("Not a git repository: '%s'", ctx.repo->path);
93 ctx.repo = NULL; 97 ctx.repo = NULL;
94 cgit_print_docstart(title, item); 98 cgit_print_http_headers(&ctx);
95 cgit_print_pageheader(title, 0); 99 cgit_print_docstart(&ctx);
100 cgit_print_pageheader(&ctx);
96 cgit_print_error(tmp); 101 cgit_print_error(tmp);
97 cgit_print_docend(); 102 cgit_print_docend();
98 return; 103 return;
99 } 104 }
100 105
101 title = fmt("%s - %s", ctx.repo->name, ctx.repo->desc); 106 ctx.page.title = fmt("%s - %s", ctx.repo->name, ctx.repo->desc);
102 show_search = 0; 107 show_search = 0;
103 108
104 if (!ctx.qry.head) { 109 if (!ctx.qry.head) {
105 ctx.qry.head = xstrdup(find_default_branch(ctx.repo)); 110 ctx.qry.head = xstrdup(find_default_branch(ctx.repo));
106 ctx.repo->defbranch = ctx.qry.head; 111 ctx.repo->defbranch = ctx.qry.head;
107 } 112 }
108 113
109 if (!ctx.qry.head) { 114 if (!ctx.qry.head) {
110 cgit_print_docstart(title, item); 115 cgit_print_http_headers(&ctx);
111 cgit_print_pageheader(title, 0); 116 cgit_print_docstart(&ctx);
117 cgit_print_pageheader(&ctx);
112 cgit_print_error("Repository seems to be empty"); 118 cgit_print_error("Repository seems to be empty");
113 cgit_print_docend(); 119 cgit_print_docend();
114 return; 120 return;
115 } 121 }
116 122
117 if (get_sha1(ctx.qry.head, sha1)) { 123 if (get_sha1(ctx.qry.head, sha1)) {
118 tmp = xstrdup(ctx.qry.head); 124 tmp = xstrdup(ctx.qry.head);
119 ctx.qry.head = ctx.repo->defbranch; 125 ctx.qry.head = ctx.repo->defbranch;
120 cgit_print_docstart(title, item); 126 cgit_print_http_headers(&ctx);
121 cgit_print_pageheader(title, 0); 127 cgit_print_docstart(&ctx);
128 cgit_print_pageheader(&ctx);
122 cgit_print_error(fmt("Invalid branch: %s", tmp)); 129 cgit_print_error(fmt("Invalid branch: %s", tmp));
123 cgit_print_docend(); 130 cgit_print_docend();
124 return; 131 return;
125 } 132 }
126 133
127 if ((cgit_cmd == CMD_SNAPSHOT) && ctx.repo->snapshots) { 134 if ((cgit_cmd == CMD_SNAPSHOT) && ctx.repo->snapshots) {
128 cgit_print_snapshot(item, ctx.qry.head, ctx.qry.sha1, 135 cgit_print_snapshot(item, ctx.qry.head, ctx.qry.sha1,
129 cgit_repobasename(ctx.repo->url), 136 cgit_repobasename(ctx.repo->url),
130 ctx.qry.path, 137 ctx.qry.path,
131 ctx.repo->snapshots ); 138 ctx.repo->snapshots );
132 return; 139 return;
133 } 140 }
134 141
135 if (cgit_cmd == CMD_PATCH) { 142 if (cgit_cmd == CMD_PATCH) {
136 cgit_print_patch(ctx.qry.sha1, item); 143 cgit_print_patch(ctx.qry.sha1, item);
137 return; 144 return;
138 } 145 }
139 146
140 if (cgit_cmd == CMD_BLOB) { 147 if (cgit_cmd == CMD_BLOB) {
141 cgit_print_blob(item, ctx.qry.sha1, ctx.qry.path); 148 cgit_print_blob(item, ctx.qry.sha1, ctx.qry.path);
142 return; 149 return;
143 } 150 }
144 151
145 show_search = (cgit_cmd == CMD_LOG); 152 show_search = (cgit_cmd == CMD_LOG);
146 cgit_print_docstart(title, item); 153 cgit_print_http_headers(&ctx);
154 cgit_print_docstart(&ctx);
147 if (!cgit_cmd) { 155 if (!cgit_cmd) {
148 cgit_print_pageheader("summary", show_search); 156 cgit_print_pageheader(&ctx);
149 cgit_print_summary(); 157 cgit_print_summary();
150 cgit_print_docend(); 158 cgit_print_docend();
151 return; 159 return;
152 } 160 }
153 161
154 cgit_print_pageheader(ctx.qry.page, show_search); 162 cgit_print_pageheader(&ctx);
155 163
156 switch(cgit_cmd) { 164 switch(cgit_cmd) {
157 case CMD_LOG: 165 case CMD_LOG:
158 cgit_print_log(ctx.qry.sha1, ctx.qry.ofs, 166 cgit_print_log(ctx.qry.sha1, ctx.qry.ofs,
159 ctx.cfg.max_commit_count, ctx.qry.grep, ctx.qry.search, 167 ctx.cfg.max_commit_count, ctx.qry.grep, ctx.qry.search,
160 ctx.qry.path, 1); 168 ctx.qry.path, 1);
161 break; 169 break;
162 case CMD_TREE: 170 case CMD_TREE:
163 cgit_print_tree(ctx.qry.sha1, ctx.qry.path); 171 cgit_print_tree(ctx.qry.sha1, ctx.qry.path);
164 break; 172 break;
165 case CMD_COMMIT: 173 case CMD_COMMIT:
166 cgit_print_commit(ctx.qry.sha1); 174 cgit_print_commit(ctx.qry.sha1);
@@ -171,37 +179,45 @@ static void cgit_print_repo_page(struct cacheitem *item)
171 case CMD_TAG: 179 case CMD_TAG:
172 cgit_print_tag(ctx.qry.sha1); 180 cgit_print_tag(ctx.qry.sha1);
173 break; 181 break;
174 case CMD_DIFF: 182 case CMD_DIFF:
175 cgit_print_diff(ctx.qry.sha1, ctx.qry.sha2, ctx.qry.path); 183 cgit_print_diff(ctx.qry.sha1, ctx.qry.sha2, ctx.qry.path);
176 break; 184 break;
177 default: 185 default:
178 cgit_print_error("Invalid request"); 186 cgit_print_error("Invalid request");
179 } 187 }
180 cgit_print_docend(); 188 cgit_print_docend();
181} 189}
182 190
191static long ttl_seconds(long ttl)
192{
193 if (ttl<0)
194 return 60 * 60 * 24 * 365;
195 else
196 return ttl * 60;
197}
198
183static void cgit_fill_cache(struct cacheitem *item, int use_cache) 199static void cgit_fill_cache(struct cacheitem *item, int use_cache)
184{ 200{
185 int stdout2; 201 int stdout2;
186 202
187 item->st.st_mtime = time(NULL);
188
189 if (use_cache) { 203 if (use_cache) {
190 stdout2 = chk_positive(dup(STDOUT_FILENO), 204 stdout2 = chk_positive(dup(STDOUT_FILENO),
191 "Preserving STDOUT"); 205 "Preserving STDOUT");
192 chk_zero(close(STDOUT_FILENO), "Closing STDOUT"); 206 chk_zero(close(STDOUT_FILENO), "Closing STDOUT");
193 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)"); 207 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)");
194 } 208 }
195 209
210 ctx.page.modified = time(NULL);
211 ctx.page.expires = ctx.page.modified + ttl_seconds(item->ttl);
196 if (ctx.repo) 212 if (ctx.repo)
197 cgit_print_repo_page(item); 213 cgit_print_repo_page(item);
198 else 214 else
199 cgit_print_repolist(item); 215 cgit_print_repolist(item);
200 216
201 if (use_cache) { 217 if (use_cache) {
202 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT"); 218 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT");
203 chk_positive(dup2(stdout2, STDOUT_FILENO), 219 chk_positive(dup2(stdout2, STDOUT_FILENO),
204 "Restoring original STDOUT"); 220 "Restoring original STDOUT");
205 chk_zero(close(stdout2), "Closing temporary STDOUT"); 221 chk_zero(close(stdout2), "Closing temporary STDOUT");
206 } 222 }
207} 223}