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 <[email protected]>
---

I've messed up updating my master branch and used git-send-email on it. You
might have gotten 1 or 2 patches that are already applied because of that.
Sorry.

 cgit.c       |  3 +++
 cgit.h       |  1 +
 cgitrc.5.txt |  8 ++++++++
 cmd.c        | 12 ++++++++++++
 ui-clone.c   | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ui-clone.h   |  2 ++
 6 files changed, 86 insertions(+)

diff --git a/cgit.c b/cgit.c
index 79019c2..0c4a292 100644
--- a/cgit.c
+++ b/cgit.c
@@ -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;
diff --git a/cgit.h b/cgit.h
index 42140ac..dcd44f0 100644
--- a/cgit.h
+++ b/cgit.h
@@ -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
diff --git a/cmd.c b/cmd.c
index 188cd56..889ed05 100644
--- a/cmd.c
+++ b/cmd.c
@@ -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;
 
diff --git a/ui-clone.c b/ui-clone.c
index a4ffd6e..15bd78b 100644
--- a/ui-clone.c
+++ b/ui-clone.c
@@ -69,8 +69,42 @@ 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);
+               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 +116,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 +135,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);
+}
diff --git a/ui-clone.h b/ui-clone.h
index 3e460a3..b27087e 100644
--- a/ui-clone.h
+++ b/ui-clone.h
@@ -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 */
-- 
2.2.1
_______________________________________________
CGit mailing list
[email protected]
http://lists.zx2c4.com/mailman/listinfo/cgit

Reply via email to