This configuration variable comes into effect when 'git clone' is invoked in an existing git repository. Instead of cloning the repository as-is, it relocates the gitdir of the repository to the path specified by this variable. Arguably, it does the right thing when working with submodules. Signed-off-by: Ramkumar Ramachandra <artagnon@xxxxxxxxx> --- builtin/clone.c | 29 +++++++++++++++++++++++++++++ environment.c | 11 ----------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/builtin/clone.c b/builtin/clone.c index e0aaf13..1b798e6 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -43,6 +43,7 @@ static char *option_template, *option_depth; static char *option_origin = NULL; static char *option_branch = NULL; static const char *real_git_dir; +static const char *submodule_gitdir; static char *option_upload_pack = "git-upload-pack"; static int option_verbosity; static int option_progress = -1; @@ -658,11 +659,22 @@ static void write_refspec_config(const char* src_ref_prefix, strbuf_release(&value); } +static int git_clone_config(const char *var, const char *value, void *cb) +{ + if (!strcmp(var, "clone.submodulegitdir")) { + git_config_string(&submodule_gitdir, var, value); + return 0; + } + return git_default_config(var, value, cb); +} + int cmd_clone(int argc, const char **argv, const char *prefix) { int is_bundle = 0, is_local; struct stat buf; const char *repo_name, *repo, *work_tree, *git_dir; + char dest_git_dir[PATH_MAX]; + char cwd[PATH_MAX]; char *path, *dir; int dest_exists; const struct ref *refs, *remote_head; @@ -676,6 +688,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) const char *src_ref_prefix = "refs/heads/"; struct remote *remote; int err = 0, complete_refs_before_fetch = 1; + int nongit = 1; struct refspec *refspec; const char *fetch_pattern; @@ -683,6 +696,14 @@ int cmd_clone(int argc, const char **argv, const char *prefix) junk_pid = getpid(); packet_trace_identity("clone"); + + /* setup_git_directory_gently without changing directories */ + getcwd(cwd, sizeof(cwd) - 1); + setup_git_directory_gently(&nongit); + chdir(cwd); + + git_config(git_clone_config, NULL); + argc = parse_options(argc, argv, prefix, builtin_clone_options, builtin_clone_usage, 0); @@ -736,6 +757,14 @@ int cmd_clone(int argc, const char **argv, const char *prefix) die(_("destination path '%s' already exists and is not " "an empty directory."), dir); + if (!nongit && submodule_gitdir) { + sprintf(dest_git_dir, "%s/%s.git", real_path(submodule_gitdir), dir); + if (!stat(dest_git_dir, &buf) && !is_empty_dir(dest_git_dir)) + die(_("destination path '%s' already exists and is not " + "an empty directory."), dest_git_dir); + real_git_dir = dest_git_dir; + } + strbuf_addf(&reflog_msg, "clone: from %s", repo); if (option_bare) diff --git a/environment.c b/environment.c index e2e75c1..9dce4c7 100644 --- a/environment.c +++ b/environment.c @@ -182,8 +182,6 @@ const char *strip_namespace(const char *namespaced_ref) return namespaced_ref + namespace_len; } -static int git_work_tree_initialized; - /* * Note. This works only before you used a work tree. This was added * primarily to support git-clone to work in a new repository it just @@ -191,15 +189,6 @@ static int git_work_tree_initialized; */ void set_git_work_tree(const char *new_work_tree) { - if (git_work_tree_initialized) { - new_work_tree = real_path(new_work_tree); - if (strcmp(new_work_tree, work_tree)) - die("internal error: work tree has already been set\n" - "Current worktree: %s\nNew worktree: %s", - work_tree, new_work_tree); - return; - } - git_work_tree_initialized = 1; work_tree = xstrdup(real_path(new_work_tree)); } -- 1.8.2.380.g0d4e79b -- 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