From: Jens Lehmann <Jens.Lehmann@xxxxxx> Date: Mon, 18 Jun 2012 22:11:45 +0200 Signed-off-by: Jens Lehmann <Jens.Lehmann@xxxxxx> Signed-off-by: Jonathan Nieder <jrnieder@xxxxxxxxx> --- Neat. Would probably be clearer with some of the corresponding tests squashed in to illustrate the intended behavior. entry.c | 4 ++++ submodule.c | 44 +++++++++++++++++++++++++++++++++++++++++--- submodule.h | 1 + unpack-trees.c | 19 +++++++++++++++++++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/entry.c b/entry.c index 7b7aa81..d1bf6ec 100644 --- a/entry.c +++ b/entry.c @@ -2,6 +2,7 @@ #include "blob.h" #include "dir.h" #include "streaming.h" +#include "submodule.h" static void create_directories(const char *path, int path_len, const struct checkout *state) @@ -203,6 +204,9 @@ static int write_entry(struct cache_entry *ce, return error("cannot create temporary submodule %s", path); if (mkdir(path, 0777) < 0) return error("cannot create submodule directory %s", path); + if (submodule_needs_update(path) && + populate_submodule(path, ce->sha1, state->force)) + return error("cannot checkout submodule %s", path); break; default: return error("unknown file mode for %s in index", path); diff --git a/submodule.c b/submodule.c index a25db46..06df5ae 100644 --- a/submodule.c +++ b/submodule.c @@ -412,6 +412,42 @@ int submodule_needs_update(const char *path) return config_update_recurse_submodules != RECURSE_SUBMODULES_OFF; } +int populate_submodule(const char *path, unsigned char sha1[20], int force) +{ + struct string_list_item *path_option; + const char *name, *real_git_dir; + struct strbuf buf = STRBUF_INIT; + struct child_process cp; + const char *argv[] = {"read-tree", force ? "--reset" : "-m", "-u", NULL, NULL}; + + path_option = unsorted_string_list_lookup(&config_name_for_path, path); + if (!path_option) + return 0; + + name = path_option->util; + + strbuf_addf(&buf, "%s/modules/%s", resolve_gitdir(get_git_dir()), name); + real_git_dir = resolve_gitdir(buf.buf); + if (!real_git_dir) + goto out; + connect_work_tree_and_git_dir(path, real_git_dir); + + /* Run read-tree --reset sha1 */ + memset(&cp, 0, sizeof(cp)); + cp.argv = argv; + cp.env = local_repo_env; + cp.git_cmd = 1; + cp.no_stdin = 1; + cp.dir = path; + argv[3] = sha1_to_hex(sha1); + if (run_command(&cp)) + warning(_("Checking out submodule %s failed"), path); + +out: + strbuf_release(&buf); + return 0; +} + int depopulate_submodule(const char *path) { struct strbuf dot_git = STRBUF_INIT; @@ -1207,6 +1243,7 @@ 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_git_dir = xstrdup(real_path(git_dir)); const char *real_work_tree = xstrdup(real_path(work_tree)); FILE *fp; @@ -1215,15 +1252,15 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir) fp = fopen(file_name.buf, "w"); if (!fp) die(_("Could not create git link %s"), file_name.buf); - fprintf(fp, "gitdir: %s\n", relative_path(git_dir, real_work_tree, + fprintf(fp, "gitdir: %s\n", relative_path(real_git_dir, real_work_tree, &rel_path)); fclose(fp); /* Update core.worktree setting */ strbuf_reset(&file_name); - strbuf_addf(&file_name, "%s/config", git_dir); + strbuf_addf(&file_name, "%s/config", real_git_dir); if (git_config_set_in_file(file_name.buf, "core.worktree", - relative_path(real_work_tree, git_dir, + relative_path(real_work_tree, real_git_dir, &rel_path))) die(_("Could not set core.worktree in %s"), file_name.buf); @@ -1231,4 +1268,5 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir) strbuf_release(&file_name); strbuf_release(&rel_path); free((void *)real_work_tree); + free((void *)real_git_dir); } diff --git a/submodule.h b/submodule.h index df291cf..3657ca8 100644 --- a/submodule.h +++ b/submodule.h @@ -24,6 +24,7 @@ void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *); int parse_fetch_recurse_submodules_arg(const char *opt, const char *arg); int parse_update_recurse_submodules_arg(const char *opt, const char *arg); int submodule_needs_update(const char *path); +int populate_submodule(const char *path, unsigned char sha1[20], int force); int depopulate_submodule(const char *path); void show_submodule_summary(FILE *f, const char *path, const char *line_prefix, diff --git a/unpack-trees.c b/unpack-trees.c index 89b506a..ed48d41 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -1367,6 +1367,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype, struct unpack_trees_options *o) { const struct cache_entry *result; + char *name_copy, *separator; /* * It may be that the 'lstat()' succeeded even though @@ -1409,6 +1410,24 @@ static int check_ok_to_remove(const char *name, int len, int dtype, return 0; } + /* + * If the path lies inside a to be added submodule it + * is ok to remove it. + */ + name_copy = xstrdup(name); + while ((separator = strrchr(name_copy, '/'))) { + int i; + *separator = '\0'; + for (i = 0; i < the_index.cache_nr; i++) { + struct cache_entry *ce = the_index.cache[i]; + if (!strcmp(ce->name, name_copy) && S_ISGITLINK(ce->ce_mode)) { + free(name_copy); + return 0; + } + } + } + free(name_copy); + return o->gently ? -1 : add_rejected_path(o, error_type, name); } -- 1.8.5.1 -- 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