From: Jens Lehmann <jens.lehm...@web.de>
Date: Mon, 18 Jun 2012 22:11:45 +0200

Signed-off-by: Jens Lehmann <jens.lehm...@web.de>
Signed-off-by: Jonathan Nieder <jrnie...@gmail.com>
---
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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to