From: Junio C Hamano Date: Fri, 30 Oct 2015 20:06:56 +0000 (-0700) Subject: Merge branch 'jk/delete-modechange-conflict' X-Git-Tag: v2.7.0-rc0~58 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/203501b39fe89193c252ec651d4bf1fafd784b30?hp=-c Merge branch 'jk/delete-modechange-conflict' 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 --- 203501b39fe89193c252ec651d4bf1fafd784b30 diff --combined merge-recursive.c index a5e74d85fd,a1ee9b7e24..21e680a78e --- 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++); } @@@ -630,24 -634,25 +630,24 @@@ static int dir_in_way(const char *path, int check_working_copy) { - int pos, pathlen = strlen(path); - char *dirpath = xmalloc(pathlen + 2); + int pos; + struct strbuf dirpath = STRBUF_INIT; struct stat st; - strcpy(dirpath, path); - dirpath[pathlen] = '/'; - dirpath[pathlen+1] = '\0'; + strbuf_addstr(&dirpath, path); + strbuf_addch(&dirpath, '/'); - pos = cache_name_pos(dirpath, pathlen+1); + pos = cache_name_pos(dirpath.buf, dirpath.len); if (pos < 0) pos = -1 - pos; if (pos < active_nr && - !strncmp(dirpath, active_cache[pos]->name, pathlen+1)) { - free(dirpath); + !strncmp(dirpath.buf, active_cache[pos]->name, dirpath.len)) { + strbuf_release(&dirpath); return 1; } - free(dirpath); + strbuf_release(&dirpath); return check_working_copy && !lstat(path, &st) && S_ISDIR(st.st_mode); } @@@ -1530,13 -1535,17 +1530,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) @@@ -1722,8 -1731,8 +1726,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) @@@ -1856,9 -1865,6 +1860,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; @@@ -1902,7 -1908,7 +1906,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); }