From: Junio C Hamano Date: Tue, 17 Dec 2013 19:32:04 +0000 (-0800) Subject: Merge branch 'jk/two-way-merge-corner-case-fix' into maint X-Git-Tag: v1.8.5.2~11 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/4766036ecdee2d45b5a955409da5e6751c3e2f05?ds=inline;hp=-c Merge branch 'jk/two-way-merge-corner-case-fix' into maint "git am --abort" sometimes complained about not being able to write a tree with an 0{40} object in it. * jk/two-way-merge-corner-case-fix: t1005: add test for "read-tree --reset -u A B" t1005: reindent unpack-trees: fix "read-tree -u --reset A B" with conflicted index --- 4766036ecdee2d45b5a955409da5e6751c3e2f05 diff --combined unpack-trees.c index 35cb05e92b,bf978e154c..ad3e9a04fe --- a/unpack-trees.c +++ b/unpack-trees.c @@@ -102,34 -102,21 +102,34 @@@ void setup_unpack_trees_porcelain(struc opts->unpack_rejects[i].strdup_strings = 1; } -static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce, - unsigned int set, unsigned int clear) +static void do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce, + unsigned int set, unsigned int clear) { - unsigned int size = ce_size(ce); - struct cache_entry *new = xmalloc(size); - clear |= CE_HASHED | CE_UNHASHED; if (set & CE_REMOVE) set |= CE_WT_REMOVE; + ce->next = NULL; + ce->ce_flags = (ce->ce_flags & ~clear) | set; + add_index_entry(&o->result, ce, + ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE); +} + +static struct cache_entry *dup_entry(const struct cache_entry *ce) +{ + unsigned int size = ce_size(ce); + struct cache_entry *new = xmalloc(size); + memcpy(new, ce, size); - new->next = NULL; - new->ce_flags = (new->ce_flags & ~clear) | set; - add_index_entry(&o->result, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); + return new; +} + +static void add_entry(struct unpack_trees_options *o, + const struct cache_entry *ce, + unsigned int set, unsigned int clear) +{ + do_add_entry(o, dup_entry(ce), set, clear); } /* @@@ -179,7 -166,7 +179,7 @@@ static void display_error_msgs(struct u * Unlink the last component and schedule the leading directories for * removal, such that empty directories get removed. */ -static void unlink_entry(struct cache_entry *ce) +static void unlink_entry(const struct cache_entry *ce) { if (!check_leading_path(ce->name, ce_namelen(ce))) return; @@@ -199,7 -186,7 +199,7 @@@ static int check_updates(struct unpack_ if (o->update && o->verbose_update) { for (total = cnt = 0; cnt < index->cache_nr; cnt++) { - struct cache_entry *ce = index->cache[cnt]; + const struct cache_entry *ce = index->cache[cnt]; if (ce->ce_flags & (CE_UPDATE | CE_WT_REMOVE)) total++; } @@@ -212,7 -199,7 +212,7 @@@ if (o->update) git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result); for (i = 0; i < index->cache_nr; i++) { - struct cache_entry *ce = index->cache[i]; + const struct cache_entry *ce = index->cache[i]; if (ce->ce_flags & CE_WT_REMOVE) { display_progress(progress, ++cnt); @@@ -241,11 -228,8 +241,11 @@@ return errs != 0; } -static int verify_uptodate_sparse(struct cache_entry *ce, struct unpack_trees_options *o); -static int verify_absent_sparse(struct cache_entry *ce, enum unpack_trees_error_types, struct unpack_trees_options *o); +static int verify_uptodate_sparse(const struct cache_entry *ce, + struct unpack_trees_options *o); +static int verify_absent_sparse(const struct cache_entry *ce, + enum unpack_trees_error_types, + struct unpack_trees_options *o); static int apply_sparse_checkout(struct cache_entry *ce, struct unpack_trees_options *o) { @@@ -300,8 -284,7 +300,8 @@@ return 0; } -static inline int call_unpack_fn(struct cache_entry **src, struct unpack_trees_options *o) +static inline int call_unpack_fn(const struct cache_entry * const *src, + struct unpack_trees_options *o) { int ret = o->fn(src, o); if (ret > 0) @@@ -330,7 -313,7 +330,7 @@@ static void mark_all_ce_unused(struct i index->cache[i]->ce_flags &= ~(CE_UNPACKED | CE_ADDED | CE_NEW_SKIP_WORKTREE); } -static int locate_in_src_index(struct cache_entry *ce, +static int locate_in_src_index(const struct cache_entry *ce, struct unpack_trees_options *o) { struct index_state *index = o->src_index; @@@ -376,7 -359,7 +376,7 @@@ static struct cache_entry *next_cache_e return NULL; } -static void add_same_unmerged(struct cache_entry *ce, +static void add_same_unmerged(const struct cache_entry *ce, struct unpack_trees_options *o) { struct index_state *index = o->src_index; @@@ -398,7 -381,7 +398,7 @@@ static int unpack_index_entry(struct cache_entry *ce, struct unpack_trees_options *o) { - struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, }; + const struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, }; int ret; src[0] = ce; @@@ -464,7 -447,7 +464,7 @@@ static int traverse_trees_recursive(in newinfo.pathspec = info->pathspec; newinfo.name = *p; newinfo.pathlen += tree_entry_len(p) + 1; - newinfo.conflicts |= df_conflicts; + newinfo.df_conflicts |= df_conflicts; for (i = 0; i < n; i++, dirmask >>= 1) { const unsigned char *sha1 = NULL; @@@ -549,8 -532,7 +549,8 @@@ static struct cache_entry *create_ce_en struct cache_entry *ce = xcalloc(1, cache_entry_size(len)); ce->ce_mode = create_ce_mode(n->mode); - ce->ce_flags = create_ce_flags(len, stage); + ce->ce_flags = create_ce_flags(stage); + ce->ce_namelen = len; hashcpy(ce->sha1, n->sha1); make_traverse_path(ce->name, info, n); @@@ -565,12 -547,17 +565,12 @@@ static int unpack_nondirectories(int n { int i; struct unpack_trees_options *o = info->data; - unsigned long conflicts; + unsigned long conflicts = info->df_conflicts | dirmask; /* Do we have *only* directories? Nothing to do */ if (mask == dirmask && !src[0]) return 0; - conflicts = info->conflicts; - if (o->merge) - conflicts >>= 1; - conflicts |= dirmask; - /* * Ok, we've filled in up to any potential index entry in src[0], * now do the rest. @@@ -595,20 -582,12 +595,20 @@@ src[i + o->merge] = create_ce_entry(info, names + i, stage); } - if (o->merge) - return call_unpack_fn(src, o); + if (o->merge) { + int rc = call_unpack_fn((const struct cache_entry * const *)src, + o); + for (i = 0; i < n; i++) { + struct cache_entry *ce = src[i + o->merge]; + if (ce != o->df_conflict_entry) + free(ce); + } + return rc; + } for (i = 0; i < n; i++) if (src[i] && src[i] != o->df_conflict_entry) - add_entry(o, src[i], 0, 0); + do_add_entry(o, src[i], 0, 0); return 0; } @@@ -650,7 -629,7 +650,7 @@@ static int find_cache_pos(struct traver int p_len = tree_entry_len(p); for (pos = o->cache_bottom; pos < index->cache_nr; pos++) { - struct cache_entry *ce = index->cache[pos]; + const struct cache_entry *ce = index->cache[pos]; const char *ce_name, *ce_slash; int cmp, ce_len; @@@ -793,7 -772,7 +793,7 @@@ static int unpack_callback(int n, unsig if (unpack_nondirectories(n, mask, dirmask, src, names, info) < 0) return -1; - if (src[0]) { + if (o->merge && src[0]) { if (ce_stage(src[0])) mark_ce_used_same_name(src[0], o); else @@@ -802,6 -781,13 +802,6 @@@ /* Now handle any directories.. */ if (dirmask) { - unsigned long conflicts = mask & ~dirmask; - if (o->merge) { - conflicts <<= 1; - if (src[0]) - conflicts |= 1; - } - /* special case: "diff-index --cached" looking at a tree */ if (o->diff_index_cached && n == 1 && dirmask == 1 && S_ISDIR(names->mode)) { @@@ -820,7 -806,7 +820,7 @@@ } } - if (traverse_trees_recursive(n, dirmask, conflicts, + if (traverse_trees_recursive(n, dirmask, mask & ~dirmask, names, info) < 0) return -1; return mask; @@@ -843,8 -829,7 +843,8 @@@ static int clear_ce_flags_dir(struct ca { struct cache_entry **cache_end; int dtype = DT_DIR; - int ret = excluded_from_list(prefix, prefix_len, basename, &dtype, el); + int ret = is_excluded_from_list(prefix, prefix_len, + basename, &dtype, el); prefix[prefix_len++] = '/'; @@@ -863,7 -848,7 +863,7 @@@ * with ret (iow, we know in advance the incl/excl * decision for the entire directory), clear flag here without * calling clear_ce_flags_1(). That function will call - * the expensive excluded_from_list() on every entry. + * the expensive is_excluded_from_list() on every entry. */ return clear_ce_flags_1(cache, cache_end - cache, prefix, prefix_len, @@@ -946,8 -931,7 +946,8 @@@ static int clear_ce_flags_1(struct cach /* Non-directory */ dtype = ce_to_dtype(ce); - ret = excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, el); + ret = is_excluded_from_list(ce->name, ce_namelen(ce), + name, &dtype, el); if (ret < 0) ret = defval; if (ret > 0) @@@ -1001,9 -985,7 +1001,9 @@@ static void mark_new_skip_worktree(stru select_flag, skip_wt_flag, el); } -static int verify_absent(struct cache_entry *, enum unpack_trees_error_types, struct unpack_trees_options *); +static int verify_absent(const struct cache_entry *, + enum unpack_trees_error_types, + struct unpack_trees_options *); /* * N-way merge "len" trees. Returns 0 on success, -1 on failure to manipulate the * resulting index, -2 on failure to reflect the changes to the work tree. @@@ -1028,7 -1010,7 +1028,7 @@@ int unpack_trees(unsigned len, struct t if (!core_apply_sparse_checkout || !o->update) o->skip_sparse_checkout = 1; if (!o->skip_sparse_checkout) { - if (add_excludes_from_file_to_list(git_path("info/sparse-checkout"), "", 0, NULL, &el, 0) < 0) + if (add_excludes_from_file_to_list(git_path("info/sparse-checkout"), "", 0, &el, 0) < 0) o->skip_sparse_checkout = 1; else o->el = ⪙ @@@ -1038,7 -1020,6 +1038,7 @@@ o->result.initialized = 1; o->result.timestamp.sec = o->src_index->timestamp.sec; o->result.timestamp.nsec = o->src_index->timestamp.nsec; + o->result.version = o->src_index->version; o->merge_size = len; mark_all_ce_unused(o->src_index); @@@ -1154,13 -1135,11 +1154,13 @@@ o->src_index = NULL; ret = check_updates(o) ? (-2) : 0; - if (o->dst_index) + if (o->dst_index) { + discard_index(o->dst_index); *o->dst_index = o->result; + } done: - free_excludes(&el); + clear_exclude_list(&el); return ret; return_failed: @@@ -1175,13 -1154,12 +1175,13 @@@ /* Here come the merge functions */ -static int reject_merge(struct cache_entry *ce, struct unpack_trees_options *o) +static int reject_merge(const struct cache_entry *ce, + struct unpack_trees_options *o) { return add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce->name); } -static int same(struct cache_entry *a, struct cache_entry *b) +static int same(const struct cache_entry *a, const struct cache_entry *b) { if (!!a != !!b) return 0; @@@ -1198,9 -1176,9 +1198,9 @@@ * When a CE gets turned into an unmerged entry, we * want it to be up-to-date */ -static int verify_uptodate_1(struct cache_entry *ce, - struct unpack_trees_options *o, - enum unpack_trees_error_types error_type) +static int verify_uptodate_1(const struct cache_entry *ce, + struct unpack_trees_options *o, + enum unpack_trees_error_types error_type) { struct stat st; @@@ -1224,7 -1202,7 +1224,7 @@@ return 0; /* * NEEDSWORK: the current default policy is to allow - * submodule to be out of sync wrt the supermodule + * submodule to be out of sync wrt the superproject * index. This needs to be tightened later for * submodules that are marked to be automatically * checked out. @@@ -1239,7 -1217,7 +1239,7 @@@ add_rejected_path(o, error_type, ce->name); } -static int verify_uptodate(struct cache_entry *ce, +static int verify_uptodate(const struct cache_entry *ce, struct unpack_trees_options *o) { if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE)) @@@ -1247,14 -1225,13 +1247,14 @@@ return verify_uptodate_1(ce, o, ERROR_NOT_UPTODATE_FILE); } -static int verify_uptodate_sparse(struct cache_entry *ce, +static int verify_uptodate_sparse(const struct cache_entry *ce, struct unpack_trees_options *o) { return verify_uptodate_1(ce, o, ERROR_SPARSE_NOT_UPTODATE_FILE); } -static void invalidate_ce_path(struct cache_entry *ce, struct unpack_trees_options *o) +static void invalidate_ce_path(const struct cache_entry *ce, + struct unpack_trees_options *o) { if (ce) cache_tree_invalidate_path(o->src_index->cache_tree, ce->name); @@@ -1267,16 -1244,16 +1267,16 @@@ * Currently, git does not checkout subprojects during a superproject * checkout, so it is not going to overwrite anything. */ -static int verify_clean_submodule(struct cache_entry *ce, - enum unpack_trees_error_types error_type, - struct unpack_trees_options *o) +static int verify_clean_submodule(const struct cache_entry *ce, + enum unpack_trees_error_types error_type, + struct unpack_trees_options *o) { return 0; } -static int verify_clean_subdirectory(struct cache_entry *ce, - enum unpack_trees_error_types error_type, - struct unpack_trees_options *o) +static int verify_clean_subdirectory(const struct cache_entry *ce, + enum unpack_trees_error_types error_type, + struct unpack_trees_options *o) { /* * we are about to extract "ce->name"; we would not want to lose @@@ -1303,7 -1280,7 +1303,7 @@@ * First let's make sure we do not have a local modification * in that directory. */ - namelen = strlen(ce->name); + namelen = ce_namelen(ce); for (i = locate_in_src_index(ce, o); i < o->src_index->cache_nr; i++) { @@@ -1355,18 -1332,18 +1355,18 @@@ */ static int icase_exists(struct unpack_trees_options *o, const char *name, int len, struct stat *st) { - struct cache_entry *src; + const struct cache_entry *src; - src = index_name_exists(o->src_index, name, len, 1); + src = index_file_exists(o->src_index, name, len, 1); return src && !ie_match_stat(o->src_index, src, st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE); } static int check_ok_to_remove(const char *name, int len, int dtype, - struct cache_entry *ce, struct stat *st, + const struct cache_entry *ce, struct stat *st, enum unpack_trees_error_types error_type, struct unpack_trees_options *o) { - struct cache_entry *result; + const struct cache_entry *result; /* * It may be that the 'lstat()' succeeded even though @@@ -1378,8 -1355,7 +1378,8 @@@ if (ignore_case && icase_exists(o, name, len, st)) return 0; - if (o->dir && excluded(o->dir, name, &dtype)) + if (o->dir && + is_excluded(o->dir, name, &dtype)) /* * ce->name is explicitly excluded, so it is Ok to * overwrite it. @@@ -1403,7 -1379,7 +1403,7 @@@ * delete this path, which is in a subdirectory that * is being replaced with a blob. */ - result = index_name_exists(&o->result, name, len, 0); + result = index_file_exists(&o->result, name, len, 0); if (result) { if (result->ce_flags & CE_REMOVE) return 0; @@@ -1417,9 -1393,9 +1417,9 @@@ * We do not want to remove or overwrite a working tree file that * is not tracked, unless it is ignored. */ -static int verify_absent_1(struct cache_entry *ce, - enum unpack_trees_error_types error_type, - struct unpack_trees_options *o) +static int verify_absent_1(const struct cache_entry *ce, + enum unpack_trees_error_types error_type, + struct unpack_trees_options *o) { int len; struct stat st; @@@ -1452,7 -1428,7 +1452,7 @@@ } } -static int verify_absent(struct cache_entry *ce, +static int verify_absent(const struct cache_entry *ce, enum unpack_trees_error_types error_type, struct unpack_trees_options *o) { @@@ -1461,9 -1437,9 +1461,9 @@@ return verify_absent_1(ce, error_type, o); } -static int verify_absent_sparse(struct cache_entry *ce, - enum unpack_trees_error_types error_type, - struct unpack_trees_options *o) +static int verify_absent_sparse(const struct cache_entry *ce, + enum unpack_trees_error_types error_type, + struct unpack_trees_options *o) { enum unpack_trees_error_types orphaned_error = error_type; if (orphaned_error == ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN) @@@ -1472,12 -1448,10 +1472,12 @@@ return verify_absent_1(ce, orphaned_error, o); } -static int merged_entry(struct cache_entry *merge, struct cache_entry *old, - struct unpack_trees_options *o) +static int merged_entry(const struct cache_entry *ce, + const struct cache_entry *old, + struct unpack_trees_options *o) { int update = CE_UPDATE; + struct cache_entry *merge = dup_entry(ce); if (!old) { /* @@@ -1495,11 -1469,8 +1495,11 @@@ update |= CE_ADDED; merge->ce_flags |= CE_NEW_SKIP_WORKTREE; - if (verify_absent(merge, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) + if (verify_absent(merge, + ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) { + free(merge); return -1; + } invalidate_ce_path(merge, o); } else if (!(old->ce_flags & CE_CONFLICTED)) { /* @@@ -1513,10 -1484,8 +1513,10 @@@ copy_cache_entry(merge, old); update = 0; } else { - if (verify_uptodate(old, o)) + if (verify_uptodate(old, o)) { + free(merge); return -1; + } /* Migrate old flags over */ update |= old->ce_flags & (CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE); invalidate_ce_path(old, o); @@@ -1529,13 -1498,12 +1529,13 @@@ invalidate_ce_path(old, o); } - add_entry(o, merge, update, CE_STAGEMASK); + do_add_entry(o, merge, update, CE_STAGEMASK); return 1; } -static int deleted_entry(struct cache_entry *ce, struct cache_entry *old, - struct unpack_trees_options *o) +static int deleted_entry(const struct cache_entry *ce, + const struct cache_entry *old, + struct unpack_trees_options *o) { /* Did it exist in the index? */ if (!old) { @@@ -1550,8 -1518,7 +1550,8 @@@ return 1; } -static int keep_entry(struct cache_entry *ce, struct unpack_trees_options *o) +static int keep_entry(const struct cache_entry *ce, + struct unpack_trees_options *o) { add_entry(o, ce, 0, 0); return 1; @@@ -1573,12 -1540,11 +1573,12 @@@ static void show_stage_entry(FILE *o } #endif -int threeway_merge(struct cache_entry **stages, struct unpack_trees_options *o) +int threeway_merge(const struct cache_entry * const *stages, + struct unpack_trees_options *o) { - struct cache_entry *index; - struct cache_entry *head; - struct cache_entry *remote = stages[o->head_idx + 1]; + const struct cache_entry *index; + const struct cache_entry *head; + const struct cache_entry *remote = stages[o->head_idx + 1]; int count; int head_match = 0; int remote_match = 0; @@@ -1663,7 -1629,7 +1663,7 @@@ if (o->aggressive) { int head_deleted = !head; int remote_deleted = !remote; - struct cache_entry *ce = NULL; + const struct cache_entry *ce = NULL; if (index) ce = index; @@@ -1746,12 -1712,11 +1746,12 @@@ * "carry forward" rule, please see . * */ -int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o) +int twoway_merge(const struct cache_entry * const *src, + struct unpack_trees_options *o) { - struct cache_entry *current = src[0]; - struct cache_entry *oldtree = src[1]; - struct cache_entry *newtree = src[2]; + const struct cache_entry *current = src[0]; + const struct cache_entry *oldtree = src[1]; + const struct cache_entry *newtree = src[2]; if (o->merge_size != 2) return error("Cannot do a twoway merge of %d trees", @@@ -1763,14 -1728,23 +1763,23 @@@ newtree = NULL; if (current) { - if ((!oldtree && !newtree) || /* 4 and 5 */ - (!oldtree && newtree && - same(current, newtree)) || /* 6 and 7 */ - (oldtree && newtree && - same(oldtree, newtree)) || /* 14 and 15 */ - (oldtree && newtree && - !same(oldtree, newtree) && /* 18 and 19 */ - same(current, newtree))) { + if (current->ce_flags & CE_CONFLICTED) { + if (same(oldtree, newtree) || o->reset) { + if (!newtree) + return deleted_entry(current, current, o); + else + return merged_entry(newtree, current, o); + } + return o->gently ? -1 : reject_merge(current, o); + } + else if ((!oldtree && !newtree) || /* 4 and 5 */ + (!oldtree && newtree && + same(current, newtree)) || /* 6 and 7 */ + (oldtree && newtree && + same(oldtree, newtree)) || /* 14 and 15 */ + (oldtree && newtree && + !same(oldtree, newtree) && /* 18 and 19 */ + same(current, newtree))) { return keep_entry(current, o); } else if (oldtree && !newtree && same(current, oldtree)) { @@@ -1813,14 -1787,14 +1822,14 @@@ * Keep the index entries at stage0, collapse stage1 but make sure * stage0 does not have anything there. */ -int bind_merge(struct cache_entry **src, - struct unpack_trees_options *o) +int bind_merge(const struct cache_entry * const *src, + struct unpack_trees_options *o) { - struct cache_entry *old = src[0]; - struct cache_entry *a = src[1]; + const struct cache_entry *old = src[0]; + const struct cache_entry *a = src[1]; if (o->merge_size != 1) - return error("Cannot do a bind merge of %d trees\n", + return error("Cannot do a bind merge of %d trees", o->merge_size); if (a && old) return o->gently ? -1 : @@@ -1837,11 -1811,10 +1846,11 @@@ * The rule is: * - take the stat information from stage0, take the data from stage1 */ -int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o) +int oneway_merge(const struct cache_entry * const *src, + struct unpack_trees_options *o) { - struct cache_entry *old = src[0]; - struct cache_entry *a = src[1]; + const struct cache_entry *old = src[0]; + const struct cache_entry *a = src[1]; if (o->merge_size != 1) return error("Cannot do a oneway merge of %d trees", @@@ -1852,7 -1825,7 +1861,7 @@@ if (old && same(old, a)) { int update = 0; - if (o->reset && !ce_uptodate(old) && !ce_skip_worktree(old)) { + if (o->reset && o->update && !ce_uptodate(old) && !ce_skip_worktree(old)) { struct stat st; if (lstat(old->name, &st) || ie_match_stat(o->src_index, old, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE))