Apply "Subproject commit HEX" changes produced by git-diff. As usual in the current git, only the superproject itself is actually modified (possibly creating empty directories for new submodules). Signed-off-by: Sven Verdoolaege <skimo@xxxxxxxxxx> --- This also makes rebase handle submodules. builtin-apply.c | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 38 insertions(+), 11 deletions(-) diff --git a/builtin-apply.c b/builtin-apply.c index da27075..24df282 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1984,6 +1984,26 @@ static int apply_fragments(struct buffer_desc *desc, struct patch *patch) return 0; } +static int read_file_or_gitlink(struct cache_entry *ce, char **buf_p, + unsigned long *size_p) +{ + if (!ce) + return 0; + + if (S_ISGITLINK(ntohl(ce->ce_mode))) { + *buf_p = xmalloc(100); + *size_p = snprintf(*buf_p, 100, + "Subproject commit %s\n", sha1_to_hex(ce->sha1)); + } else { + enum object_type type; + *buf_p = read_sha1_file(ce->sha1, &type, size_p); + if (!*buf_p) + return -1; + } + + return 0; +} + static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce) { char *buf; @@ -1994,20 +2014,18 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry * alloc = 0; buf = NULL; if (cached) { - if (ce) { - enum object_type type; - buf = read_sha1_file(ce->sha1, &type, &size); - if (!buf) - return error("read of %s failed", - patch->old_name); - alloc = size; - } + if (read_file_or_gitlink(ce, &buf, &size)) + return error("read of %s failed", patch->old_name); + alloc = size; } else if (patch->old_name) { size = xsize_t(st->st_size); alloc = size + 8192; buf = xmalloc(alloc); - if (read_old_data(st, patch->old_name, &buf, &alloc, &size)) + if (S_ISGITLINK(patch->old_mode)) + size = snprintf(buf, alloc, + "Subproject commit %s\n", sha1_to_hex(ce->sha1)); + else if (read_old_data(st, patch->old_name, &buf, &alloc, &size)) return error("read of %s failed", patch->old_name); } @@ -2098,7 +2116,7 @@ static int check_patch(struct patch *patch, struct patch *prev_patch) } if (!cached) changed = ce_match_stat(ce, &st, 1); - if (changed) + if (changed && !S_ISGITLINK(patch->old_mode)) return error("%s: does not match index", old_name); if (cached) @@ -2387,7 +2405,9 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned die("unable to stat newly created file %s", path); fill_stat_cache_info(ce, &st); } - if (write_sha1_file(buf, size, blob_type, ce->sha1) < 0) + if (S_ISGITLINK(mode)) + get_sha1_hex(buf + strlen("Subproject commit "), ce->sha1); + else if (write_sha1_file(buf, size, blob_type, ce->sha1) < 0) die("unable to create backing store for newly created file %s", path); if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) die("unable to add cache entry for %s", path); @@ -2398,6 +2418,13 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, int fd; char *nbuf; + if (S_ISGITLINK(mode)) { + struct stat st; + if (!lstat(path, &st) && S_ISDIR(st.st_mode)) + return 0; + return mkdir(path, 0777); + } + if (has_symlinks && S_ISLNK(mode)) /* Although buf:size is counted string, it also is NUL * terminated. -- 1.5.3.rc4.29.g74276-dirty - 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