summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c27
-rw-r--r--cgit.h1
-rw-r--r--cgitrc.5.txt10
-rw-r--r--scan-tree.c37
-rw-r--r--scan-tree.h3
5 files changed, 70 insertions, 8 deletions
diff --git a/cgit.c b/cgit.c
index c263872..2364d1c 100644
--- a/cgit.c
+++ b/cgit.c
@@ -178,15 +178,20 @@ void config_cb(const char *name, const char *value)
178 else if (!strcmp(name, "max-blob-size")) 178 else if (!strcmp(name, "max-blob-size"))
179 ctx.cfg.max_blob_size = atoi(value); 179 ctx.cfg.max_blob_size = atoi(value);
180 else if (!strcmp(name, "max-repo-count")) 180 else if (!strcmp(name, "max-repo-count"))
181 ctx.cfg.max_repo_count = atoi(value); 181 ctx.cfg.max_repo_count = atoi(value);
182 else if (!strcmp(name, "max-commit-count")) 182 else if (!strcmp(name, "max-commit-count"))
183 ctx.cfg.max_commit_count = atoi(value); 183 ctx.cfg.max_commit_count = atoi(value);
184 else if (!strcmp(name, "project-list"))
185 ctx.cfg.project_list = xstrdup(expand_macros(value));
184 else if (!strcmp(name, "scan-path")) 186 else if (!strcmp(name, "scan-path"))
185 if (!ctx.cfg.nocache && ctx.cfg.cache_size) 187 if (!ctx.cfg.nocache && ctx.cfg.cache_size)
186 process_cached_repolist(expand_macros(value)); 188 process_cached_repolist(expand_macros(value));
189 else if (ctx.cfg.project_list)
190 scan_projects(expand_macros(value),
191 ctx.cfg.project_list, repo_config);
187 else 192 else
188 scan_tree(expand_macros(value), repo_config); 193 scan_tree(expand_macros(value), repo_config);
189 else if (!strcmp(name, "source-filter")) 194 else if (!strcmp(name, "source-filter"))
190 ctx.cfg.source_filter = new_filter(value, 1); 195 ctx.cfg.source_filter = new_filter(value, 1);
191 else if (!strcmp(name, "summary-log")) 196 else if (!strcmp(name, "summary-log"))
192 ctx.cfg.summary_log = atoi(value); 197 ctx.cfg.summary_log = atoi(value);
@@ -292,12 +297,13 @@ static void prepare_context(struct cgit_context *ctx)
292 ctx->cfg.max_lock_attempts = 5; 297 ctx->cfg.max_lock_attempts = 5;
293 ctx->cfg.max_msg_len = 80; 298 ctx->cfg.max_msg_len = 80;
294 ctx->cfg.max_repodesc_len = 80; 299 ctx->cfg.max_repodesc_len = 80;
295 ctx->cfg.max_blob_size = 0; 300 ctx->cfg.max_blob_size = 0;
296 ctx->cfg.max_stats = 0; 301 ctx->cfg.max_stats = 0;
297 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s"; 302 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s";
303 ctx->cfg.project_list = NULL;
298 ctx->cfg.renamelimit = -1; 304 ctx->cfg.renamelimit = -1;
299 ctx->cfg.robots = "index, nofollow"; 305 ctx->cfg.robots = "index, nofollow";
300 ctx->cfg.root_title = "Git repository browser"; 306 ctx->cfg.root_title = "Git repository browser";
301 ctx->cfg.root_desc = "a fast webinterface for the git dscm"; 307 ctx->cfg.root_desc = "a fast webinterface for the git dscm";
302 ctx->cfg.script_name = CGIT_SCRIPT_NAME; 308 ctx->cfg.script_name = CGIT_SCRIPT_NAME;
303 ctx->cfg.section = ""; 309 ctx->cfg.section = "";
@@ -571,13 +577,16 @@ static int generate_cached_repolist(const char *path, const char *cached_rc)
571 if (errno != EEXIST) 577 if (errno != EEXIST)
572 fprintf(stderr, "[cgit] Error opening %s: %s (%d)\n", 578 fprintf(stderr, "[cgit] Error opening %s: %s (%d)\n",
573 locked_rc, strerror(errno), errno); 579 locked_rc, strerror(errno), errno);
574 return errno; 580 return errno;
575 } 581 }
576 idx = cgit_repolist.count; 582 idx = cgit_repolist.count;
577 scan_tree(path, repo_config); 583 if (ctx.cfg.project_list)
584 scan_projects(path, ctx.cfg.project_list, repo_config);
585 else
586 scan_tree(path, repo_config);
578 print_repolist(f, &cgit_repolist, idx); 587 print_repolist(f, &cgit_repolist, idx);
579 if (rename(locked_rc, cached_rc)) 588 if (rename(locked_rc, cached_rc))
580 fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n", 589 fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n",
581 locked_rc, cached_rc, strerror(errno), errno); 590 locked_rc, cached_rc, strerror(errno), errno);
582 fclose(f); 591 fclose(f);
583 return 0; 592 return 0;
@@ -585,23 +594,31 @@ static int generate_cached_repolist(const char *path, const char *cached_rc)
585 594
586static void process_cached_repolist(const char *path) 595static void process_cached_repolist(const char *path)
587{ 596{
588 struct stat st; 597 struct stat st;
589 char *cached_rc; 598 char *cached_rc;
590 time_t age; 599 time_t age;
600 unsigned long hash;
591 601
592 cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root, 602 hash = hash_str(path);
593 hash_str(path))); 603 if (ctx.cfg.project_list)
604 hash += hash_str(ctx.cfg.project_list);
605 cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root, hash));
594 606
595 if (stat(cached_rc, &st)) { 607 if (stat(cached_rc, &st)) {
596 /* Nothing is cached, we need to scan without forking. And 608 /* Nothing is cached, we need to scan without forking. And
597 * if we fail to generate a cached repolist, we need to 609 * if we fail to generate a cached repolist, we need to
598 * invoke scan_tree manually. 610 * invoke scan_tree manually.
599 */ 611 */
600 if (generate_cached_repolist(path, cached_rc)) 612 if (generate_cached_repolist(path, cached_rc)) {
601 scan_tree(path, repo_config); 613 if (ctx.cfg.project_list)
614 scan_projects(path, ctx.cfg.project_list,
615 repo_config);
616 else
617 scan_tree(path, repo_config);
618 }
602 return; 619 return;
603 } 620 }
604 621
605 parse_configfile(cached_rc, config_cb); 622 parse_configfile(cached_rc, config_cb);
606 623
607 /* If the cached configfile hasn't expired, lets exit now */ 624 /* If the cached configfile hasn't expired, lets exit now */
diff --git a/cgit.h b/cgit.h
index e9e2718..4591f8c 100644
--- a/cgit.h
+++ b/cgit.h
@@ -163,12 +163,13 @@ struct cgit_config {
163 char *header; 163 char *header;
164 char *index_header; 164 char *index_header;
165 char *index_info; 165 char *index_info;
166 char *logo; 166 char *logo;
167 char *logo_link; 167 char *logo_link;
168 char *module_link; 168 char *module_link;
169 char *project_list;
169 char *robots; 170 char *robots;
170 char *root_title; 171 char *root_title;
171 char *root_desc; 172 char *root_desc;
172 char *root_readme; 173 char *root_readme;
173 char *script_name; 174 char *script_name;
174 char *section; 175 char *section;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index a853522..ec004d4 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -221,12 +221,17 @@ noplainemail::
221 Default value: "0". 221 Default value: "0".
222 222
223noheader:: 223noheader::
224 Flag which, when set to "1", will make cgit omit the standard header 224 Flag which, when set to "1", will make cgit omit the standard header
225 on all pages. Default value: none. See also: "embedded". 225 on all pages. Default value: none. See also: "embedded".
226 226
227project-list::
228 A list of subdirectories inside of scan-path, relative to it, that
229 should loaded as git repositories. This must be defined prior to
230 scan-path. Default value: none. See also: scan-path.
231
227renamelimit:: 232renamelimit::
228 Maximum number of files to consider when detecting renames. The value 233 Maximum number of files to consider when detecting renames. The value
229 "-1" uses the compiletime value in git (for further info, look at 234 "-1" uses the compiletime value in git (for further info, look at
230 `man git-diff`). Default value: "-1". 235 `man git-diff`). Default value: "-1".
231 236
232repo.group:: 237repo.group::
@@ -250,13 +255,16 @@ root-title::
250 Text printed as heading on the repository index page. Default value: 255 Text printed as heading on the repository index page. Default value:
251 "Git Repository Browser". 256 "Git Repository Browser".
252 257
253scan-path:: 258scan-path::
254 A path which will be scanned for repositories. If caching is enabled, 259 A path which will be scanned for repositories. If caching is enabled,
255 the result will be cached as a cgitrc include-file in the cache 260 the result will be cached as a cgitrc include-file in the cache
256 directory. Default value: none. See also: cache-scanrc-ttl. 261 directory. If project-list has been defined prior to scan-path,
262 scan-path loads only the directories listed in the file pointed to by
263 project-list. Default value: none. See also: cache-scanrc-ttl,
264 project-list.
257 265
258section:: 266section::
259 The name of the current repository section - all repositories defined 267 The name of the current repository section - all repositories defined
260 after this option will inherit the current section name. Default value: 268 after this option will inherit the current section name. Default value:
261 none. 269 none.
262 270
diff --git a/scan-tree.c b/scan-tree.c
index 1e18f3c..9bf9b38 100644
--- a/scan-tree.c
+++ b/scan-tree.c
@@ -1,6 +1,15 @@
1/* scan-tree.c
2 *
3 * Copyright (C) 2008-2009 Lars Hjemli
4 * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com>
5 *
6 * Licensed under GNU General Public License v2
7 * (see COPYING for full license text)
8 */
9
1#include "cgit.h" 10#include "cgit.h"
2#include "configfile.h" 11#include "configfile.h"
3#include "html.h" 12#include "html.h"
4 13
5#define MAX_PATH 4096 14#define MAX_PATH 4096
6 15
@@ -139,10 +148,38 @@ static void scan_path(const char *base, const char *path, repo_config_fn fn)
139 scan_path(base, buf, fn); 148 scan_path(base, buf, fn);
140 free(buf); 149 free(buf);
141 } 150 }
142 closedir(dir); 151 closedir(dir);
143} 152}
144 153
154#define lastc(s) s[strlen(s) - 1]
155
156void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn)
157{
158 char line[MAX_PATH * 2], *z;
159 FILE *projects;
160 int err;
161
162 projects = fopen(projectsfile, "r");
163 if (!projects) {
164 fprintf(stderr, "Error opening projectsfile %s: %s (%d)\n",
165 projectsfile, strerror(errno), errno);
166 }
167 while (fgets(line, sizeof(line), projects) != NULL) {
168 for (z = &lastc(line);
169 strlen(line) && strchr("\n\r", *z);
170 z = &lastc(line))
171 *z = '\0';
172 if (strlen(line))
173 scan_path(path, fmt("%s/%s", path, line), fn);
174 }
175 if ((err = ferror(projects))) {
176 fprintf(stderr, "Error reading from projectsfile %s: %s (%d)\n",
177 projectsfile, strerror(err), err);
178 }
179 fclose(projects);
180}
181
145void scan_tree(const char *path, repo_config_fn fn) 182void scan_tree(const char *path, repo_config_fn fn)
146{ 183{
147 scan_path(path, path, fn); 184 scan_path(path, path, fn);
148} 185}
diff --git a/scan-tree.h b/scan-tree.h
index 11539f4..1afbd4b 100644
--- a/scan-tree.h
+++ b/scan-tree.h
@@ -1,3 +1,2 @@
1 1extern void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn);
2
3extern void scan_tree(const char *path, repo_config_fn fn); 2extern void scan_tree(const char *path, repo_config_fn fn);