{"thread":{"id":"18070","subject":"[PATCH 1/2] Add init-serve, the remote side of \"git init --remote=host:path\"","startedAt":"2009-02-28T21:12:23Z","lastAt":"2009-03-01T00:04:19Z","messageCount":3,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"106555","messageId":"7vsklye05k.fsf@gitster.siamese.dyndns.org","threadId":"18070","inReplyTo":null,"subject":"[PATCH 1/2] Add init-serve, the remote side of \"git init --remote=host:path\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-28T21:12:23Z","receivedAt":"2009-02-28T21:12:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This is still sprinkled with a few NEEDSWORK, but should be good enough\nto start developing and testing the requesting side of the protocol pair.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Makefile             |    1 +\n builtin-init-serve.c |  117 ++++++++++++++++++++++++++++++++++++++++++++++++++\n builtin.h            |    1 +\n git.c                |    1 +\n 4 files changed, 120 insertions(+), 0 deletions(-)\n create mode 100644 builtin-init-serve.c\n\ndiff --git a/Makefile b/Makefile\nindex 0675c43..c0d0cfd 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -544,6 +544,7 @@ BUILTIN_OBJS += builtin-gc.o\n BUILTIN_OBJS += builtin-grep.o\n BUILTIN_OBJS += builtin-help.o\n BUILTIN_OBJS += builtin-init-db.o\n+BUILTIN_OBJS += builtin-init-serve.o\n BUILTIN_OBJS += builtin-log.o\n BUILTIN_OBJS += builtin-ls-files.o\n BUILTIN_OBJS += builtin-ls-remote.o\ndiff --git a/builtin-init-serve.c b/builtin-init-serve.c\nnew file mode 100644\nindex 0000000..9d701e7\n--- /dev/null\n+++ b/builtin-init-serve.c\n@@ -0,0 +1,117 @@\n+#include \"cache.h\"\n+#include \"builtin.h\"\n+#include \"pkt-line.h\"\n+#include \"run-command.h\"\n+#include \"strbuf.h\"\n+\n+/*\n+ * The other end gives the command line arguments to \"git init\"\n+ * one by one over pkt-line, and then expects a message back.\n+ *\n+ * We need to read them all even if we know we will reject\n+ * the request before responding.\n+ */\n+static int serve(const char *errmsg)\n+{\n+\tint argc = 0;\n+\tconst char *argv[64];\n+\n+\targv[argc++] = \"git\";\n+\targv[argc++] = \"init\";\n+\tfor (;;) {\n+\t\tchar line[1000];\n+\t\tint len;\n+\n+\t\tlen = packet_read_line(0, line, sizeof(line));\n+\t\tif (!len)\n+\t\t\tbreak;\n+\n+\t\tif (!*errmsg) {\n+\t\t\t/*\n+\t\t\t * Notice any command line arguments that we\n+\t\t\t * may not want to invoke \"git init\" with when\n+\t\t\t * we are doing this remotely, and reject the\n+\t\t\t * request.\n+\t\t\t */\n+\t\t\tif (!prefixcmp(line, \"--template=\")) {\n+\t\t\t\tstatic char err[1000];\n+\t\t\t\tsnprintf(err, sizeof(err),\n+\t\t\t\t\t \"forbidden option to 'git init': %s\",\n+\t\t\t\t\t line);\n+\t\t\t\terrmsg = err;\n+\t\t\t} else if (argc + 1 < ARRAY_SIZE(argv))\n+\t\t\t\targv[argc++] = xstrdup(line);\n+\t\t\telse\n+\t\t\t\terrmsg = \"arg list too long\";\n+\t\t}\n+\t}\n+\n+\tif (*errmsg)\n+\t\tpacket_write(1, \"ng init - %s\\n\", errmsg);\n+\telse {\n+\t\t/*\n+\t\t * NEEDSWORK: refactor this list in the codepath for\n+\t\t * local pipe transport in connect.c and use it here\n+\t\t * and also over there.\n+\t\t */\n+\t\tconst char *sanitize_env[] = {\n+\t\t\tALTERNATE_DB_ENVIRONMENT,\n+\t\t\tDB_ENVIRONMENT,\n+\t\t\tGIT_DIR_ENVIRONMENT,\n+\t\t\tGIT_WORK_TREE_ENVIRONMENT,\n+\t\t\tGRAFT_ENVIRONMENT,\n+\t\t\tINDEX_ENVIRONMENT,\n+\t\t\tNULL\n+\t\t};\n+\t\tstruct child_process child;\n+\n+\t\targv[argc] = NULL;\n+\t\tmemset(&child, 0, sizeof(child));\n+\t\tchild.argv = argv;\n+\t\tchild.env = sanitize_env;\n+\n+\t\t/*\n+\t\t * NEEDSWORK: I do not currently think it is worth it,\n+\t\t * but this might want to set up and use the sideband\n+\t\t * to capture and send output from the child back to\n+\t\t * the requestor.  At least this comment needs to be removed\n+\t\t * once we make the decision.\n+\t\t */\n+\t\tchild.stdout_to_stderr = 1;\n+\n+\t\t/*\n+\t\t * NEEDSWORK: we might want to distinguish various\n+\t\t * error codes from run_command() and return different\n+\t\t * messages back.  I am too lazy to be bothered.\n+\t\t */\n+\t\tif (run_command(&child))\n+\t\t\tpacket_write(1, \"ng init\\n\");\n+\t\telse\n+\t\t\tpacket_write(1, \"ok init\\n\");\n+\t}\n+\treturn 0;\n+}\n+\n+int cmd_init_serve(int argc, const char **argv, const char *prefix)\n+{\n+\tconst char *dir;\n+\tstruct strbuf errmsg = STRBUF_INIT;\n+\n+\tif (argc != 2)\n+\t\treturn serve(\"init /p/a/th\");\n+\tdir = argv[1];\n+\n+\t/*\n+\t * Perhaps lift avoid_alias() from daemon.c and check\n+\t * dir with it, as programs like gitosis may\n+\t * want to restrict the arguments to this service.\n+\t */\n+\tif (mkdir(dir, 0777))\n+\t\tstrbuf_addf(&errmsg,\n+\t\t\t    \"cannot mkdir('%s'): %s\", dir, strerror(errno));\n+\telse if (chdir(dir))\n+\t\tstrbuf_addf(&errmsg,\n+\t\t\t    \"cannot chdir('%s'): %s\", dir, strerror(errno));\n+\n+\treturn serve(errmsg.buf);\n+}\ndiff --git a/builtin.h b/builtin.h\nindex 1495cf6..e9f9ffb 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -59,6 +59,7 @@ extern int cmd_grep(int argc, const char **argv, const char *prefix);\n extern int cmd_help(int argc, const char **argv, const char *prefix);\n extern int cmd_http_fetch(int argc, const char **argv, const char *prefix);\n extern int cmd_init_db(int argc, const char **argv, const char *prefix);\n+extern int cmd_init_serve(int argc, const char **argv, const char *prefix);\n extern int cmd_log(int argc, const char **argv, const char *prefix);\n extern int cmd_log_reflog(int argc, const char **argv, const char *prefix);\n extern int cmd_ls_files(int argc, const char **argv, const char *prefix);\ndiff --git a/git.c b/git.c\nindex c2b181e..1df8584 100644\n--- a/git.c\n+++ b/git.c\n@@ -311,6 +311,7 @@ static void handle_internal_command(int argc, const char **argv)\n #endif\n \t\t{ \"init\", cmd_init_db },\n \t\t{ \"init-db\", cmd_init_db },\n+\t\t{ \"init-serve\", cmd_init_serve },\n \t\t{ \"log\", cmd_log, RUN_SETUP | USE_PAGER },\n \t\t{ \"ls-files\", cmd_ls_files, RUN_SETUP },\n \t\t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n-- \n1.6.2.rc2.99.g9f3bb\n"},{"id":"106556","messageId":"7vocwme03b.fsf@gitster.siamese.dyndns.org","threadId":"18070","inReplyTo":"7vsklye05k.fsf@gitster.siamese.dyndns.org","subject":"[PATCH 2/2] \"git init --remote=host:path\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-28T21:13:44Z","receivedAt":"2009-02-28T21:13:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This implements the requesting side of the pair.\n\nIt probably should take the same --exec=init-serve parameter similar to\nthe way other programs like receive-pack and send-pack does, but I am too\nlazy to add it.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-init-db.c |   34 +++++++++++++++++++++++++++++++++-\n t/t0001-init.sh   |    7 +++++++\n 2 files changed, 40 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin-init-db.c b/builtin-init-db.c\nindex ee3911f..0b6da70 100644\n--- a/builtin-init-db.c\n+++ b/builtin-init-db.c\n@@ -6,6 +6,7 @@\n #include \"cache.h\"\n #include \"builtin.h\"\n #include \"exec_cmd.h\"\n+#include \"pkt-line.h\"\n \n #ifndef DEFAULT_GIT_TEMPLATE_DIR\n #define DEFAULT_GIT_TEMPLATE_DIR \"/usr/share/git-core/templates\"\n@@ -363,6 +364,33 @@ static int guess_repository_type(const char *git_dir)\n \treturn 1;\n }\n \n+static int remote_init(const char *remote, int argc, const char **argv)\n+{\n+\tstruct child_process *child;\n+\tint fd[2], i, len, status;\n+\tchar line[1000];\n+\n+\tchild = git_connect(fd, remote, \"git init-serve\", 0);\n+\tfor (i = 1; i < argc; i++) {\n+\t\tfprintf(stderr, \"writing %d (%s)\\n\", i, argv[i]);\n+\t\tpacket_write(fd[1], argv[i]);\n+\t}\n+\tpacket_flush(fd[1]);\n+\n+\tstatus = 0;\n+\tlen = packet_read_line(fd[0], line, sizeof(line));\n+\tif (len < 3 ||\n+\t    (memcmp(line, \"ok \", 3) && memcmp(line, \"ng \", 3)))\n+\t\tdie(\"protocol error: %s\\n\", line);\n+\n+\tif (line[0] != 'o') {\n+\t\terror(\"%s\", line);\n+\t\tstatus = -1;\n+\t}\n+\tstatus |= finish_connect(child);\n+\treturn status;\n+}\n+\n static const char init_db_usage[] =\n \"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]\";\n \n@@ -394,7 +422,11 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)\n \t\t\tinit_shared_repository = git_config_perm(\"arg\", arg+9);\n \t\telse if (!strcmp(arg, \"-q\") || !strcmp(arg, \"--quiet\"))\n \t\t\tflags |= INIT_DB_QUIET;\n-\t\telse\n+\t\telse if (!prefixcmp(arg, \"--remote=\")) {\n+\t\t\tif (i != 1)\n+\t\t\t\tdie(\"--remote option must be given first\");\n+\t\t\treturn remote_init(arg+9, argc-1, argv+1);\n+\t\t} else\n \t\t\tusage(init_db_usage);\n \t}\n \ndiff --git a/t/t0001-init.sh b/t/t0001-init.sh\nindex 5ac0a27..d1069ee 100755\n--- a/t/t0001-init.sh\n+++ b/t/t0001-init.sh\n@@ -199,4 +199,11 @@ test_expect_success 'init honors global core.sharedRepository' '\n \tx`git config -f shared-honor-global/.git/config core.sharedRepository`\n '\n \n+test_expect_success 'init --remote' '\n+\tR=\"$(pwd)/test-of-remote\" &&\n+\tgit init --remote=\"$R\" --bare &&\n+\ttest -d \"$R/objects/pack\" &&\n+\ttest_must_fail git init --remote=\"$R\"\n+'\n+\n test_done\n-- \n1.6.2.rc2.99.g9f3bb\n"},{"id":"106564","messageId":"7vbpsmds70.fsf@gitster.siamese.dyndns.org","threadId":"18070","inReplyTo":"7vsklye05k.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/2] Add init-serve, the remote side of \"git init --remote=host:path\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-01T00:04:19Z","receivedAt":"2009-03-01T00:04:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"I've cleaned up the series somewhat and now it is two independent clean-up\nfollowed by the updated version of these two patches.\n"}]}