diff options
author | Florian Pritz <bluewind@xinu.at> | 2014-12-29 17:05:07 +0100 |
---|---|---|
committer | Florian Pritz <bluewind@xinu.at> | 2014-12-29 17:52:56 +0100 |
commit | 4f5e9b0d6c1090681c489a10179ff1a7c215ac19 (patch) | |
tree | ac7bece975e3b7394b2c30a9a404212270d31955 | |
parent | 7552266aaccb9445e082fc04215afcb55ad543d8 (diff) | |
download | cgit-working.tar.gz cgit-working.tar.xz |
Support Git over HTTP using git-http-backendworking
This saves users from the hassle of setting up git-http-backend when
they already run cgit.
References: man git-http-backend
Signed-off-by: Florian Pritz <bluewind@xinu.at>
-rw-r--r-- | cgit.c | 3 | ||||
-rw-r--r-- | cgit.h | 1 | ||||
-rw-r--r-- | cgitrc.5.txt | 8 | ||||
-rw-r--r-- | cmd.c | 12 | ||||
-rw-r--r-- | ui-clone.c | 61 | ||||
-rw-r--r-- | ui-clone.h | 2 |
6 files changed, 87 insertions, 0 deletions
@@ -124,6 +124,8 @@ static void config_cb(const char *name, const char *value) ctx.cfg.head_include = xstrdup(value); else if (!strcmp(name, "header")) ctx.cfg.header = xstrdup(value); + else if (!strcmp(name, "http-backend-path")) + ctx.cfg.http_backend_path = xstrdup(value); else if (!strcmp(name, "logo")) ctx.cfg.logo = xstrdup(value); else if (!strcmp(name, "index-header")) @@ -353,6 +355,7 @@ static void prepare_context(void) ctx.cfg.css = "/cgit.css"; ctx.cfg.logo = "/cgit.png"; ctx.cfg.favicon = "/favicon.ico"; + ctx.cfg.http_backend_path = NULL; ctx.cfg.local_time = 0; ctx.cfg.enable_http_clone = 1; ctx.cfg.enable_index_owner = 1; @@ -190,6 +190,7 @@ struct cgit_config { char *footer; char *head_include; char *header; + char *http_backend_path; char *index_header; char *index_info; char *logo; diff --git a/cgitrc.5.txt b/cgitrc.5.txt index be6703f..62b73ba 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@ -218,6 +218,11 @@ header:: The content of the file specified with this option will be included verbatim at the top of all pages. Default value: none. +http-backend-path:: + Path to the git-http-backend smart HTTP backend binary. Setting this + allows the git clone to fetch/push via Git over HTTP. You'll also + need to enable enable-http-clone for this to work. Default value: none. + include:: Name of a configfile to include before the rest of the current config- file is parsed. Default value: none. See also: "MACRO EXPANSION". @@ -766,6 +771,9 @@ enable-index-owner=1 # Allow http transport git clone enable-http-clone=1 +# Use Git over HTTP +http-backend-path=/usr/lib/git-core/git-http-backend + # Show extra links for each repository on the index page enable-index-links=1 @@ -136,6 +136,16 @@ static void tree_fn(void) cgit_print_tree(ctx.qry.sha1, ctx.qry.path); } +static void git_upload_pack_fn(void) +{ + cgit_clone_git_upload_pack(); +} + +static void git_receive_pack_fn(void) +{ + cgit_clone_git_receive_pack(); +} + #define def_cmd(name, want_repo, want_layout, want_vpath, is_clone) \ {#name, name##_fn, want_repo, want_layout, want_vpath, is_clone} @@ -162,6 +172,8 @@ struct cgit_cmd *cgit_get_cmd(void) def_cmd(summary, 1, 1, 0, 0), def_cmd(tag, 1, 1, 0, 0), def_cmd(tree, 1, 1, 1, 0), + {"git-upload-pack", git_upload_pack_fn, 1, 0, 0, 1}, + {"git-receive-pack", git_receive_pack_fn, 1, 0, 0, 1}, }; int i; @@ -69,8 +69,43 @@ static void send_file(char *path) html_include(path); } +static void dispatch_to_git_http_backend(void) +{ + if (access(ctx.cfg.http_backend_path, X_OK) != -1) { + size_t git_root_len; + char *git_root = NULL; + + /* git-http-backend does it's own URL parsing and concatenates + * GIT_PROJECT_ROOT and PATH_INFO to find the git repo. + * The root is the same as scan-path, but scan-path is not + * always available so we calculate the root path. + * Example: + * repo.path = /srv/git/some/more/dirs/ + * qry.repo = some/more/dirs + * -> git_root = /srv/git/ + */ + strip_suffix(ctx.repo->path, "/", &git_root_len); + strip_suffix_mem(ctx.repo->path, &git_root_len, ctx.qry.repo); + + git_root = xmalloc(git_root_len + 1); + strncpy(git_root, ctx.repo->path, git_root_len); + git_root[git_root_len] = '\0'; + + setenv("GIT_PROJECT_ROOT", git_root, 1); + execl(ctx.cfg.http_backend_path, "git-http-backend", NULL); + } else { + fprintf(stderr, "[cgit] http-backend-path (%s) is not executable: %s\n", + ctx.cfg.http_backend_path, strerror(errno)); + html_status(500, "Internal Server Error", 0); + } +} + void cgit_clone_info(void) { + if (ctx.cfg.http_backend_path) { + return dispatch_to_git_http_backend(); + } + if (!ctx.qry.path || strcmp(ctx.qry.path, "refs")) return; @@ -82,6 +117,10 @@ void cgit_clone_info(void) void cgit_clone_objects(void) { + if (ctx.cfg.http_backend_path) { + return dispatch_to_git_http_backend(); + } + if (!ctx.qry.path) { html_status(400, "Bad request", 0); return; @@ -97,5 +136,27 @@ void cgit_clone_objects(void) void cgit_clone_head(void) { + if (ctx.cfg.http_backend_path) { + return dispatch_to_git_http_backend(); + } + send_file(git_path("%s", "HEAD")); } + +void cgit_clone_git_upload_pack(void) +{ + if (ctx.cfg.http_backend_path) { + return dispatch_to_git_http_backend(); + } + + html_status(404, "Not found", 0); +} + +void cgit_clone_git_receive_pack(void) +{ + if (ctx.cfg.http_backend_path) { + return dispatch_to_git_http_backend(); + } + + html_status(404, "Not found", 0); +} @@ -4,5 +4,7 @@ void cgit_clone_info(void); void cgit_clone_objects(void); void cgit_clone_head(void); +void cgit_clone_git_upload_pack(void); +void cgit_clone_git_receive_pack(void); #endif /* UI_CLONE_H */ |