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
_______________________________________________
CGit mailing list
[email protected]
http://lists.zx2c4.com/mailman/listinfo/cgit

Reply via email to