X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=read-tree.c;h=55f7f87133c4a310855fe478452dbc51f6d28fca;hb=b05b52027c0e43abc9629049944283729a07899f;hp=aa6172b52eeadb4f118e5145c182270342a70bf0;hpb=35702a983e2d8e6bb7b0ebff4016648f407366a2;p=git.git diff --git a/read-tree.c b/read-tree.c index aa6172b52..55f7f8713 100644 --- a/read-tree.c +++ b/read-tree.c @@ -411,7 +411,7 @@ static void verify_uptodate(struct cache_entry *ce) { struct stat st; - if (index_only) + if (index_only || reset) return; if (!lstat(ce->name, &st)) { @@ -435,6 +435,21 @@ static void invalidate_ce_path(struct cache_entry *ce) cache_tree_invalidate_path(active_cache_tree, ce->name); } +/* + * We do not want to remove or overwrite a working tree file that + * is not tracked. + */ +static void verify_absent(const char *path, const char *action) +{ + struct stat st; + + if (index_only || reset || !update) + return; + if (!lstat(path, &st)) + die("Untracked working tree file '%s' " + "would be %s by merge.", path, action); +} + static int merged_entry(struct cache_entry *merge, struct cache_entry *old) { merge->ce_flags |= htons(CE_UPDATE); @@ -453,8 +468,11 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old) invalidate_ce_path(old); } } - else + else { + verify_absent(merge->name, "overwritten"); invalidate_ce_path(merge); + } + merge->ce_flags &= ~htons(CE_STAGEMASK); add_cache_entry(merge, ADD_CACHE_OK_TO_ADD); return 1; @@ -464,6 +482,8 @@ static int deleted_entry(struct cache_entry *ce, struct cache_entry *old) { if (old) verify_uptodate(old); + else + verify_absent(ce->name, "removed"); ce->ce_mode = 0; add_cache_entry(ce, ADD_CACHE_OK_TO_ADD); invalidate_ce_path(ce); @@ -500,6 +520,7 @@ static int threeway_merge(struct cache_entry **stages) int count; int head_match = 0; int remote_match = 0; + const char *path = NULL; int df_conflict_head = 0; int df_conflict_remote = 0; @@ -511,8 +532,11 @@ static int threeway_merge(struct cache_entry **stages) for (i = 1; i < head_idx; i++) { if (!stages[i]) any_anc_missing = 1; - else + else { + if (!path) + path = stages[i]->name; no_anc_exists = 0; + } } index = stages[0]; @@ -528,8 +552,15 @@ static int threeway_merge(struct cache_entry **stages) remote = NULL; } + if (!path && index) + path = index->name; + if (!path && head) + path = head->name; + if (!path && remote) + path = remote->name; + /* First, if there's a #16 situation, note that to prevent #13 - * and #14. + * and #14. */ if (!same(remote, head)) { for (i = 1; i < head_idx; i++) { @@ -588,6 +619,8 @@ static int threeway_merge(struct cache_entry **stages) (remote_deleted && head && head_match)) { if (index) return deleted_entry(index, index); + else if (path) + verify_absent(path, "removed"); return 0; } /* @@ -605,6 +638,8 @@ static int threeway_merge(struct cache_entry **stages) if (index) { verify_uptodate(index); } + else if (path) + verify_absent(path, "overwritten"); nontrivial_merge = 1; @@ -690,7 +725,7 @@ static int twoway_merge(struct cache_entry **src) * Bind merge. * * Keep the index entries at stage0, collapse stage1 but make sure - * stage0 does not have anything in prefix. + * stage0 does not have anything there. */ static int bind_merge(struct cache_entry **src) { @@ -700,12 +735,12 @@ static int bind_merge(struct cache_entry **src) if (merge_size != 1) return error("Cannot do a bind merge of %d trees\n", merge_size); - if (!a) - return merged_entry(old, NULL); - if (old) + if (a && old) die("Entry '%s' overlaps. Cannot bind.", a->name); - - return merged_entry(a, NULL); + if (!a) + return keep_entry(old); + else + return merged_entry(a, NULL); } /* @@ -725,7 +760,7 @@ static int oneway_merge(struct cache_entry **src) if (!a) { invalidate_ce_path(old); - return deleted_entry(old, NULL); + return deleted_entry(old, old); } if (old && same(old, a)) { if (reset) { @@ -736,7 +771,7 @@ static int oneway_merge(struct cache_entry **src) } return keep_entry(old); } - return merged_entry(a, NULL); + return merged_entry(a, old); } static int read_cache_unmerged(void) @@ -766,7 +801,7 @@ static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree) { struct tree_entry_list *ent; int cnt; - + memcpy(it->sha1, tree->object.sha1, 20); for (cnt = 0, ent = tree->entries; ent; ent = ent->next) { if (!ent->directory)