summaryrefslogtreecommitdiffabout
path: root/cgit.c
Unidiff
Diffstat (limited to 'cgit.c') (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c117
1 files changed, 102 insertions, 15 deletions
diff --git a/cgit.c b/cgit.c
index 4c14f77..09c857c 100644
--- a/cgit.c
+++ b/cgit.c
@@ -12,4 +12,5 @@ static const char cgit_lib_error[] =
12 12
13int htmlfd = 0;
13 14
14char *cgit_root = "/var/git"; 15char *cgit_root = "/usr/src/git";
15char *cgit_root_title = "Git repository browser"; 16char *cgit_root_title = "Git repository browser";
@@ -20,2 +21,10 @@ char *cgit_virtual_root = NULL;
20 21
22char *cgit_cache_root = "/var/cache/cgit";
23
24int cgit_cache_root_ttl = 5;
25int cgit_cache_repo_ttl = 5;
26int cgit_cache_dynamic_ttl = 5;
27int cgit_cache_static_ttl = -1;
28int cgit_cache_max_create_time = 5;
29
21char *cgit_repo_name = NULL; 30char *cgit_repo_name = NULL;
@@ -24,2 +33,6 @@ char *cgit_repo_owner = NULL;
24 33
34int cgit_query_has_symref = 0;
35int cgit_query_has_sha1 = 0;
36
37char *cgit_querystring = NULL;
25char *cgit_query_repo = NULL; 38char *cgit_query_repo = NULL;
@@ -27,2 +40,5 @@ char *cgit_query_page = NULL;
27char *cgit_query_head = NULL; 40char *cgit_query_head = NULL;
41char *cgit_query_sha1 = NULL;
42
43struct cacheitem cacheitem;
28 44
@@ -30,3 +46,3 @@ int cgit_parse_query(char *txt, configfn fn)
30{ 46{
31 char *t = txt, *value = NULL, c; 47 char *t, *value = NULL, c;
32 48
@@ -35,2 +51,4 @@ int cgit_parse_query(char *txt, configfn fn)
35 51
52 t = txt = xstrdup(txt);
53
36 while((c=*t) != '\0') { 54 while((c=*t) != '\0') {
@@ -84,4 +102,9 @@ void cgit_querystring_cb(const char *name, const char *value)
84 cgit_query_page = xstrdup(value); 102 cgit_query_page = xstrdup(value);
85 else if (!strcmp(name, "h")) 103 else if (!strcmp(name, "h")) {
86 cgit_query_head = xstrdup(value); 104 cgit_query_head = xstrdup(value);
105 cgit_query_has_symref = 1;
106 } else if (!strcmp(name, "id")) {
107 cgit_query_sha1 = xstrdup(value);
108 cgit_query_has_sha1 = 1;
109 }
87} 110}
@@ -138,2 +161,22 @@ static int cgit_print_branch_cb(const char *refname, const unsigned char *sha1,
138 161
162/* Sun, 06 Nov 1994 08:49:37 GMT */
163static char *http_date(time_t t)
164{
165 static char day[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
166 static char month[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
167 "Jul", "Aug", "Sep", "Oct", "Now", "Dec"};
168 struct tm *tm = gmtime(&t);
169 return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday],
170 tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year,
171 tm->tm_hour, tm->tm_min, tm->tm_sec);
172}
173
174static int ttl_seconds(int ttl)
175{
176 if (ttl<0)
177 return 60 * 60 * 24 * 365;
178 else
179 return ttl * 60;
180}
181
139static void cgit_print_docstart(char *title) 182static void cgit_print_docstart(char *title)
@@ -141,2 +184,5 @@ static void cgit_print_docstart(char *title)
141 html("Content-Type: text/html; charset=utf-8\n"); 184 html("Content-Type: text/html; charset=utf-8\n");
185 htmlf("Last-Modified: %s\n", http_date(cacheitem.st.st_mtime));
186 htmlf("Expires: %s\n", http_date(cacheitem.st.st_mtime +
187 ttl_seconds(cacheitem.ttl)));
142 html("\n"); 188 html("\n");
@@ -177,2 +223,3 @@ static void cgit_print_repolist()
177 223
224 chdir(cgit_root);
178 cgit_print_docstart(cgit_root_title); 225 cgit_print_docstart(cgit_root_title);
@@ -199,3 +246,3 @@ static void cgit_print_repolist()
199 cgit_repo_name = cgit_repo_desc = cgit_repo_owner = NULL; 246 cgit_repo_name = cgit_repo_desc = cgit_repo_owner = NULL;
200 name = fmt("%s/.git/info/cgit", de->d_name); 247 name = fmt("%s/info/cgit", de->d_name);
201 if (cgit_read_config(name, cgit_repo_config_cb)) 248 if (cgit_read_config(name, cgit_repo_config_cb))
@@ -293,3 +340,3 @@ static void cgit_print_commit_shortlog(struct commit *commit)
293 html("</td><td>"); 340 html("</td><td>");
294 char *qry = fmt("h=%s", sha1_to_hex(commit->object.sha1)); 341 char *qry = fmt("id=%s", sha1_to_hex(commit->object.sha1));
295 char *url = cgit_pageurl(cgit_query_repo, "view", qry); 342 char *url = cgit_pageurl(cgit_query_repo, "view", qry);
@@ -373,4 +420,4 @@ static void cgit_print_repo_page()
373{ 420{
374 if (chdir(cgit_query_repo) || 421 if (chdir(fmt("%s/%s", cgit_root, cgit_query_repo)) ||
375 cgit_read_config(".git/info/cgit", cgit_repo_config_cb)) { 422 cgit_read_config("info/cgit", cgit_repo_config_cb)) {
376 char *title = fmt("%s - %s", cgit_root_title, "Bad request"); 423 char *title = fmt("%s - %s", cgit_root_title, "Bad request");
@@ -383,3 +430,3 @@ static void cgit_print_repo_page()
383 } 430 }
384 431 setenv("GIT_DIR", fmt("%s/%s", cgit_root, cgit_query_repo), 1);
385 char *title = fmt("%s - %s", cgit_repo_name, cgit_repo_desc); 432 char *title = fmt("%s - %s", cgit_repo_name, cgit_repo_desc);
@@ -392,3 +439,3 @@ static void cgit_print_repo_page()
392 } else if (!strcmp(cgit_query_page, "view")) { 439 } else if (!strcmp(cgit_query_page, "view")) {
393 cgit_print_object(cgit_query_head); 440 cgit_print_object(cgit_query_sha1);
394 } 441 }
@@ -397,9 +444,6 @@ static void cgit_print_repo_page()
397 444
398int main(int argc, const char **argv) 445static void cgit_fill_cache(struct cacheitem *item)
399{ 446{
400 if (cgit_read_config("/etc/cgitrc", cgit_global_config_cb)) 447 htmlfd = item->fd;
401 die("Error reading config: %d %s", errno, strerror(errno)); 448 item->st.st_mtime = time(NULL);
402
403 chdir(cgit_root);
404 cgit_parse_query(getenv("QUERY_STRING"), cgit_querystring_cb);
405 if (cgit_query_repo) 449 if (cgit_query_repo)
@@ -408,2 +452,45 @@ int main(int argc, const char **argv)
408 cgit_print_repolist(); 452 cgit_print_repolist();
453}
454
455static void cgit_refresh_cache(struct cacheitem *item)
456{
457 top:
458 if (!cache_lookup(item)) {
459 if (cache_lock(item)) {
460 cgit_fill_cache(item);
461 cache_unlock(item);
462 } else {
463 sched_yield();
464 goto top;
465 }
466 } else if (cache_expired(item)) {
467 if (cache_lock(item)) {
468 cgit_fill_cache(item);
469 cache_unlock(item);
470 }
471 }
472}
473
474static void cgit_print_cache(struct cacheitem *item)
475{
476 static char buf[4096];
477 ssize_t i;
478
479 int fd = open(item->name, O_RDONLY);
480 if (fd<0)
481 die("Unable to open cached file %s", item->name);
482
483 while((i=read(fd, buf, sizeof(buf))) > 0)
484 write(STDOUT_FILENO, buf, i);
485
486 close(fd);
487}
488
489int main(int argc, const char **argv)
490{
491 cgit_read_config("/etc/cgitrc", cgit_global_config_cb);
492 cgit_querystring = xstrdup(getenv("QUERY_STRING"));
493 cgit_parse_query(cgit_querystring, cgit_querystring_cb);
494 cgit_refresh_cache(&cacheitem);
495 cgit_print_cache(&cacheitem);
409 return 0; 496 return 0;