From mboxrd@z Thu Jan 1 00:00:00 1970 From: dcallagh at redhat.com (Dan Callaghan) Date: Wed, 16 Jul 2014 17:15:42 +1000 Subject: [PATCH] scan-user-path option, to scan for git repos in users' homedirs Message-ID: <1405494942-28128-1-git-send-email-dcallagh@redhat.com> I'm using the --user-dir option for git-daemon to allow users to expose git repos under ~/public_git. I wanted them to be listed in cgit as well, so I added this scan-user-path option. --- cgit.c | 9 ++++++++- cgit.h | 1 + cgitrc.5.txt | 16 +++++++++++++++ scan-tree.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- scan-tree.h | 1 + 5 files changed, 84 insertions(+), 8 deletions(-) diff --git a/cgit.c b/cgit.c index 20f6e27..5bc1f9e 100644 --- a/cgit.c +++ b/cgit.c @@ -212,6 +212,8 @@ static void config_cb(const char *name, const char *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, "user-list")) + ctx.cfg.user_list = xstrdup(expand_macros(value)); else if (!strcmp(name, "scan-path")) if (!ctx.cfg.nocache && ctx.cfg.cache_size) process_cached_repolist(expand_macros(value)); @@ -222,7 +224,11 @@ static void config_cb(const char *name, const char *value) scan_tree(expand_macros(value), repo_config); else if (!strcmp(name, "scan-hidden-path")) ctx.cfg.scan_hidden_path = atoi(value); - else if (!strcmp(name, "section-from-path")) + else if (!strcmp(name, "scan-user-path")) { + if (ctx.cfg.user_list) + scan_homedirs(expand_macros(value), + ctx.cfg.user_list, repo_config); + } else if (!strcmp(name, "section-from-path")) ctx.cfg.section_from_path = atoi(value); else if (!strcmp(name, "repository-sort")) ctx.cfg.repository_sort = xstrdup(value); @@ -373,6 +379,7 @@ static void prepare_context(void) ctx.cfg.summary_tags = 10; ctx.cfg.max_atom_items = 10; ctx.cfg.ssdiff = 0; + ctx.cfg.user_list = NULL; ctx.env.cgit_config = getenv("CGIT_CONFIG"); ctx.env.http_host = getenv("HTTP_HOST"); ctx.env.https = getenv("HTTPS"); diff --git a/cgit.h b/cgit.h index 0badc64..09e9c14 100644 --- a/cgit.h +++ b/cgit.h @@ -192,6 +192,7 @@ struct cgit_config { char *mimetype_file; char *module_link; char *project_list; + char *user_list; struct string_list readme; char *robots; char *root_title; diff --git a/cgitrc.5.txt b/cgitrc.5.txt index b7570db..b73e85a 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@ -379,6 +379,17 @@ scan-path:: Default value: none. See also: cache-scanrc-ttl, project-list, "MACRO EXPANSION". +scan-user-path:: + Path (relative to the user's homedir) which will be scanned for + repositories. The homedir of each user named in the user-list file is + scanned, starting from this path. For example, if "alice" and "bob" are + named in the user-list file and scan-user-path is set to "public_git", + `~alice/public_git` and `~bob/public_git` will be scanned for + repositories. + User repository names are prefixed with ~username/ to prevent + collisions between users. + Default value: none. See also: user-list, "MACRO EXPANSION". + section:: The name of the current repository section - all repositories defined after this option will inherit the current section name. Default value: @@ -433,6 +444,11 @@ strict-export:: repositories to match those exported by git-daemon. This option must be defined prior to scan-path. +user-list:: + Filename which lists usernames whose homedirs will be scanned by + scan-user-path. + Default value: none. See also: scan-user-path, "MACRO EXPANSION". + virtual-root:: Url which, if specified, will be used as root for all cgit links. It will also cause cgit to generate 'virtual urls', i.e. urls like diff --git a/scan-tree.c b/scan-tree.c index 044bcdc..62dfc71 100644 --- a/scan-tree.c +++ b/scan-tree.c @@ -74,7 +74,8 @@ static char *xstrrchr(char *s, char *from, int c) return from < s ? NULL : from; } -static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn) +static void add_repo(const char *base, struct strbuf *path, + const char *name_prefix, repo_config_fn fn) { struct stat st; struct passwd *pwd; @@ -105,6 +106,7 @@ static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn) return; strbuf_setlen(path, pathlen); + strbuf_addstr(&rel, name_prefix); if (!starts_with(path->buf, base)) strbuf_addbuf(&rel, path); else @@ -176,7 +178,8 @@ static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn) strbuf_release(&rel); } -static void scan_path(const char *base, const char *path, repo_config_fn fn) +static void scan_path(const char *base, const char *path, + const char *name_prefix, repo_config_fn fn) { DIR *dir = opendir(path); struct dirent *ent; @@ -192,12 +195,12 @@ static void scan_path(const char *base, const char *path, repo_config_fn fn) strbuf_add(&pathbuf, path, strlen(path)); if (is_git_dir(pathbuf.buf)) { - add_repo(base, &pathbuf, fn); + add_repo(base, &pathbuf, name_prefix, fn); goto end; } strbuf_addstr(&pathbuf, "/.git"); if (is_git_dir(pathbuf.buf)) { - add_repo(base, &pathbuf, fn); + add_repo(base, &pathbuf, name_prefix, fn); goto end; } /* @@ -222,7 +225,7 @@ static void scan_path(const char *base, const char *path, repo_config_fn fn) continue; } if (S_ISDIR(st.st_mode)) - scan_path(base, pathbuf.buf, fn); + scan_path(base, pathbuf.buf, name_prefix, fn); } end: strbuf_release(&pathbuf); @@ -246,7 +249,7 @@ void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn continue; strbuf_insert(&line, 0, "/", 1); strbuf_insert(&line, 0, path, strlen(path)); - scan_path(path, line.buf, fn); + scan_path(path, line.buf, "", fn); } if ((err = ferror(projects))) { fprintf(stderr, "Error reading from projectsfile %s: %s (%d)\n", @@ -258,5 +261,53 @@ void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn void scan_tree(const char *path, repo_config_fn fn) { - scan_path(path, path, fn); + scan_path(path, path, "", fn); +} + +void scan_homedirs(const char *path, const char *usersfile, repo_config_fn fn) +{ + struct strbuf line = STRBUF_INIT; + struct strbuf pathbuf = STRBUF_INIT; + FILE *users; + struct passwd *pwd; + int err; + + users = fopen(usersfile, "r"); + if (!users) { + fprintf(stderr, "Error opening users-file %s: %s (%d)\n", + usersfile, strerror(errno), errno); + strbuf_release(&line); + strbuf_release(&pathbuf); + return; + } + while (strbuf_getline(&line, users, '\n') != EOF) { + if (!line.len) + continue; + errno = 0; + pwd = getpwnam(line.buf); + if (!pwd) { + if (errno) { + fprintf(stderr, "Error looking up user %s: %s (%d)\n", + line.buf, strerror(errno), errno); + } else { + fprintf(stderr, "User does not exist: %s\n", line.buf); + } + continue; + } + strbuf_reset(&pathbuf); + strbuf_addstr(&pathbuf, pwd->pw_dir); + strbuf_addch(&pathbuf, '/'); + strbuf_addstr(&pathbuf, path); + /* use ~username/ as repo name prefix */ + strbuf_insert(&line, 0, "~", 1); + strbuf_addch(&line, '/'); + scan_path(pathbuf.buf, pathbuf.buf, line.buf, fn); + } + if ((err = ferror(users))) { + fprintf(stderr, "Error reading from users-file %s: %s (%d)\n", + usersfile, strerror(err), err); + } + fclose(users); + strbuf_release(&line); + strbuf_release(&pathbuf); } diff --git a/scan-tree.h b/scan-tree.h index 1afbd4b..db21d56 100644 --- a/scan-tree.h +++ b/scan-tree.h @@ -1,2 +1,3 @@ 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_homedirs(const char *path, const char *usersfile, repo_config_fn fn); -- 1.9.3