[PATCH] scan-user-path option, to scan for git repos in users' homedirs

Ferry Huberts mailings at hupie.com
Wed Jul 16 09:22:34 CEST 2014


Great!
I've doing this through scripting so having it done automatically would 
be awesome.

One thing though: if I could place the ~user repos in a configurable 
section then that would even be more awesome.

My servers (https://github.com/reposerf/reposerf) put the user repos 
under a section called 'Developer Repositories' while non-user repos are 
under other sections, like 'Release Repositories' etc.


Ferry

On 16/07/14 09:15, Dan Callaghan wrote:
> 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);
>

-- 
Ferry Huberts


More information about the CGit mailing list