aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Lars Hjemli <hjemli@gmail.com>2010-08-04 10:10:29 (JST)
committerGravatar Lars Hjemli <hjemli@gmail.com>2010-08-04 10:10:29 (JST)
commitaec9c245e7eaf444c7ae1851e3eda3b30748950f (patch)
tree04d5e945781441f2589ae8eb44bee8d5a2b17c2b
parente6c960c7c0f0d2e54b51cc43ef190df3ce52755e (diff)
parent119397b175874bd606952e93b7249ae4ffb9afbe (diff)
downloadcgit-aec9c245e7eaf444c7ae1851e3eda3b30748950f.zip
cgit-aec9c245e7eaf444c7ae1851e3eda3b30748950f.tar.gz
Merge branch 'jd/gitolite'
-rw-r--r--cgit.c33
-rw-r--r--cgit.h3
-rw-r--r--cgitrc.5.txt21
-rw-r--r--scan-tree.c73
-rw-r--r--scan-tree.h3
5 files changed, 116 insertions, 17 deletions
diff --git a/cgit.c b/cgit.c
index c263872..eff5b7a 100644
--- a/cgit.c
+++ b/cgit.c
@@ -135,6 +135,8 @@ void config_cb(const char *name, const char *value)
135 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); 135 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);
136 else if (!strcmp(name, "enable-filter-overrides")) 136 else if (!strcmp(name, "enable-filter-overrides"))
137 ctx.cfg.enable_filter_overrides = atoi(value); 137 ctx.cfg.enable_filter_overrides = atoi(value);
138 else if (!strcmp(name, "enable-gitweb-owner"))
139 ctx.cfg.enable_gitweb_owner = atoi(value);
138 else if (!strcmp(name, "enable-index-links")) 140 else if (!strcmp(name, "enable-index-links"))
139 ctx.cfg.enable_index_links = atoi(value); 141 ctx.cfg.enable_index_links = atoi(value);
140 else if (!strcmp(name, "enable-log-filecount")) 142 else if (!strcmp(name, "enable-log-filecount"))
@@ -181,9 +183,14 @@ void config_cb(const char *name, const char *value)
181 ctx.cfg.max_repo_count = atoi(value); 183 ctx.cfg.max_repo_count = atoi(value);
182 else if (!strcmp(name, "max-commit-count")) 184 else if (!strcmp(name, "max-commit-count"))
183 ctx.cfg.max_commit_count = atoi(value); 185 ctx.cfg.max_commit_count = atoi(value);
186 else if (!strcmp(name, "project-list"))
187 ctx.cfg.project_list = xstrdup(expand_macros(value));
184 else if (!strcmp(name, "scan-path")) 188 else if (!strcmp(name, "scan-path"))
185 if (!ctx.cfg.nocache && ctx.cfg.cache_size) 189 if (!ctx.cfg.nocache && ctx.cfg.cache_size)
186 process_cached_repolist(expand_macros(value)); 190 process_cached_repolist(expand_macros(value));
191 else if (ctx.cfg.project_list)
192 scan_projects(expand_macros(value),
193 ctx.cfg.project_list, repo_config);
187 else 194 else
188 scan_tree(expand_macros(value), repo_config); 195 scan_tree(expand_macros(value), repo_config);
189 else if (!strcmp(name, "source-filter")) 196 else if (!strcmp(name, "source-filter"))
@@ -200,6 +207,8 @@ void config_cb(const char *name, const char *value)
200 ctx.cfg.agefile = xstrdup(value); 207 ctx.cfg.agefile = xstrdup(value);
201 else if (!strcmp(name, "renamelimit")) 208 else if (!strcmp(name, "renamelimit"))
202 ctx.cfg.renamelimit = atoi(value); 209 ctx.cfg.renamelimit = atoi(value);
210 else if (!strcmp(name, "remove-suffix"))
211 ctx.cfg.remove_suffix = atoi(value);
203 else if (!strcmp(name, "robots")) 212 else if (!strcmp(name, "robots"))
204 ctx.cfg.robots = xstrdup(value); 213 ctx.cfg.robots = xstrdup(value);
205 else if (!strcmp(name, "clone-prefix")) 214 else if (!strcmp(name, "clone-prefix"))
@@ -286,6 +295,7 @@ static void prepare_context(struct cgit_context *ctx)
286 ctx->cfg.css = "/cgit.css"; 295 ctx->cfg.css = "/cgit.css";
287 ctx->cfg.logo = "/cgit.png"; 296 ctx->cfg.logo = "/cgit.png";
288 ctx->cfg.local_time = 0; 297 ctx->cfg.local_time = 0;
298 ctx->cfg.enable_gitweb_owner = 1;
289 ctx->cfg.enable_tree_linenumbers = 1; 299 ctx->cfg.enable_tree_linenumbers = 1;
290 ctx->cfg.max_repo_count = 50; 300 ctx->cfg.max_repo_count = 50;
291 ctx->cfg.max_commit_count = 50; 301 ctx->cfg.max_commit_count = 50;
@@ -295,7 +305,9 @@ static void prepare_context(struct cgit_context *ctx)
295 ctx->cfg.max_blob_size = 0; 305 ctx->cfg.max_blob_size = 0;
296 ctx->cfg.max_stats = 0; 306 ctx->cfg.max_stats = 0;
297 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s"; 307 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s";
308 ctx->cfg.project_list = NULL;
298 ctx->cfg.renamelimit = -1; 309 ctx->cfg.renamelimit = -1;
310 ctx->cfg.remove_suffix = 0;
299 ctx->cfg.robots = "index, nofollow"; 311 ctx->cfg.robots = "index, nofollow";
300 ctx->cfg.root_title = "Git repository browser"; 312 ctx->cfg.root_title = "Git repository browser";
301 ctx->cfg.root_desc = "a fast webinterface for the git dscm"; 313 ctx->cfg.root_desc = "a fast webinterface for the git dscm";
@@ -574,7 +586,10 @@ static int generate_cached_repolist(const char *path, const char *cached_rc)
574 return errno; 586 return errno;
575 } 587 }
576 idx = cgit_repolist.count; 588 idx = cgit_repolist.count;
577 scan_tree(path, repo_config); 589 if (ctx.cfg.project_list)
590 scan_projects(path, ctx.cfg.project_list, repo_config);
591 else
592 scan_tree(path, repo_config);
578 print_repolist(f, &cgit_repolist, idx); 593 print_repolist(f, &cgit_repolist, idx);
579 if (rename(locked_rc, cached_rc)) 594 if (rename(locked_rc, cached_rc))
580 fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n", 595 fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n",
@@ -588,17 +603,25 @@ static void process_cached_repolist(const char *path)
588 struct stat st; 603 struct stat st;
589 char *cached_rc; 604 char *cached_rc;
590 time_t age; 605 time_t age;
606 unsigned long hash;
591 607
592 cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root, 608 hash = hash_str(path);
593 hash_str(path))); 609 if (ctx.cfg.project_list)
610 hash += hash_str(ctx.cfg.project_list);
611 cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root, hash));
594 612
595 if (stat(cached_rc, &st)) { 613 if (stat(cached_rc, &st)) {
596 /* Nothing is cached, we need to scan without forking. And 614 /* Nothing is cached, we need to scan without forking. And
597 * if we fail to generate a cached repolist, we need to 615 * if we fail to generate a cached repolist, we need to
598 * invoke scan_tree manually. 616 * invoke scan_tree manually.
599 */ 617 */
600 if (generate_cached_repolist(path, cached_rc)) 618 if (generate_cached_repolist(path, cached_rc)) {
601 scan_tree(path, repo_config); 619 if (ctx.cfg.project_list)
620 scan_projects(path, ctx.cfg.project_list,
621 repo_config);
622 else
623 scan_tree(path, repo_config);
624 }
602 return; 625 return;
603 } 626 }
604 627
diff --git a/cgit.h b/cgit.h
index 32d9d2b..4090cd4 100644
--- a/cgit.h
+++ b/cgit.h
@@ -167,6 +167,7 @@ struct cgit_config {
167 char *logo; 167 char *logo;
168 char *logo_link; 168 char *logo_link;
169 char *module_link; 169 char *module_link;
170 char *project_list;
170 char *robots; 171 char *robots;
171 char *root_title; 172 char *root_title;
172 char *root_desc; 173 char *root_desc;
@@ -183,6 +184,7 @@ struct cgit_config {
183 int cache_static_ttl; 184 int cache_static_ttl;
184 int embedded; 185 int embedded;
185 int enable_filter_overrides; 186 int enable_filter_overrides;
187 int enable_gitweb_owner;
186 int enable_index_links; 188 int enable_index_links;
187 int enable_log_filecount; 189 int enable_log_filecount;
188 int enable_log_linecount; 190 int enable_log_linecount;
@@ -202,6 +204,7 @@ struct cgit_config {
202 int noplainemail; 204 int noplainemail;
203 int noheader; 205 int noheader;
204 int renamelimit; 206 int renamelimit;
207 int remove_suffix;
205 int snapshots; 208 int snapshots;
206 int summary_branches; 209 int summary_branches;
207 int summary_log; 210 int summary_log;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index a853522..5d77973 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -95,6 +95,11 @@ enable-filter-overrides::
95 Flag which, when set to "1", allows all filter settings to be 95 Flag which, when set to "1", allows all filter settings to be
96 overridden in repository-specific cgitrc files. Default value: none. 96 overridden in repository-specific cgitrc files. Default value: none.
97 97
98enable-gitweb-owner::
99 If set to "1" and scan-path is enabled, we first check each repository
100 for the git config value "gitweb.owner" to determine the owner.
101 Default value: "1". See also: scan-path.
102
98enable-index-links:: 103enable-index-links::
99 Flag which, when set to "1", will make cgit generate extra links for 104 Flag which, when set to "1", will make cgit generate extra links for
100 each repo in the repository index (specifically, to the "summary", 105 each repo in the repository index (specifically, to the "summary",
@@ -224,6 +229,16 @@ noheader::
224 Flag which, when set to "1", will make cgit omit the standard header 229 Flag which, when set to "1", will make cgit omit the standard header
225 on all pages. Default value: none. See also: "embedded". 230 on all pages. Default value: none. See also: "embedded".
226 231
232project-list::
233 A list of subdirectories inside of scan-path, relative to it, that
234 should loaded as git repositories. This must be defined prior to
235 scan-path. Default value: none. See also: scan-path.
236
237remove-suffix::
238 If set to "1" and scan-path is enabled, if any repositories are found
239 with a suffix of ".git", this suffix will be removed for the url and
240 name. Default value: "0". See also: scan-path.
241
227renamelimit:: 242renamelimit::
228 Maximum number of files to consider when detecting renames. The value 243 Maximum number of files to consider when detecting renames. The value
229 "-1" uses the compiletime value in git (for further info, look at 244 "-1" uses the compiletime value in git (for further info, look at
@@ -253,7 +268,10 @@ root-title::
253scan-path:: 268scan-path::
254 A path which will be scanned for repositories. If caching is enabled, 269 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 270 the result will be cached as a cgitrc include-file in the cache
256 directory. Default value: none. See also: cache-scanrc-ttl. 271 directory. If project-list has been defined prior to scan-path,
272 scan-path loads only the directories listed in the file pointed to by
273 project-list. Default value: none. See also: cache-scanrc-ttl,
274 project-list.
257 275
258section:: 276section::
259 The name of the current repository section - all repositories defined 277 The name of the current repository section - all repositories defined
@@ -530,3 +548,4 @@ will generate the following html element:
530AUTHOR 548AUTHOR
531------ 549------
532Lars Hjemli <hjemli@gmail.com> 550Lars Hjemli <hjemli@gmail.com>
551Jason A. Donenfeld <Jason@zx2c4.com>
diff --git a/scan-tree.c b/scan-tree.c
index 1e18f3c..e987824 100644
--- a/scan-tree.c
+++ b/scan-tree.c
@@ -1,3 +1,12 @@
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"
@@ -38,12 +47,20 @@ static int is_git_dir(const char *path)
38 47
39struct cgit_repo *repo; 48struct cgit_repo *repo;
40repo_config_fn config_fn; 49repo_config_fn config_fn;
50char *owner;
41 51
42static void repo_config(const char *name, const char *value) 52static void repo_config(const char *name, const char *value)
43{ 53{
44 config_fn(repo, name, value); 54 config_fn(repo, name, value);
45} 55}
46 56
57static int git_owner_config(const char *key, const char *value, void *cb)
58{
59 if (!strcmp(key, "gitweb.owner"))
60 owner = xstrdup(value);
61 return 0;
62}
63
47static void add_repo(const char *base, const char *path, repo_config_fn fn) 64static void add_repo(const char *base, const char *path, repo_config_fn fn)
48{ 65{
49 struct stat st; 66 struct stat st;
@@ -58,11 +75,10 @@ static void add_repo(const char *base, const char *path, repo_config_fn fn)
58 } 75 }
59 if (!stat(fmt("%s/noweb", path), &st)) 76 if (!stat(fmt("%s/noweb", path), &st))
60 return; 77 return;
61 if ((pwd = getpwuid(st.st_uid)) == NULL) { 78
62 fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", 79 owner = NULL;
63 path, strerror(errno), errno); 80 if (ctx.cfg.enable_gitweb_owner)
64 return; 81 git_config_from_file(git_owner_config, fmt("%s/config", path), NULL);
65 }
66 if (base == path) 82 if (base == path)
67 p = fmt("%s", path); 83 p = fmt("%s", path);
68 else 84 else
@@ -72,12 +88,23 @@ static void add_repo(const char *base, const char *path, repo_config_fn fn)
72 p[strlen(p) - 5] = '\0'; 88 p[strlen(p) - 5] = '\0';
73 89
74 repo = cgit_add_repo(xstrdup(p)); 90 repo = cgit_add_repo(xstrdup(p));
91 if (ctx.cfg.remove_suffix)
92 if ((p = strrchr(repo->url, '.')) && !strcmp(p, ".git"))
93 *p = '\0';
75 repo->name = repo->url; 94 repo->name = repo->url;
76 repo->path = xstrdup(path); 95 repo->path = xstrdup(path);
77 p = (pwd && pwd->pw_gecos) ? strchr(pwd->pw_gecos, ',') : NULL; 96 while (!owner) {
78 if (p) 97 if ((pwd = getpwuid(st.st_uid)) == NULL) {
79 *p = '\0'; 98 fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n",
80 repo->owner = (pwd ? xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name) : ""); 99 path, strerror(errno), errno);
100 break;
101 }
102 if (pwd->pw_gecos)
103 if ((p = strchr(pwd->pw_gecos, ',')))
104 *p = '\0';
105 owner = xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name);
106 }
107 repo->owner = owner;
81 108
82 p = fmt("%s/description", path); 109 p = fmt("%s/description", path);
83 if (!stat(p, &st)) 110 if (!stat(p, &st))
@@ -142,6 +169,34 @@ static void scan_path(const char *base, const char *path, repo_config_fn fn)
142 closedir(dir); 169 closedir(dir);
143} 170}
144 171
172#define lastc(s) s[strlen(s) - 1]
173
174void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn)
175{
176 char line[MAX_PATH * 2], *z;
177 FILE *projects;
178 int err;
179
180 projects = fopen(projectsfile, "r");
181 if (!projects) {
182 fprintf(stderr, "Error opening projectsfile %s: %s (%d)\n",
183 projectsfile, strerror(errno), errno);
184 }
185 while (fgets(line, sizeof(line), projects) != NULL) {
186 for (z = &lastc(line);
187 strlen(line) && strchr("\n\r", *z);
188 z = &lastc(line))
189 *z = '\0';
190 if (strlen(line))
191 scan_path(path, fmt("%s/%s", path, line), fn);
192 }
193 if ((err = ferror(projects))) {
194 fprintf(stderr, "Error reading from projectsfile %s: %s (%d)\n",
195 projectsfile, strerror(err), err);
196 }
197 fclose(projects);
198}
199
145void scan_tree(const char *path, repo_config_fn fn) 200void scan_tree(const char *path, repo_config_fn fn)
146{ 201{
147 scan_path(path, path, fn); 202 scan_path(path, path, fn);
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);