This teaches receive-pack to create a new directory as a bare repository when a user tries to push into a directory that does not exist. Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> --- "Shawn O. Pearce" <spearce@xxxxxxxxxxx> writes: > But I think that's only true for situations where you are likely the > owner of the repository in your own home directory, such as ~you > on kernel.org. For "hosted repositories" like any of the systems > you described above, there is a lot more to the creation than just > executing "git init" somewhere. > . > For the usage of > creating a new repository in your own home directory on some remote > server, why isn't this just an option to git push? I am not at all convinced that the use case people would for whatever reason do not want to "ssh-in, create and then push from here" is limited to "your own playpen in your $HOME", but it certainly limits the complexity and the scope of the damage. builtin-receive-pack.c | 29 ++++++++++++++++++++++++++++- t/t5541-push-create.sh | 20 ++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletions(-) create mode 100755 t/t5541-push-create.sh diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c index 849f1fe..2f2831c 100644 --- a/builtin-receive-pack.c +++ b/builtin-receive-pack.c @@ -652,6 +652,33 @@ static void add_alternate_refs(void) foreach_alt_odb(add_refs_from_alternate, NULL); } +static char *create_new_repo(char *dir) +{ + struct child_process child; + const char *argv[20]; + int argc; + + if (mkdir(dir, 0777)) { + error("cannot mkdir '%s': %s", dir, strerror(errno)); + return NULL; + } + argc = 0; + argv[argc++] = "init"; + argv[argc++] = "--bare"; + argv[argc++] = NULL; + child.argv = argv; + if (run_command_v_opt_cd_env(argv, + RUN_COMMAND_NO_STDIN | + RUN_COMMAND_STDOUT_TO_STDERR | + RUN_GIT_CMD, + dir, + NULL)) { + error("cannot run git init"); + return NULL; + } + return enter_repo(dir, 0); +} + int cmd_receive_pack(int argc, const char **argv, const char *prefix) { int i; @@ -674,7 +701,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) setup_path(); - if (!enter_repo(dir, 0)) + if (!enter_repo(dir, 0) && !create_new_repo(dir)) die("'%s': unable to chdir or not a git archive", dir); if (is_repository_shallow()) diff --git a/t/t5541-push-create.sh b/t/t5541-push-create.sh new file mode 100755 index 0000000..52558a5 --- /dev/null +++ b/t/t5541-push-create.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +test_description='push into nonexisting repository' + +. ./test-lib.sh + +test_expect_success setup ' + test_commit A && + test_commit B && + test_commit C +' + +test_expect_success 'push into nonexisting repository' ' + this=$(git rev-parse B) && + git push "file://$(pwd)/not-here.git" B:refs/heads/master && + that=$(GIT_DIR=not-here.git git rev-parse HEAD) && + test "$this" = "$that" +' + +test_done -- 1.6.2.rc2.123.gab4478 -- 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