git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] Add init-serve, the remote side of "git init --remote=host:path"
@ 2009-02-28 21:12 Junio C Hamano
  2009-02-28 21:13 ` [PATCH 2/2] " Junio C Hamano
  2009-03-01  0:04 ` [PATCH 1/2] Add init-serve, the remote side of " Junio C Hamano
  0 siblings, 2 replies; 3+ messages in thread
From: Junio C Hamano @ 2009-02-28 21:12 UTC (permalink / raw)
  To: git

This is still sprinkled with a few NEEDSWORK, but should be good enough
to start developing and testing the requesting side of the protocol pair.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Makefile             |    1 +
 builtin-init-serve.c |  117 ++++++++++++++++++++++++++++++++++++++++++++++++++
 builtin.h            |    1 +
 git.c                |    1 +
 4 files changed, 120 insertions(+), 0 deletions(-)
 create mode 100644 builtin-init-serve.c

diff --git a/Makefile b/Makefile
index 0675c43..c0d0cfd 100644
--- a/Makefile
+++ b/Makefile
@@ -544,6 +544,7 @@ BUILTIN_OBJS += builtin-gc.o
 BUILTIN_OBJS += builtin-grep.o
 BUILTIN_OBJS += builtin-help.o
 BUILTIN_OBJS += builtin-init-db.o
+BUILTIN_OBJS += builtin-init-serve.o
 BUILTIN_OBJS += builtin-log.o
 BUILTIN_OBJS += builtin-ls-files.o
 BUILTIN_OBJS += builtin-ls-remote.o
diff --git a/builtin-init-serve.c b/builtin-init-serve.c
new file mode 100644
index 0000000..9d701e7
--- /dev/null
+++ b/builtin-init-serve.c
@@ -0,0 +1,117 @@
+#include "cache.h"
+#include "builtin.h"
+#include "pkt-line.h"
+#include "run-command.h"
+#include "strbuf.h"
+
+/*
+ * The other end gives the command line arguments to "git init"
+ * one by one over pkt-line, and then expects a message back.
+ *
+ * We need to read them all even if we know we will reject
+ * the request before responding.
+ */
+static int serve(const char *errmsg)
+{
+	int argc = 0;
+	const char *argv[64];
+
+	argv[argc++] = "git";
+	argv[argc++] = "init";
+	for (;;) {
+		char line[1000];
+		int len;
+
+		len = packet_read_line(0, line, sizeof(line));
+		if (!len)
+			break;
+
+		if (!*errmsg) {
+			/*
+			 * Notice any command line arguments that we
+			 * may not want to invoke "git init" with when
+			 * we are doing this remotely, and reject the
+			 * request.
+			 */
+			if (!prefixcmp(line, "--template=")) {
+				static char err[1000];
+				snprintf(err, sizeof(err),
+					 "forbidden option to 'git init': %s",
+					 line);
+				errmsg = err;
+			} else if (argc + 1 < ARRAY_SIZE(argv))
+				argv[argc++] = xstrdup(line);
+			else
+				errmsg = "arg list too long";
+		}
+	}
+
+	if (*errmsg)
+		packet_write(1, "ng init - %s\n", errmsg);
+	else {
+		/*
+		 * NEEDSWORK: refactor this list in the codepath for
+		 * local pipe transport in connect.c and use it here
+		 * and also over there.
+		 */
+		const char *sanitize_env[] = {
+			ALTERNATE_DB_ENVIRONMENT,
+			DB_ENVIRONMENT,
+			GIT_DIR_ENVIRONMENT,
+			GIT_WORK_TREE_ENVIRONMENT,
+			GRAFT_ENVIRONMENT,
+			INDEX_ENVIRONMENT,
+			NULL
+		};
+		struct child_process child;
+
+		argv[argc] = NULL;
+		memset(&child, 0, sizeof(child));
+		child.argv = argv;
+		child.env = sanitize_env;
+
+		/*
+		 * NEEDSWORK: I do not currently think it is worth it,
+		 * but this might want to set up and use the sideband
+		 * to capture and send output from the child back to
+		 * the requestor.  At least this comment needs to be removed
+		 * once we make the decision.
+		 */
+		child.stdout_to_stderr = 1;
+
+		/*
+		 * NEEDSWORK: we might want to distinguish various
+		 * error codes from run_command() and return different
+		 * messages back.  I am too lazy to be bothered.
+		 */
+		if (run_command(&child))
+			packet_write(1, "ng init\n");
+		else
+			packet_write(1, "ok init\n");
+	}
+	return 0;
+}
+
+int cmd_init_serve(int argc, const char **argv, const char *prefix)
+{
+	const char *dir;
+	struct strbuf errmsg = STRBUF_INIT;
+
+	if (argc != 2)
+		return serve("init /p/a/th");
+	dir = argv[1];
+
+	/*
+	 * Perhaps lift avoid_alias() from daemon.c and check
+	 * dir with it, as programs like gitosis may
+	 * want to restrict the arguments to this service.
+	 */
+	if (mkdir(dir, 0777))
+		strbuf_addf(&errmsg,
+			    "cannot mkdir('%s'): %s", dir, strerror(errno));
+	else if (chdir(dir))
+		strbuf_addf(&errmsg,
+			    "cannot chdir('%s'): %s", dir, strerror(errno));
+
+	return serve(errmsg.buf);
+}
diff --git a/builtin.h b/builtin.h
index 1495cf6..e9f9ffb 100644
--- a/builtin.h
+++ b/builtin.h
@@ -59,6 +59,7 @@ extern int cmd_grep(int argc, const char **argv, const char *prefix);
 extern int cmd_help(int argc, const char **argv, const char *prefix);
 extern int cmd_http_fetch(int argc, const char **argv, const char *prefix);
 extern int cmd_init_db(int argc, const char **argv, const char *prefix);
