GIT_NAMESPACE is designed to be used mainly on the server side, that
the server can serve multiple git repositories while share one single
repository storage using different GIT_NAMESPACE settings.

Since we know that one remote repository hosts multiple namespaces,
can we handle different namespaces in one local repository? Or can
we access the proper namespace of the remote repository without
complicated server settings?

We can access namespace of remote repository using a proper formated
URL or with the help of settings of "remote.<name>.receivepack" and
"remote.<name>.uploadpack". E.g.

Use remote-ext style URL to access specific namespace of the remote:

    $ git remote add foo \
        'ext::ssh git@server git --namespace foo %s path/to/repo.git'

    $ git remote add bar \
        'ext::ssh git@server git --namespace bar %s path/to/repo.git'

Or set "remote.<name>.receivepack" and "remote.<name>.uploadpack".

    [remote "foo"]
        url = ssh://git@server/path/to/repo.git
        receivepack = git --namespace foo receive-pack
        uploadpack = git --namespace foo upload-pack
        fetch = +refs/heads/*:refs/remotes/foo/*

    [remote "bar"]
        url = ssh://git@server/path/to/repo.git
        receivepack = git --namespace bar receive-pack
        uploadpack = git --namespace bar upload-pack
        fetch = +refs/heads/*:refs/remotes/foo/*

But if the remote ssh server use a limit shell (such as git-shell
or gitolite), the above URLs won't work. This is because these git
specific shell (git-shell or gitolite) do not like options.

This patch makes git-shell aware of the "--namespace" option.

Signed-off-by: Jiang Xin <worldhello....@gmail.com>
---
 shell.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/shell.c b/shell.c
index 66350b2..a619577 100644
--- a/shell.c
+++ b/shell.c
@@ -25,6 +25,50 @@ static int do_generic_cmd(const char *me, char *arg)
        return execv_git_cmd(my_argv);
 }
 
+static int do_git_with_opts_cmd(const char *me, char *arg)
+{
+       const char *allowed_cmds[] = {
+               "receive-pack",
+               "upload-pack",
+               "upload-archive",
+               NULL,
+       };
+       const char **user_argv, **p;
+       const char *cmd = NULL;
+       int count;
+
+       count = split_cmdline(arg, &user_argv);
+       if (count < 0) {
+               die ("Invalid command format '%s'\n", arg);
+       }
+
+       if (count == 3 && !strncmp("--namespace=", *user_argv, 12)) {
+               cmd = user_argv[1];
+               p = user_argv + 2;
+       } else if (count == 4 && !strcmp("--namespace", *user_argv)) {
+               cmd = user_argv[2];
+               p = user_argv + 3;
+       } else {
+               cmd = user_argv[0];
+               p = user_argv + 1;
+       }
+
+       if (cmd) {
+               /* last arg is path of repository */
+               if (!*p || *(p+1))
+                       die("bad argument");
+
+               for (p = allowed_cmds; *p; p++) {
+                       if (strcmp(*p, cmd))
+                               continue;
+                       setup_path();
+                       return execv_git_cmd(user_argv);
+               }
+       }
+
+       die("bad command");
+}
+
 static int do_cvs_cmd(const char *me, char *arg)
 {
        const char *cvsserver_argv[3] = {
@@ -138,6 +182,7 @@ static struct commands {
        { "git-receive-pack", do_generic_cmd },
        { "git-upload-pack", do_generic_cmd },
        { "git-upload-archive", do_generic_cmd },
+       { "git", do_git_with_opts_cmd },
        { "cvs", do_cvs_cmd },
        { NULL },
 };
@@ -185,7 +230,7 @@ int main(int argc, char **argv)
        }
 
        prog = xstrdup(argv[2]);
-       if (!strncmp(prog, "git", 3) && isspace(prog[3]))
+       if (!strncmp(prog, "git", 3) && isspace(prog[3]) && isalpha(prog[4]))
                /* Accept "git foo" as if the caller said "git-foo". */
                prog[3] = '-';
 
-- 
1.8.5.rc2.2.g0469850

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to