[PATCH] Fix oversimplified optimization for add_cache_entry().
An earlier change to optimize directory-file conflict check
broke what "read-tree --emu23" expects. This is fixed by this
commit.
(1) Introduces an explicit flag to tell add_cache_entry() not to
check for conflicts and use it when reading an existing tree
into an empty stage --- by definition this case can never
introduce such conflicts.
(2) Makes read-cache.c:has_file_name() and read-cache.c:has_dir_name()
aware of the cache stages, and flag conflict only with paths
in the same stage.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
maint
Junio C Hamano20 years agocommitted byLinus Torvalds
@ -179,6 +179,7 @@ static int has_file_name(const struct cache_entry *ce, int pos, int ok_to_replac
@@ -179,6 +179,7 @@ static int has_file_name(const struct cache_entry *ce, int pos, int ok_to_replac
{
int retval = 0;
int len = ce_namelen(ce);
int stage = ce_stage(ce);
const char *name = ce->name;
while (pos < active_nr) {
@ -188,6 +189,8 @@ static int has_file_name(const struct cache_entry *ce, int pos, int ok_to_replac
@@ -188,6 +189,8 @@ static int has_file_name(const struct cache_entry *ce, int pos, int ok_to_replac
break;
if (memcmp(name, p->name, len))
break;
if (ce_stage(p) != stage)
continue;
if (p->name[len] != '/')
continue;
retval = -1;
@ -205,6 +208,7 @@ static int has_file_name(const struct cache_entry *ce, int pos, int ok_to_replac
@@ -205,6 +208,7 @@ static int has_file_name(const struct cache_entry *ce, int pos, int ok_to_replac
static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace)
{
int retval = 0;
int stage = ce_stage(ce);
const char *name = ce->name;
const char *slash = name + ce_namelen(ce);
@ -219,7 +223,7 @@ static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace
@@ -219,7 +223,7 @@ static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace
@ -231,18 +235,23 @@ static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace
@@ -231,18 +235,23 @@ static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace
/*
* Trivial optimization: if we find an entry that
* already matches the sub-directory, then we know
* we're ok, and we can exit
* we're ok, and we can exit.
*/
pos = -pos-1;
if (pos < active_nr) {
while (pos < active_nr) {
struct cache_entry *p = active_cache[pos];
if (ce_namelen(p) <= len)
continue;
if (p->name[len] != '/')
continue;
if (memcmp(p->name, name, len))
continue;
break;
if ((ce_namelen(p) <= len) ||
(p->name[len] != '/') ||
memcmp(p->name, name, len))
break; /* not our subdirectory */
if (ce_stage(p) == stage)
/* 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
* level or anything shorter.
*/
return retval;
pos++;
}
}
return retval;
@ -277,6 +286,7 @@ int add_cache_entry(struct cache_entry *ce, int option)
@@ -277,6 +286,7 @@ int add_cache_entry(struct cache_entry *ce, int option)
int pos;
int ok_to_add = option & ADD_CACHE_OK_TO_ADD;
int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
@ -18,7 +18,7 @@ static int read_one_entry(unsigned char *sha1, const char *base, int baselen, co
@@ -18,7 +18,7 @@ static int read_one_entry(unsigned char *sha1, const char *base, int baselen, co