+extern int cmd_init_serve(int argc, const char **argv, const char *prefix);
 extern int cmd_log(int argc, const char **argv, const char *prefix);
 extern int cmd_log_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
diff --git a/git.c b/git.c
index c2b181e..1df8584 100644
--- a/git.c
+++ b/git.c
@@ -311,6 +311,7 @@ static void handle_internal_command(int argc, const char **argv)
 #endif
 		{ "init", cmd_init_db },
 		{ "init-db", cmd_init_db },
+		{ "init-serve", cmd_init_serve },
 		{ "log", cmd_log, RUN_SETUP | USE_PAGER },
 		{ "ls-files", cmd_ls_files, RUN_SETUP },
 		{ "ls-tree", cmd_ls_tree, RUN_SETUP },
-- 
1.6.2.rc2.99.g9f3bb

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] "git init --remote=host:path"
  2009-02-28 21:12 [PATCH 1/2] Add init-serve, the remote side of "git init --remote=host:path" Junio C Hamano
@ 2009-02-28 21:13 ` Junio C Hamano
  2009-03-01  0:04 ` [PATCH 1/2] Add init-serve, the remote side of " Junio C Hamano
  1 sibling, 0 replies; 3+ messages in thread
From: Junio C Hamano @ 2009-02-28 21:13 UTC (permalink / raw)
  To: git

This implements the requesting side of the pair.

It probably should take the same --exec=init-serve parameter similar to
the way other programs like receive-pack and send-pack does, but I am too
lazy to add it.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin-init-db.c |   34 +++++++++++++++++++++++++++++++++-
 t/t0001-init.sh   |    7 +++++++
 2 files changed, 40 insertions(+), 1 deletions(-)

diff --git a/builtin-init-db.c b/builtin-init-db.c
index ee3911f..0b6da70 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -6,6 +6,7 @@
 #include "cache.h"
 #include "builtin.h"
 #include "exec_cmd.h"
+#include "pkt-line.h"
 
 #ifndef DEFAULT_GIT_TEMPLATE_DIR
 #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates"
@@ -363,6 +364,33 @@ static int guess_repository_type(const char *git_dir)
 	return 1;
 }
 
+static int remote_init(const char *remote, int argc, const char **argv)
+{
+	struct child_process *child;
+	int fd[2], i, len, status;
+	char line[1000];
+
+	child = git_connect(fd, remote, "git init-serve", 0);
+	for (i = 1; i < argc; i++) {
+		fprintf(stderr, "writing %d (%s)\n", i, argv[i]);
+		packet_write(fd[1], argv[i]);
+	}
+	packet_flush(fd[1]);
+
+	status = 0;
+	len = packet_read_line(fd[0], line, sizeof(line));
+	if (len < 3 ||
+	    (memcmp(line, "ok ", 3) && memcmp(line, "ng ", 3)))
+		die("protocol error: %s\n", line);
+
+	if (line[0] != 'o') {
+		error("%s", line);
+		status = -1;
+	}
+	status |= finish_connect(child);
+	return status;
+}
+
 static const char init_db_usage[] =
 "git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
 
@@ -394,7 +422,11 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 			init_shared_repository = git_config_perm("arg", arg+9);
 		else if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet"))
 			flags |= INIT_DB_QUIET;
-		else
+		else if (!prefixcmp(arg, "--remote=")) {
+			if (i != 1)
+				die("--remote option must be given first");
+			return remote_init(arg+9, argc-1, argv+1);
+		} else
 			usage(init_db_usage);
 	}
 
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 5ac0a27..d1069ee 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -199,4 +199,11 @@ test_expect_success 'init honors global core.sharedRepository' '
 	x`git config -f shared-honor-global/.git/config core.sharedRepository`
 '
 
+test_expect_success 'init --remote' '
+	R="$(pwd)/test-of-remote" &&
+	git init --remote="$R" --bare &&
+	test -d "$R/objects/pack" &&
+	test_must_fail git init --remote="$R"
+'
+
 test_done
-- 
1.6.2.rc2.99.g9f3bb

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 1/2] Add init-serve, the remote side of "git init --remote=host:path"
  2009-02-28 21:12 [PATCH 1/2] Add init-serve, the remote side of "git init --remote=host:path" Junio C Hamano
  2009-02-28 21:13 ` [PATCH 2/2] " Junio C Hamano
@ 2009-03-01  0:04 ` Junio C Hamano
  1 sibling, 0 replies; 3+ messages in thread
From: Junio C Hamano @ 2009-03-01  0:04 UTC (permalink / raw)
  To: git

I've cleaned up the series somewhat and now it is two independent clean-up
followed by the updated version of these two patches.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-03-01  0:05 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-28 21:12 [PATCH 1/2] Add init-serve, the remote side of "git init --remote=host:path" Junio C Hamano
2009-02-28 21:13 ` [PATCH 2/2] " Junio C Hamano
2009-03-01  0:04 ` [PATCH 1/2] Add init-serve, the remote side of " Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).