summaryrefslogtreecommitdiffabout
path: root/cgit.c
Side-by-side diff
Diffstat (limited to 'cgit.c') (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/cgit.c b/cgit.c
index e1d2216..96900bb 100644
--- a/cgit.c
+++ b/cgit.c
@@ -485,257 +485,257 @@ int cmp_repos(const void *a, const void *b)
{
const struct cgit_repo *ra = a, *rb = b;
return strcmp(ra->url, rb->url);
}
char *build_snapshot_setting(int bitmap)
{
const struct cgit_snapshot_format *f;
char *result = xstrdup("");
char *tmp;
int len;
for (f = cgit_snapshot_formats; f->suffix; f++) {
if (f->bit & bitmap) {
tmp = result;
result = xstrdup(fmt("%s%s ", tmp, f->suffix));
free(tmp);
}
}
len = strlen(result);
if (len)
result[len - 1] = '\0';
return result;
}
char *get_first_line(char *txt)
{
char *t = xstrdup(txt);
char *p = strchr(t, '\n');
if (p)
*p = '\0';
return t;
}
void print_repo(FILE *f, struct cgit_repo *repo)
{
fprintf(f, "repo.url=%s\n", repo->url);
fprintf(f, "repo.name=%s\n", repo->name);
fprintf(f, "repo.path=%s\n", repo->path);
if (repo->owner)
fprintf(f, "repo.owner=%s\n", repo->owner);
if (repo->desc) {
char *tmp = get_first_line(repo->desc);
fprintf(f, "repo.desc=%s\n", tmp);
free(tmp);
}
if (repo->readme)
fprintf(f, "repo.readme=%s\n", repo->readme);
if (repo->defbranch)
fprintf(f, "repo.defbranch=%s\n", repo->defbranch);
if (repo->module_link)
fprintf(f, "repo.module-link=%s\n", repo->module_link);
if (repo->section)
fprintf(f, "repo.section=%s\n", repo->section);
if (repo->clone_url)
fprintf(f, "repo.clone-url=%s\n", repo->clone_url);
fprintf(f, "repo.enable-log-filecount=%d\n",
repo->enable_log_filecount);
fprintf(f, "repo.enable-log-linecount=%d\n",
repo->enable_log_linecount);
if (repo->about_filter && repo->about_filter != ctx.cfg.about_filter)
fprintf(f, "repo.about-filter=%s\n", repo->about_filter->cmd);
if (repo->commit_filter && repo->commit_filter != ctx.cfg.commit_filter)
fprintf(f, "repo.commit-filter=%s\n", repo->commit_filter->cmd);
if (repo->source_filter && repo->source_filter != ctx.cfg.source_filter)
fprintf(f, "repo.source-filter=%s\n", repo->source_filter->cmd);
if (repo->snapshots != ctx.cfg.snapshots) {
char *tmp = build_snapshot_setting(repo->snapshots);
fprintf(f, "repo.snapshots=%s\n", tmp);
free(tmp);
}
if (repo->max_stats != ctx.cfg.max_stats)
fprintf(f, "repo.max-stats=%s\n",
cgit_find_stats_periodname(repo->max_stats));
fprintf(f, "\n");
}
void print_repolist(FILE *f, struct cgit_repolist *list, int start)
{
int i;
for(i = start; i < list->count; i++)
print_repo(f, &list->repos[i]);
}
/* Scan 'path' for git repositories, save the resulting repolist in 'cached_rc'
* and return 0 on success.
*/
static int generate_cached_repolist(const char *path, const char *cached_rc)
{
char *locked_rc;
int idx;
FILE *f;
locked_rc = xstrdup(fmt("%s.lock", cached_rc));
f = fopen(locked_rc, "wx");
if (!f) {
/* Inform about the error unless the lockfile already existed,
* since that only means we've got concurrent requests.
*/
if (errno != EEXIST)
fprintf(stderr, "[cgit] Error opening %s: %s (%d)\n",
locked_rc, strerror(errno), errno);
return errno;
}
idx = cgit_repolist.count;
if (ctx.cfg.project_list)
scan_projects(path, ctx.cfg.project_list, repo_config);
else
scan_tree(path, repo_config);
print_repolist(f, &cgit_repolist, idx);
if (rename(locked_rc, cached_rc))
fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n",
locked_rc, cached_rc, strerror(errno), errno);
fclose(f);
return 0;
}
static void process_cached_repolist(const char *path)
{
struct stat st;
char *cached_rc;
time_t age;
unsigned long hash;
hash = hash_str(path);
if (ctx.cfg.project_list)
hash += hash_str(ctx.cfg.project_list);
- cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root, hash));
+ cached_rc = xstrdup(fmt("%s/rc-%8lx", ctx.cfg.cache_root, hash));
if (stat(cached_rc, &st)) {
/* Nothing is cached, we need to scan without forking. And
* if we fail to generate a cached repolist, we need to
* invoke scan_tree manually.
*/
if (generate_cached_repolist(path, cached_rc)) {
if (ctx.cfg.project_list)
scan_projects(path, ctx.cfg.project_list,
repo_config);
else
scan_tree(path, repo_config);
}
return;
}
parse_configfile(cached_rc, config_cb);
/* If the cached configfile hasn't expired, lets exit now */
age = time(NULL) - st.st_mtime;
if (age <= (ctx.cfg.cache_scanrc_ttl * 60))
return;
/* The cached repolist has been parsed, but it was old. So lets
* rescan the specified path and generate a new cached repolist
* in a child-process to avoid latency for the current request.
*/
if (fork())
return;
exit(generate_cached_repolist(path, cached_rc));
}
static void cgit_parse_args(int argc, const char **argv)
{
int i;
int scan = 0;
for (i = 1; i < argc; i++) {
if (!strncmp(argv[i], "--cache=", 8)) {
ctx.cfg.cache_root = xstrdup(argv[i]+8);
}
if (!strcmp(argv[i], "--nocache")) {
ctx.cfg.nocache = 1;
}
if (!strcmp(argv[i], "--nohttp")) {
ctx.env.no_http = "1";
}
if (!strncmp(argv[i], "--query=", 8)) {
ctx.qry.raw = xstrdup(argv[i]+8);
}
if (!strncmp(argv[i], "--repo=", 7)) {
ctx.qry.repo = xstrdup(argv[i]+7);
}
if (!strncmp(argv[i], "--page=", 7)) {
ctx.qry.page = xstrdup(argv[i]+7);
}
if (!strncmp(argv[i], "--head=", 7)) {
ctx.qry.head = xstrdup(argv[i]+7);
ctx.qry.has_symref = 1;
}
if (!strncmp(argv[i], "--sha1=", 7)) {
ctx.qry.sha1 = xstrdup(argv[i]+7);
ctx.qry.has_sha1 = 1;
}
if (!strncmp(argv[i], "--ofs=", 6)) {
ctx.qry.ofs = atoi(argv[i]+6);
}
if (!strncmp(argv[i], "--scan-tree=", 12) ||
!strncmp(argv[i], "--scan-path=", 12)) {
/* HACK: the global snapshot bitmask defines the
* set of allowed snapshot formats, but the config
* file hasn't been parsed yet so the mask is
* currently 0. By setting all bits high before
* scanning we make sure that any in-repo cgitrc
* snapshot setting is respected by scan_tree().
* BTW: we assume that there'll never be more than
* 255 different snapshot formats supported by cgit...
*/
ctx.cfg.snapshots = 0xFF;
scan++;
scan_tree(argv[i] + 12, repo_config);
}
}
if (scan) {
qsort(cgit_repolist.repos, cgit_repolist.count,
sizeof(struct cgit_repo), cmp_repos);
print_repolist(stdout, &cgit_repolist, 0);
exit(0);
}
}
static int calc_ttl()
{
if (!ctx.repo)
return ctx.cfg.cache_root_ttl;
if (!ctx.qry.page)
return ctx.cfg.cache_repo_ttl;
if (ctx.qry.has_symref)
return ctx.cfg.cache_dynamic_ttl;
if (ctx.qry.has_sha1)
return ctx.cfg.cache_static_ttl;
return ctx.cfg.cache_repo_ttl;
}
int main(int argc, const char **argv)
{
const char *path;
char *qry;
int err, ttl;
prepare_context(&ctx);
cgit_repolist.length = 0;
cgit_repolist.count = 0;
cgit_repolist.repos = NULL;
cgit_parse_args(argc, argv);
parse_configfile(expand_macros(ctx.env.cgit_config), config_cb);
ctx.repo = NULL;
http_parse_querystring(ctx.qry.raw, querystring_cb);
/* If virtual-root isn't specified in cgitrc, lets pretend
* that virtual-root equals SCRIPT_NAME.
*/