Merge branch 'jc/read-tree-safety' into next

* jc/read-tree-safety:
  read-tree -m -u: do not overwrite or remove untracked working tree files.
This commit is contained in:
Junio C Hamano
2006-05-17 15:54:39 -07:00
5 changed files with 89 additions and 32 deletions

View File

@ -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;
@ -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)