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.net@xxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html