On 31.01.2012 20:25, The Ranger wrote:
I've created a quick patch to add gitolite config file parsing support
to cgit.

diff -puNX exclude.pat cgit-0.9.0.2/cgit.c cgit-gitolite/cgit.c
--- cgit-0.9.0.2/cgit.c 2011-07-21 17:24:10.000000000 +0300
+++ cgit-gitolite/cgit.c        2012-01-31 13:03:27.974747168 +0200
@@ -15,6 +15,7 @@
 #include "ui-shared.h"
 #include "ui-stats.h"
 #include "scan-tree.h"
+#include "gitolite.h"

 const char *cgit_version = CGIT_VERSION;

@@ -235,6 +236,9 @@ void config_cb(const char *name, const c
                add_mimetype(name + 9, value);
        else if (!strcmp(name, "include"))
                parse_configfile(expand_macros(value), config_cb);
+       else if (!strcmp(name, "gitolite-conf")) {
+               ctx.cfg.gitolite_conf = gitolite_scan_conf(value, 
ctx.env.remote_user);
+       }
 }

 static void querystring_cb(const char *name, const char *value)
@@ -309,6 +313,7 @@ static void prepare_context(struct cgit_
        ctx->cfg.cache_scanrc_ttl = 15;
        ctx->cfg.cache_static_ttl = -1;
        ctx->cfg.css = "/cgit.css";
+       ctx->cfg.gitolite_conf = NULL;
        ctx->cfg.logo = "/cgit.png";
        ctx->cfg.local_time = 0;
        ctx->cfg.enable_gitweb_owner = 1;
@@ -345,6 +350,7 @@ static void prepare_context(struct cgit_
        ctx->env.script_name = xstrdupn(getenv("SCRIPT_NAME"));
        ctx->env.server_name = xstrdupn(getenv("SERVER_NAME"));
        ctx->env.server_port = xstrdupn(getenv("SERVER_PORT"));
+       ctx->env.remote_user = xstrdupn(getenv("REMOTE_USER"));
        ctx->page.mimetype = "text/html";
        ctx->page.charset = PAGE_ENCODING;
        ctx->page.filename = NULL;
@@ -794,6 +800,9 @@ int main(int argc, const char **argv)
                ctx.cfg.cache_size = 0;
        err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root,
                            ctx.qry.raw, ttl, process_request, &ctx);
+
+       gitolite_free_res(ctx.cfg.gitolite_conf);
+
        if (err)
                cgit_print_error(fmt("Error processing page: %s (%d)",
                                     strerror(err), err));
diff -puNX exclude.pat cgit-0.9.0.2/cgit.h cgit-gitolite/cgit.h
--- cgit-0.9.0.2/cgit.h 2011-07-21 17:24:10.000000000 +0300
+++ cgit-gitolite/cgit.h        2012-01-25 18:15:01.687362057 +0200
@@ -222,6 +222,7 @@ struct cgit_config {
        struct string_list mimetypes;
        struct cgit_filter *about_filter;
        struct cgit_filter *commit_filter;
+       struct gitolite_conf *gitolite_conf;
        struct cgit_filter *source_filter;
 };

@@ -249,6 +250,7 @@ struct cgit_environment {
        char *script_name;
        char *server_name;
        char *server_port;
+       char *remote_user;
 };

 struct cgit_context {
Common subdirectories: cgit-0.9.0.2/filters and cgit-gitolite/filters
diff -puNX exclude.pat cgit-0.9.0.2/gitolite.c cgit-gitolite/gitolite.c
--- cgit-0.9.0.2/gitolite.c     1970-01-01 03:00:00.000000000 +0300
+++ cgit-gitolite/gitolite.c    2012-01-31 19:52:42.605533772 +0200
@@ -0,0 +1,232 @@
+/*
+ * gitolite.c
+ *
+ *  Created on: 24.01.2012
+ *      Author: ivari
+ */
+
+#include <stdio.h>
+
+#include "cgit.h"
+#include "gitolite.h"
+
+struct gitolite_option {
+       char option[MAX_OPT_LEN];
+       char value[MAX_OPT_LEN];
+};
+
+//Parse configuration options from gitolite.conf
+static int gitolite_read_option(FILE *file, struct gitolite_option *option) {
+       int matches;
+       char line[sizeof(option->option) + sizeof(option->value)];
+       memset(option, 0, sizeof(struct gitolite_option));
+
+       if(fgets(line, sizeof(line), file) == NULL) return -1;
+ matches = sscanf(line, "%s%*[ =\t]%[^\n]s\n", option->option, option->value);
+       if(matches < 1) return 0;
+
+       //Handle one big string
+       if(matches == 1) {
+               char *p = strchr(option->option, '=');
+               if(p == NULL) return 0;
+               *p = '\0';
+               strncpy(option->value, p+1, sizeof(option->value));
+               option->value[sizeof(option->value)-1] = 0;
+       }
+
+       //Skip comments
+       if(option->option[0] == '#') return 0;
+       return 1;
+}
+
+//Add repo to list
+static struct gitolite_repo * gitolite_add_repo(struct gitolite_conf *conf) {
+       struct gitolite_repo *repo;
+       if(conf == NULL) return NULL;
+
+       repo = xmalloc(sizeof(*repo));
+       if(repo == NULL) return NULL;
+       memset(repo, 0, sizeof(struct gitolite_repo));
+
+       // First repo?
+       if(conf->r_first == NULL) conf->r_first = repo;
+
+       // We have more than one repo?
+       if(conf->r_last != NULL) conf->r_last->next = repo;
+
+       conf->r_last = repo;
+
+       return repo;
+}
+
+//Add group to list
+static struct gitolite_group * gitolite_add_group(struct gitolite_conf *conf) {
+       struct gitolite_group *group;
+       if(conf == NULL) return NULL;
+
+       group = xmalloc(sizeof(*group));
+       if(group == NULL) return NULL;
+       memset(group, 0, sizeof(struct gitolite_group));
+
+       if(conf->g_first == NULL) conf->g_first = group;
+       if(conf->g_last != NULL) conf->g_last->next = group;
+
+       conf->g_last = group;
+
+       return group;
+}
+
+static int gitolite_check_group(struct gitolite_conf *conf, const char *name) {
+       struct gitolite_group *group;
+
+       if(!strcmp(name, "@all")) return 1;
+
+       if(conf == NULL) return 0;
+
+       group = conf->g_first;
+       while(group != NULL) {
+               if(!strcmp(group->name, name)) return 1;
+               group = group->next;
+       }
+
+       return 0;
+}
+
+static void gitolite_parse_user(struct gitolite_conf *conf, struct gitolite_option *option, char *path, const char *user) {
+       struct gitolite_repo *repo;
+       char *p;
+
+       while((p = strrchr(option->value, ' ')) != NULL) {
+               *p = '\0';
+               if(*(p+1) == '@' && gitolite_check_group(conf, p+1) > 0) goto 
ADDREPO;
+               if(!strcmp(p+1, user)) goto ADDREPO;
+       }
+
+ if(option->value[0] == '@' && gitolite_check_group(conf, option->value) > 0) goto ADDREPO;
+
+       //If not current user, skip
+       if(strcmp(option->value, user)) return;
+
+ADDREPO:
+       repo = gitolite_add_repo(conf);
+       repo->path = xstrdup(path);
+}
+
+static void gitolite_parse_group(struct gitolite_conf *conf, struct gitolite_option *option, const char *user) {
+       struct gitolite_group *group;
+       char *p;
+
+       while((p = strrchr(option->value, ' ')) != NULL) {
+               *p = '\0';
+               if(strcmp(p+1, user)) continue;
+       }
+
+       if(strcmp(option->value, user)) return;
+
+       group = gitolite_add_group(conf);
+       group->name = xstrdup(option->option);
+}
+
+//Add repos from gitolite.conf file
+struct gitolite_conf * gitolite_scan_conf(const char *gitolite_path, const char *user) {
+       FILE *file;
+       struct gitolite_option option;
+       struct gitolite_conf *conf = NULL;
+
+       int i;
+       char *p;
+       char path[MAX_OPT_LEN];
+
+       conf = xmalloc(sizeof(*conf));
+       memset(conf, 0, sizeof(*conf));
+
+       //User not found, deny everything by default
+       if(user == NULL) return conf;
+
+       file = fopen(gitolite_path, "r");
+       if(file == NULL) {
+ fprintf(stderr, "Could not open gitolite config file %s\n", gitolite_path);
+               return conf;
+       }
+
+       //Remove @suffix from user names (gitolite does not like this)
+       if ((p = strchr(user, '@')) != NULL) *p = '\0';
+
+       while((i = gitolite_read_option(file, &option)) != -1) {
+               if(i == 0 || *(option.value) == 0) continue;
+
+               // Repo definition
+               if(!strcmp(option.option, "repo")) {
+                       strncpy(path, option.value, sizeof(path));
+                       path[sizeof(path)-1] = 0;
+                       continue;
+               }
+
+               // Access definition
+               if(strcmp(option.option, "R") >= 0) {
+                       gitolite_parse_user(conf, &option, path, user);
+                       continue;
+               }
+
+               // Group definition
+               if(option.option[0] == '@') {
+                       gitolite_parse_group(conf, &option, user);
+                       continue;
+               }
+       }
+
+       fclose(file);
+       return conf;
+}
+
+
+
+//Check repo before showing it
+int gitolite_check_repo(struct gitolite_conf *conf, const char *base) {
+       char *p;
+       struct gitolite_repo *repo;
+
+       //No conf set up, disable this check
+       if(conf == NULL) return 1;
+
+       //Remove .git suffix
+       if ((p = strrchr(base, '.')) && !strcmp(p, ".git")) *p = '\0';
+
+       repo = conf->r_first;
+       while(repo != NULL) {
+               if(!strcmp(repo->path, base)) return 1;
+               repo = repo->next;
+       }
+
+       //Repo was not found, deny
+       return 0;
+}
+
+//Cleanup
+void gitolite_free_res(struct gitolite_conf *conf) {
+       struct gitolite_repo *repo;
+       struct gitolite_repo *n_repo;
+
+       struct gitolite_group *group;
+       struct gitolite_group *n_group;
+
+       if(conf == NULL) return;
+
+       //Empty struct, no repos?
+       repo = conf->r_first;
+
+       while(repo != NULL) {
+               n_repo = repo->next;
+               free(repo);
+               repo = n_repo;
+       }
+
+       group = conf->g_first;
+       while(group != NULL) {
+               n_group = group->next;
+               free(group);
+               group = n_group;
+       }
+
+       free(conf);
+}
diff -puNX exclude.pat cgit-0.9.0.2/gitolite.h cgit-gitolite/gitolite.h
--- cgit-0.9.0.2/gitolite.h     1970-01-01 03:00:00.000000000 +0300
+++ cgit-gitolite/gitolite.h    2012-01-31 17:44:02.025566452 +0200
@@ -0,0 +1,35 @@
+/*
+ * gitolite.h
+ *
+ *  Created on: 24.01.2012
+ *      Author: ivari
+ */
+
+#ifndef GITOLITE_H_
+#define GITOLITE_H_
+
+#define MAX_OPT_LEN 256
+
+struct gitolite_conf {
+       struct gitolite_repo *r_first;
+       struct gitolite_repo *r_last;
+
+       struct gitolite_group *g_first;
+       struct gitolite_group *g_last;
+};
+
+struct gitolite_repo {
+       char *path;
+       struct gitolite_repo *next;
+};
+
+struct gitolite_group {
+       char *name;
+       struct gitolite_group *next;
+};
+
+struct gitolite_conf * gitolite_scan_conf(const char *gitolite_path, const char *user);
+int gitolite_check_repo(struct gitolite_conf *conf, const char *base);
+void gitolite_free_res(struct gitolite_conf *conf);
+
+#endif /* GITOLITE_H_ */
diff -puNX exclude.pat cgit-0.9.0.2/Makefile cgit-gitolite/Makefile
--- cgit-0.9.0.2/Makefile       2011-07-21 17:24:10.000000000 +0300
+++ cgit-gitolite/Makefile      2012-01-25 16:28:49.223364486 +0200
@@ -116,6 +116,7 @@ OBJECTS += ui-summary.o
 OBJECTS += ui-tag.o
 OBJECTS += ui-tree.o
 OBJECTS += vector.o
+OBJECTS += gitolite.o

 ifdef NEEDS_LIBICONV
        EXTLIBS += -liconv
diff -puNX exclude.pat cgit-0.9.0.2/scan-tree.c cgit-gitolite/scan-tree.c
--- cgit-0.9.0.2/scan-tree.c    2011-07-21 17:24:10.000000000 +0300
+++ cgit-gitolite/scan-tree.c   2012-01-26 16:29:53.777586126 +0200
@@ -10,6 +10,7 @@
 #include "cgit.h"
 #include "configfile.h"
 #include "html.h"
+#include "gitolite.h"

 #define MAX_PATH 4096

@@ -99,6 +100,11 @@ static void add_repo(const char *base, c
        if (!strcmp(rel + strlen(rel) - 5, "/.git"))
                rel[strlen(rel) - 5] = '\0';

+       if (!gitolite_check_repo(ctx.cfg.gitolite_conf, rel)) {
+               free(rel);
+               return;
+       }
+
        repo = cgit_add_repo(rel);
        if (ctx.cfg.remove_suffix)
                if ((p = strrchr(repo->url, '.')) && !strcmp(p, ".git"))
Common subdirectories: cgit-0.9.0.2/tests and cgit-gitolite/tests


--
rgrds,
Ranger



_______________________________________________
cgit mailing list
[email protected]
http://hjemli.net/mailman/listinfo/cgit

Reply via email to