From: Junio C Hamano Date: Thu, 5 Nov 2015 20:18:11 +0000 (-0800) Subject: Merge branch 'jk/delete-modechange-conflict' into maint X-Git-Tag: v2.6.3~6 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/5e6154fb145d66af36e10ef4db7e1d1e9502c501?ds=inline;hp=-c Merge branch 'jk/delete-modechange-conflict' into maint Merging a branch that removes a path and another that changes the mode bits on the same path should have conflicted at the path, but it didn't and silently favoured the removal. * jk/delete-modechange-conflict: merge: detect delete/modechange conflict t6031: generalize for recursive and resolve strategies t6031: move triple-rename test to t3030 --- 5e6154fb145d66af36e10ef4db7e1d1e9502c501 diff --combined merge-recursive.c index 44d85bea4b,a1ee9b7e24..b446df9c1d --- a/merge-recursive.c +++ b/merge-recursive.c @@@ -275,20 -275,23 +275,20 @@@ struct tree *write_tree_from_memory(str } static int save_files_dirs(const unsigned char *sha1, - const char *base, int baselen, const char *path, + struct strbuf *base, const char *path, unsigned int mode, int stage, void *context) { - int len = strlen(path); - char *newpath = xmalloc(baselen + len + 1); + int baselen = base->len; struct merge_options *o = context; - memcpy(newpath, base, baselen); - memcpy(newpath + baselen, path, len); - newpath[baselen + len] = '\0'; + strbuf_addstr(base, path); if (S_ISDIR(mode)) - string_list_insert(&o->current_directory_set, newpath); + string_list_insert(&o->current_directory_set, base->buf); else - string_list_insert(&o->current_file_set, newpath); - free(newpath); + string_list_insert(&o->current_file_set, base->buf); + strbuf_setlen(base, baselen); return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0); } @@@ -611,6 -614,7 +611,6 @@@ static char *unique_path(struct merge_o { struct strbuf newpath = STRBUF_INIT; int suffix = 0; - struct stat st; size_t base_len; strbuf_addf(&newpath, "%s~", path); @@@ -619,7 -623,7 +619,7 @@@ base_len = newpath.len; while (string_list_has_string(&o->current_file_set, newpath.buf) || string_list_has_string(&o->current_directory_set, newpath.buf) || - lstat(newpath.buf, &st) == 0) { + file_exists(newpath.buf)) { strbuf_setlen(&newpath, base_len); strbuf_addf(&newpath, "_%d", suffix++); } @@@ -1531,13 -1535,17 +1531,17 @@@ static int read_sha1_strbuf(const unsig } static int blob_unchanged(const unsigned char *o_sha, + unsigned o_mode, const unsigned char *a_sha, + unsigned a_mode, int renormalize, const char *path) { struct strbuf o = STRBUF_INIT; struct strbuf a = STRBUF_INIT; int ret = 0; /* assume changed for safety */ + if (a_mode != o_mode) + return 0; if (sha_eq(o_sha, a_sha)) return 1; if (!renormalize) @@@ -1723,8 -1731,8 +1727,8 @@@ static int process_entry(struct merge_o } else if (o_sha && (!a_sha || !b_sha)) { /* Case A: Deleted in one */ if ((!a_sha && !b_sha) || - (!b_sha && blob_unchanged(o_sha, a_sha, normalize, path)) || - (!a_sha && blob_unchanged(o_sha, b_sha, normalize, path))) { + (!b_sha && blob_unchanged(o_sha, o_mode, a_sha, a_mode, normalize, path)) || + (!a_sha && blob_unchanged(o_sha, o_mode, b_sha, b_mode, normalize, path))) { /* Deleted in both or deleted in one and * unchanged in the other */ if (a_sha) @@@ -1857,9 -1865,6 +1861,9 @@@ int merge_trees(struct merge_options *o string_list_clear(re_head, 0); string_list_clear(entries, 1); + free(re_merge); + free(re_head); + free(entries); } else clean = 1; @@@ -1903,7 -1908,7 +1907,7 @@@ int merge_recursive(struct merge_option } if (!ca) { - ca = get_merge_bases(h1, h2, 1); + ca = get_merge_bases(h1, h2); ca = reverse_commit_list(ca); }