diff options
author | Junio C Hamano <junkio@cox.net> | 2005-06-25 02:25:29 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-25 16:52:16 -0700 |
commit | b155725daeec48436d1fcbec4854ffd317408a6e (patch) | |
tree | 37c9bb329b890f432e21508bda67ef093cdd8130 /read-cache.c | |
parent | aacc15ec5261fca8a02570f93028e3ac4213caae (diff) | |
download | git-b155725daeec48436d1fcbec4854ffd317408a6e.tar.gz |
[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>
Diffstat (limited to 'read-cache.c')
-rw-r--r-- | read-cache.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/read-cache.c b/read-cache.c index 9b6ce46b9f..5a61bf752b 100644 --- a/read-cache.c +++ b/read-cache.c @@ -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 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 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 } len = slash - name; - pos = cache_name_pos(name, len); + pos = cache_name_pos(name, ntohs(create_ce_flags(len, stage))); if (pos >= 0) { retval = -1; if (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) 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; pos = cache_name_pos(ce->name, ntohs(ce->ce_flags)); /* existing match? Just replace it */ @@ -302,7 +312,7 @@ int add_cache_entry(struct cache_entry *ce, int option) if (!ok_to_add) return -1; - if (!ce_stage(ce) && check_file_directory_conflict(ce, pos, ok_to_replace)) { + if (!skip_df_check && check_file_directory_conflict(ce, pos, ok_to_replace)) { if (!ok_to_replace) return -1; pos = cache_name_pos(ce->name, ntohs(ce->ce_flags)); |