Commit 21cd8d00 authored by Junio C Hamano's avatar Junio C Hamano

add_cache_entry(): removal of file foo does not conflict with foo/bar

Similarly, removal of file foo/bar does not conflict with a file foo.
Signed-off-by: default avatarJunio C Hamano <junkio@cox.net>
parent c0718268
......@@ -487,6 +487,8 @@ static int has_file_name(const struct cache_entry *ce, int pos, int ok_to_replac
continue;
if (p->name[len] != '/')
continue;
if (!ce_stage(p) && !p->ce_mode)
continue;
retval = -1;
if (!ok_to_replace)
break;
......@@ -519,26 +521,37 @@ static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace
pos = cache_name_pos(name, ntohs(create_ce_flags(len, stage)));
if (pos >= 0) {
retval = -1;
if (!ok_to_replace)
break;
remove_cache_entry_at(pos);
continue;
/*
* Found one, but not so fast. This could
* be a marker that says "I was here, but
* I am being removed". Such an entry is
* not a part of the resulting tree, and
* it is Ok to have a directory at the same
* path.
*/
if (stage || active_cache[pos]->ce_mode) {
retval = -1;
if (!ok_to_replace)
break;
remove_cache_entry_at(pos);
continue;
}
}
else
pos = -pos-1;
/*
* Trivial optimization: if we find an entry that
* already matches the sub-directory, then we know
* we're ok, and we can exit.
*/
pos = -pos-1;
while (pos < active_nr) {
struct cache_entry *p = active_cache[pos];
if ((ce_namelen(p) <= len) ||
(p->name[len] != '/') ||
memcmp(p->name, name, len))
break; /* not our subdirectory */
if (ce_stage(p) == stage)
if (ce_stage(p) == stage && (stage || p->ce_mode))
/* p is at the same stage as our entry, and
* is a subdirectory of what we are looking
* at, so we cannot have conflicts at our
......@@ -562,12 +575,21 @@ static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace
*/
static int check_file_directory_conflict(const struct cache_entry *ce, int pos, int ok_to_replace)
{
int retval;
/*
* When ce is an "I am going away" entry, we allow it to be added
*/
if (!ce_stage(ce) && !ce->ce_mode)
return 0;
/*
* We check if the path is a sub-path of a subsequent pathname
* first, since removing those will not change the position
* in the array
* in the array.
*/
int retval = has_file_name(ce, pos, ok_to_replace);
retval = has_file_name(ce, pos, ok_to_replace);
/*
* Then check if the path might have a clashing sub-directory
* before it.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment