diff options
| author | Junio C Hamano <gitster@pobox.com> | 2017-01-10 15:24:27 -0800 | 
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2017-01-10 15:24:28 -0800 | 
| commit | da2b74eeec0b12d7b20d34a5e284295f81ad40a8 (patch) | |
| tree | 3259c3bf07a1439bb3be7f57b352aa58d609c318 /submodule.c | |
| parent | 2ced5f2c2ddcfe3a45d75ae1d552c11cad70236d (diff) | |
| parent | 7c4be458b1c7ba81b0cc63d76a144261eb2395be (diff) | |
| download | git-da2b74eeec0b12d7b20d34a5e284295f81ad40a8.tar.gz | |
Merge branch 'sb/submodule-embed-gitdir'
A new submodule helper "git submodule embedgitdirs" to make it
easier to move embedded .git/ directory for submodules in a
superproject to .git/modules/ (and point the latter with the former
that is turned into a "gitdir:" file) has been added.
* sb/submodule-embed-gitdir:
  worktree: initialize return value for submodule_uses_worktrees
  submodule: add absorb-git-dir function
  move connect_work_tree_and_git_dir to dir.h
  worktree: check if a submodule uses worktrees
  test-lib-functions.sh: teach test_commit -C <dir>
  submodule helper: support super prefix
  submodule: use absolute path for computing relative path connecting
Diffstat (limited to 'submodule.c')
| -rw-r--r-- | submodule.c | 127 | 
1 files changed, 103 insertions, 24 deletions
| diff --git a/submodule.c b/submodule.c index ece17315d6..73521cdbb2 100644 --- a/submodule.c +++ b/submodule.c @@ -14,6 +14,7 @@  #include "blob.h"  #include "thread-utils.h"  #include "quote.h" +#include "worktree.h"  static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;  static int parallel_jobs = 1; @@ -1296,30 +1297,6 @@ int merge_submodule(unsigned char result[20], const char *path,  	return 0;  } -/* Update gitfile and core.worktree setting to connect work tree and git dir */ -void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir) -{ -	struct strbuf file_name = STRBUF_INIT; -	struct strbuf rel_path = STRBUF_INIT; -	const char *real_work_tree = xstrdup(real_path(work_tree)); - -	/* Update gitfile */ -	strbuf_addf(&file_name, "%s/.git", work_tree); -	write_file(file_name.buf, "gitdir: %s", -		   relative_path(git_dir, real_work_tree, &rel_path)); - -	/* Update core.worktree setting */ -	strbuf_reset(&file_name); -	strbuf_addf(&file_name, "%s/config", git_dir); -	git_config_set_in_file(file_name.buf, "core.worktree", -			       relative_path(real_work_tree, git_dir, -					     &rel_path)); - -	strbuf_release(&file_name); -	strbuf_release(&rel_path); -	free((void *)real_work_tree); -} -  int parallel_submodules(void)  {  	return parallel_jobs; @@ -1335,3 +1312,105 @@ void prepare_submodule_repo_env(struct argv_array *out)  	}  	argv_array_push(out, "GIT_DIR=.git");  } + +/* + * Embeds a single submodules git directory into the superprojects git dir, + * non recursively. + */ +static void relocate_single_git_dir_into_superproject(const char *prefix, +						      const char *path) +{ +	char *old_git_dir = NULL, *real_old_git_dir = NULL, *real_new_git_dir = NULL; +	const char *new_git_dir; +	const struct submodule *sub; + +	if (submodule_uses_worktrees(path)) +		die(_("relocate_gitdir for submodule '%s' with " +		      "more than one worktree not supported"), path); + +	old_git_dir = xstrfmt("%s/.git", path); +	if (read_gitfile(old_git_dir)) +		/* If it is an actual gitfile, it doesn't need migration. */ +		return; + +	real_old_git_dir = xstrdup(real_path(old_git_dir)); + +	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); +	real_new_git_dir = xstrdup(real_path(new_git_dir)); + +	if (!prefix) +		prefix = get_super_prefix(); + +	fprintf(stderr, _("Migrating git directory of '%s%s' from\n'%s' to\n'%s'\n"), +		prefix ? prefix : "", path, +		real_old_git_dir, real_new_git_dir); + +	relocate_gitdir(path, real_old_git_dir, real_new_git_dir); + +	free(old_git_dir); +	free(real_old_git_dir); +	free(real_new_git_dir); +} + +/* + * Migrate the git directory of the submodule given by path from + * having its git directory within the working tree to the git dir nested + * in its superprojects git dir under modules/. + */ +void absorb_git_dir_into_superproject(const char *prefix, +				      const char *path, +				      unsigned flags) +{ +	const char *sub_git_dir, *v; +	char *real_sub_git_dir = NULL, *real_common_git_dir = NULL; +	struct strbuf gitdir = STRBUF_INIT; + +	strbuf_addf(&gitdir, "%s/.git", path); +	sub_git_dir = resolve_gitdir(gitdir.buf); + +	/* Not populated? */ +	if (!sub_git_dir) +		goto out; + +	/* Is it already absorbed into the superprojects git dir? */ +	real_sub_git_dir = xstrdup(real_path(sub_git_dir)); +	real_common_git_dir = xstrdup(real_path(get_git_common_dir())); +	if (!skip_prefix(real_sub_git_dir, real_common_git_dir, &v)) +		relocate_single_git_dir_into_superproject(prefix, path); + +	if (flags & ABSORB_GITDIR_RECURSE_SUBMODULES) { +		struct child_process cp = CHILD_PROCESS_INIT; +		struct strbuf sb = STRBUF_INIT; + +		if (flags & ~ABSORB_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", +					   "absorb-git-dirs", NULL); +		prepare_submodule_repo_env(&cp.env_array); +		if (run_command(&cp)) +			die(_("could not recurse into submodule '%s'"), path); + +		strbuf_release(&sb); +	} + +out: +	strbuf_release(&gitdir); +	free(real_sub_git_dir); +	free(real_common_git_dir); +} | 
