diff options
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 78 |
1 files changed, 78 insertions, 0 deletions
@@ -15,6 +15,9 @@ #include "utf8.h" #include "varint.h" #include "ewah/ewok.h" +#include "submodule-config.h" +#include "run-command.h" +#include "worktree.h" struct path_simplify { int len; @@ -2748,3 +2751,78 @@ void untracked_cache_add_to_index(struct index_state *istate, { untracked_cache_invalidate_path(istate, path); } + +/* + * Migrate the given submodule (and all its submodules recursively) from + * having its git directory within the working tree to the git dir nested + * in its superprojects git dir under modules/. + */ +void relocate_gitdir(const char *prefix, const char *path, unsigned flags) +{ + char *old_git_dir; + const char *new_git_dir; + const struct submodule *sub; + struct worktree **worktrees; + int i; + + worktrees = get_submodule_worktrees(path); + for (i = 0; worktrees[i]; i++) + ; + if (i > 1) + die(_("relocate_gitdir for submodule with more than one worktree not supported")); + + old_git_dir = xstrfmt("%s/.git", path); + if (read_gitfile(old_git_dir)) + /* If it is an actual gitfile, it doesn't need migration. */ + goto out; + + sub = submodule_from_path(null_sha1, path); + if (!sub) + die(_("Could not lookup name for submodule '%s'"), + path); + + new_git_dir = git_path("modules/%s", sub->name); + if (safe_create_leading_directories_const(new_git_dir) < 0) + die(_("could not create directory '%s'"), new_git_dir); + + if (!prefix) + prefix = get_super_prefix(); + printf("Migrating git directory of %s%s from\n'%s' to\n'%s'\n", + prefix ? prefix : "", path, + real_path(old_git_dir), new_git_dir); + + if (rename(old_git_dir, new_git_dir) < 0) + die_errno(_("Could not migrate git directory from '%s' to '%s'"), + old_git_dir, new_git_dir); + + connect_work_tree_and_git_dir(path, new_git_dir); + +out: + if (flags & RELOCATE_GITDIR_RECURSE_SUBMODULES) { + struct child_process cp = CHILD_PROCESS_INIT; + struct strbuf sb = STRBUF_INIT; + + if (flags & ~RELOCATE_GITDIR_RECURSE_SUBMODULES) + die("BUG: we don't know how to pass the flags down?"); + + if (get_super_prefix()) + strbuf_addstr(&sb, get_super_prefix()); + strbuf_addstr(&sb, path); + strbuf_addch(&sb, '/'); + + cp.dir = path; + cp.git_cmd = 1; + cp.no_stdin = 1; + argv_array_pushl(&cp.args, "--super-prefix", sb.buf, + "submodule--helper", + "embed-git-dirs", NULL); + prepare_submodule_repo_env(&cp.env_array); + if (run_command(&cp)) + die(_("Could not migrate git directory in submodule '%s'"), + path); + + strbuf_release(&sb); + } + + free(old_git_dir); +} |