diff options
author | Junio C Hamano <junkio@cox.net> | 2007-04-07 23:52:40 -0700 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2007-04-07 23:52:40 -0700 |
commit | 640ee0d1cd771bf6093602f1beb143d356607446 (patch) | |
tree | 4beb1f02eadd8fbb8957078ca6c4684e1bb78fb7 /read-cache.c | |
parent | 5838dffdcbe92bbbf50a29067fd9dc871155d76d (diff) | |
parent | c81935348be263de3da085e6ac828b583a85c905 (diff) | |
download | git-640ee0d1cd771bf6093602f1beb143d356607446.tar.gz |
Merge branch 'jc/read-tree-df' (early part)
* 'jc/read-tree-df' (early part):
Fix switching to a branch with D/F when current branch has file D.
Fix twoway_merge that passed d/f conflict marker to merged_entry().
Fix read-tree --prefix=dir/.
unpack-trees: get rid of *indpos parameter.
unpack_trees.c: pass unpack_trees_options structure to keep_entry() as well.
add_cache_entry(): removal of file foo does not conflict with foo/bar
Diffstat (limited to 'read-cache.c')
-rw-r--r-- | read-cache.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/read-cache.c b/read-cache.c index a8f8a6b2b2..54573ce2ee 100644 --- a/read-cache.c +++ b/read-cache.c @@ -485,6 +485,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; @@ -517,26 +519,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 @@ -560,12 +573,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. |