From: Sven Verdoolaege <skimo@xxxxxxxxxx> Signed-off-by: Sven Verdoolaege <skimo@xxxxxxxxxx> --- entry.c | 23 ++++++++++++++++++++--- submodules.c | 43 +++++++++++++++++++++++++++++++++++++++++++ submodules.h | 1 + 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/entry.c b/entry.c index 7ba2241..f3e0c59 100644 --- a/entry.c +++ b/entry.c @@ -1,6 +1,7 @@ #include "cache.h" #include "blob.h" #include "run-command.h" +#include "submodules.h" static void create_directories(const char *path, const struct checkout *state) { @@ -82,7 +83,7 @@ static int checkout_submodule(struct cache_entry *ce, const char *path, const st int argc; int err; - if (!state->submodules) + if (!state->submodules && !is_checkedout_submodule(ce->name)) return 0; argc = 0; @@ -101,10 +102,25 @@ static int checkout_submodule(struct cache_entry *ce, const char *path, const st return 0; } +static int write_submodule(struct cache_entry *ce, char *path, const struct checkout *state) +{ + if (mkdir(path, 0777) < 0) + return error("git-checkout-index: cannot create subproject directory %s", path); + + if (!state->submodules) + return 0; + + if (attach_submodule(ce->name)) + return -1; + + return checkout_submodule(ce, path, state); +} + static int write_entry(struct cache_entry *ce, char *path, const struct checkout *state, int to_tempfile) { int fd; long wrote; + int err; switch (ntohl(ce->ce_mode) & S_IFMT) { char *buf, *new; @@ -174,8 +190,9 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout case S_IFGITLINK: if (to_tempfile) return error("git-checkout-index: cannot create temporary subproject %s", path); - if (mkdir(path, 0777) < 0) - return error("git-checkout-index: cannot create subproject directory %s", path); + err = write_submodule(ce, path, state); + if (err) + return err; break; default: return error("git-checkout-index: unknown file mode for %s", path); diff --git a/submodules.c b/submodules.c index 44c0f2c..325de33 100644 --- a/submodules.c +++ b/submodules.c @@ -209,3 +209,46 @@ int clone_submodule(const char *submodule) return 0; } + +static const char *relativize_path(const char *path, const char *dest) +{ + static char relative_path[PATH_MAX]; + int slashes; + const char *cp; + char *rp; + + if (path[0] == '/') + return path; + + for (slashes = 0, cp = strchr(dest, '/'); cp; cp = strchr(cp, '/')) { + ++slashes; + while (*cp == '/') + ++cp; + } + if (3 * slashes + strlen(path) + 1 > sizeof(relative_path)) + die("path too long"); + + rp = relative_path; + while (slashes--) { + memcpy(rp, "../", 3); + rp += 3; + } + strcpy(rp, path); + + return relative_path; +} + +int attach_submodule(const char *submodule) +{ + struct stat st; + const char *submodule_dir, *dest; + + submodule_dir = git_path("submodules/%s/.git", submodule); + if (lstat(submodule_dir, &st)) + return error("submodule '%s' unavailable", submodule); + + dest = mkpath("%s/.git", submodule); + submodule_dir = relativize_path(submodule_dir, dest); + + return symlink(submodule_dir, dest); +} diff --git a/submodules.h b/submodules.h index bf3f118..57432bb 100644 --- a/submodules.h +++ b/submodules.h @@ -3,5 +3,6 @@ int is_checkedout_submodule(const char *path); int clone_submodule(const char *submodule); +int attach_submodule(const char *submodule); #endif -- 1.5.2.784.g5532e - 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