Merge branch 'jd/gitolite'

This commit is contained in:
Lars Hjemli 2010-08-04 03:10:29 +02:00
commit aec9c245e7
5 changed files with 116 additions and 17 deletions

29
cgit.c
View File

@ -135,6 +135,8 @@ void config_cb(const char *name, const char *value)
ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);
else if (!strcmp(name, "enable-filter-overrides")) else if (!strcmp(name, "enable-filter-overrides"))
ctx.cfg.enable_filter_overrides = atoi(value); ctx.cfg.enable_filter_overrides = atoi(value);
else if (!strcmp(name, "enable-gitweb-owner"))
ctx.cfg.enable_gitweb_owner = atoi(value);
else if (!strcmp(name, "enable-index-links")) else if (!strcmp(name, "enable-index-links"))
ctx.cfg.enable_index_links = atoi(value); ctx.cfg.enable_index_links = atoi(value);
else if (!strcmp(name, "enable-log-filecount")) else if (!strcmp(name, "enable-log-filecount"))
@ -181,9 +183,14 @@ void config_cb(const char *name, const char *value)
ctx.cfg.max_repo_count = atoi(value); ctx.cfg.max_repo_count = atoi(value);
else if (!strcmp(name, "max-commit-count")) else if (!strcmp(name, "max-commit-count"))
ctx.cfg.max_commit_count = atoi(value); ctx.cfg.max_commit_count = atoi(value);
else if (!strcmp(name, "project-list"))
ctx.cfg.project_list = xstrdup(expand_macros(value));
else if (!strcmp(name, "scan-path")) else if (!strcmp(name, "scan-path"))
if (!ctx.cfg.nocache && ctx.cfg.cache_size) if (!ctx.cfg.nocache && ctx.cfg.cache_size)
process_cached_repolist(expand_macros(value)); process_cached_repolist(expand_macros(value));
else if (ctx.cfg.project_list)
scan_projects(expand_macros(value),
ctx.cfg.project_list, repo_config);
else else
scan_tree(expand_macros(value), repo_config); scan_tree(expand_macros(value), repo_config);
else if (!strcmp(name, "source-filter")) else if (!strcmp(name, "source-filter"))
@ -200,6 +207,8 @@ void config_cb(const char *name, const char *value)
ctx.cfg.agefile = xstrdup(value); ctx.cfg.agefile = xstrdup(value);
else if (!strcmp(name, "renamelimit")) else if (!strcmp(name, "renamelimit"))
ctx.cfg.renamelimit = atoi(value); ctx.cfg.renamelimit = atoi(value);
else if (!strcmp(name, "remove-suffix"))
ctx.cfg.remove_suffix = atoi(value);
else if (!strcmp(name, "robots")) else if (!strcmp(name, "robots"))
ctx.cfg.robots = xstrdup(value); ctx.cfg.robots = xstrdup(value);
else if (!strcmp(name, "clone-prefix")) else if (!strcmp(name, "clone-prefix"))
@ -286,6 +295,7 @@ static void prepare_context(struct cgit_context *ctx)
ctx->cfg.css = "/cgit.css"; ctx->cfg.css = "/cgit.css";
ctx->cfg.logo = "/cgit.png"; ctx->cfg.logo = "/cgit.png";
ctx->cfg.local_time = 0; ctx->cfg.local_time = 0;
ctx->cfg.enable_gitweb_owner = 1;
ctx->cfg.enable_tree_linenumbers = 1; ctx->cfg.enable_tree_linenumbers = 1;
ctx->cfg.max_repo_count = 50; ctx->cfg.max_repo_count = 50;
ctx->cfg.max_commit_count = 50; ctx->cfg.max_commit_count = 50;
@ -295,7 +305,9 @@ static void prepare_context(struct cgit_context *ctx)
ctx->cfg.max_blob_size = 0; ctx->cfg.max_blob_size = 0;
ctx->cfg.max_stats = 0; ctx->cfg.max_stats = 0;
ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s"; ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s";
ctx->cfg.project_list = NULL;
ctx->cfg.renamelimit = -1; ctx->cfg.renamelimit = -1;
ctx->cfg.remove_suffix = 0;
ctx->cfg.robots = "index, nofollow"; ctx->cfg.robots = "index, nofollow";
ctx->cfg.root_title = "Git repository browser"; ctx->cfg.root_title = "Git repository browser";
ctx->cfg.root_desc = "a fast webinterface for the git dscm"; ctx->cfg.root_desc = "a fast webinterface for the git dscm";
@ -574,6 +586,9 @@ static int generate_cached_repolist(const char *path, const char *cached_rc)
return errno; return errno;
} }
idx = cgit_repolist.count; idx = cgit_repolist.count;
if (ctx.cfg.project_list)
scan_projects(path, ctx.cfg.project_list, repo_config);
else
scan_tree(path, repo_config); scan_tree(path, repo_config);
print_repolist(f, &cgit_repolist, idx); print_repolist(f, &cgit_repolist, idx);
if (rename(locked_rc, cached_rc)) if (rename(locked_rc, cached_rc))
@ -588,17 +603,25 @@ static void process_cached_repolist(const char *path)
struct stat st; struct stat st;
char *cached_rc; char *cached_rc;
time_t age; time_t age;
unsigned long hash;
cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root, hash = hash_str(path);
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));
if (stat(cached_rc, &st)) { if (stat(cached_rc, &st)) {
/* Nothing is cached, we need to scan without forking. And /* Nothing is cached, we need to scan without forking. And
* if we fail to generate a cached repolist, we need to * if we fail to generate a cached repolist, we need to
* invoke scan_tree manually. * invoke scan_tree manually.
*/ */
if (generate_cached_repolist(path, cached_rc)) 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); scan_tree(path, repo_config);
}
return; return;
} }

3
cgit.h
View File

@ -167,6 +167,7 @@ struct cgit_config {
char *logo; char *logo;
char *logo_link; char *logo_link;
char *module_link; char *module_link;
char *project_list;
char *robots; char *robots;
char *root_title; char *root_title;
char *root_desc; char *root_desc;
@ -183,6 +184,7 @@ struct cgit_config {
int cache_static_ttl; int cache_static_ttl;
int embedded; int embedded;
int enable_filter_overrides; int enable_filter_overrides;
int enable_gitweb_owner;
int enable_index_links; int enable_index_links;
int enable_log_filecount; int enable_log_filecount;
int enable_log_linecount; int enable_log_linecount;
@ -202,6 +204,7 @@ struct cgit_config {
int noplainemail; int noplainemail;
int noheader; int noheader;
int renamelimit; int renamelimit;
int remove_suffix;
int snapshots; int snapshots;
int summary_branches; int summary_branches;
int summary_log; int summary_log;

View File

@ -95,6 +95,11 @@ enable-filter-overrides::
Flag which, when set to "1", allows all filter settings to be Flag which, when set to "1", allows all filter settings to be
overridden in repository-specific cgitrc files. Default value: none. overridden in repository-specific cgitrc files. Default value: none.
enable-gitweb-owner::
If set to "1" and scan-path is enabled, we first check each repository
for the git config value "gitweb.owner" to determine the owner.
Default value: "1". See also: scan-path.
enable-index-links:: enable-index-links::
Flag which, when set to "1", will make cgit generate extra links for Flag which, when set to "1", will make cgit generate extra links for
each repo in the repository index (specifically, to the "summary", each repo in the repository index (specifically, to the "summary",
@ -224,6 +229,16 @@ noheader::
Flag which, when set to "1", will make cgit omit the standard header Flag which, when set to "1", will make cgit omit the standard header
on all pages. Default value: none. See also: "embedded". on all pages. Default value: none. See also: "embedded".
project-list::
A list of subdirectories inside of scan-path, relative to it, that
should loaded as git repositories. This must be defined prior to
scan-path. Default value: none. See also: scan-path.
remove-suffix::
If set to "1" and scan-path is enabled, if any repositories are found
with a suffix of ".git", this suffix will be removed for the url and
name. Default value: "0". See also: scan-path.
renamelimit:: renamelimit::
Maximum number of files to consider when detecting renames. The value Maximum number of files to consider when detecting renames. The value
"-1" uses the compiletime value in git (for further info, look at "-1" uses the compiletime value in git (for further info, look at
@ -253,7 +268,10 @@ root-title::
scan-path:: scan-path::
A path which will be scanned for repositories. If caching is enabled, A path which will be scanned for repositories. If caching is enabled,
the result will be cached as a cgitrc include-file in the cache the result will be cached as a cgitrc include-file in the cache
directory. Default value: none. See also: cache-scanrc-ttl. directory. If project-list has been defined prior to scan-path,
scan-path loads only the directories listed in the file pointed to by
project-list. Default value: none. See also: cache-scanrc-ttl,
project-list.
section:: section::
The name of the current repository section - all repositories defined The name of the current repository section - all repositories defined
@ -530,3 +548,4 @@ will generate the following html element:
AUTHOR AUTHOR
------ ------
Lars Hjemli <hjemli@gmail.com> Lars Hjemli <hjemli@gmail.com>
Jason A. Donenfeld <Jason@zx2c4.com>

View File

@ -1,3 +1,12 @@
/* scan-tree.c
*
* Copyright (C) 2008-2009 Lars Hjemli
* Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com>
*
* Licensed under GNU General Public License v2
* (see COPYING for full license text)
*/
#include "cgit.h" #include "cgit.h"
#include "configfile.h" #include "configfile.h"
#include "html.h" #include "html.h"
@ -38,12 +47,20 @@ static int is_git_dir(const char *path)
struct cgit_repo *repo; struct cgit_repo *repo;
repo_config_fn config_fn; repo_config_fn config_fn;
char *owner;
static void repo_config(const char *name, const char *value) static void repo_config(const char *name, const char *value)
{ {
config_fn(repo, name, value); config_fn(repo, name, value);
} }
static int git_owner_config(const char *key, const char *value, void *cb)
{
if (!strcmp(key, "gitweb.owner"))
owner = xstrdup(value);
return 0;
}
static void add_repo(const char *base, const char *path, repo_config_fn fn) static void add_repo(const char *base, const char *path, repo_config_fn fn)
{ {
struct stat st; struct stat st;
@ -58,11 +75,10 @@ static void add_repo(const char *base, const char *path, repo_config_fn fn)
} }
if (!stat(fmt("%s/noweb", path), &st)) if (!stat(fmt("%s/noweb", path), &st))
return; return;
if ((pwd = getpwuid(st.st_uid)) == NULL) {
fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n", owner = NULL;
path, strerror(errno), errno); if (ctx.cfg.enable_gitweb_owner)
return; git_config_from_file(git_owner_config, fmt("%s/config", path), NULL);
}
if (base == path) if (base == path)
p = fmt("%s", path); p = fmt("%s", path);
else else
@ -72,12 +88,23 @@ static void add_repo(const char *base, const char *path, repo_config_fn fn)
p[strlen(p) - 5] = '\0'; p[strlen(p) - 5] = '\0';
repo = cgit_add_repo(xstrdup(p)); repo = cgit_add_repo(xstrdup(p));
if (ctx.cfg.remove_suffix)
if ((p = strrchr(repo->url, '.')) && !strcmp(p, ".git"))
*p = '\0';
repo->name = repo->url; repo->name = repo->url;
repo->path = xstrdup(path); repo->path = xstrdup(path);
p = (pwd && pwd->pw_gecos) ? strchr(pwd->pw_gecos, ',') : NULL; while (!owner) {
if (p) if ((pwd = getpwuid(st.st_uid)) == NULL) {
fprintf(stderr, "Error reading owner-info for %s: %s (%d)\n",
path, strerror(errno), errno);
break;
}
if (pwd->pw_gecos)
if ((p = strchr(pwd->pw_gecos, ',')))
*p = '\0'; *p = '\0';
repo->owner = (pwd ? xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name) : ""); owner = xstrdup(pwd->pw_gecos ? pwd->pw_gecos : pwd->pw_name);
}
repo->owner = owner;
p = fmt("%s/description", path); p = fmt("%s/description", path);
if (!stat(p, &st)) if (!stat(p, &st))
@ -142,6 +169,34 @@ static void scan_path(const char *base, const char *path, repo_config_fn fn)
closedir(dir); closedir(dir);
} }
#define lastc(s) s[strlen(s) - 1]
void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn)
{
char line[MAX_PATH * 2], *z;
FILE *projects;
int err;
projects = fopen(projectsfile, "r");
if (!projects) {
fprintf(stderr, "Error opening projectsfile %s: %s (%d)\n",
projectsfile, strerror(errno), errno);
}
while (fgets(line, sizeof(line), projects) != NULL) {
for (z = &lastc(line);
strlen(line) && strchr("\n\r", *z);
z = &lastc(line))
*z = '\0';
if (strlen(line))
scan_path(path, fmt("%s/%s", path, line), fn);
}
if ((err = ferror(projects))) {
fprintf(stderr, "Error reading from projectsfile %s: %s (%d)\n",
projectsfile, strerror(err), err);
}
fclose(projects);
}
void scan_tree(const char *path, repo_config_fn fn) void scan_tree(const char *path, repo_config_fn fn)
{ {
scan_path(path, path, fn); scan_path(path, path, fn);

View File

@ -1,3 +1,2 @@
extern void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn);
extern void scan_tree(const char *path, repo_config_fn fn); extern void scan_tree(const char *path, repo_config_fn fn);