summaryrefslogtreecommitdiff
path: root/read-cache.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2007-04-08 06:52:40 (GMT)
committerJunio C Hamano <junkio@cox.net>2007-04-08 06:52:40 (GMT)
commit640ee0d1cd771bf6093602f1beb143d356607446 (patch)
tree4beb1f02eadd8fbb8957078ca6c4684e1bb78fb7 /read-cache.c
parent5838dffdcbe92bbbf50a29067fd9dc871155d76d (diff)
parentc81935348be263de3da085e6ac828b583a85c905 (diff)
downloadgit-640ee0d1cd771bf6093602f1beb143d356607446.zip
git-640ee0d1cd771bf6093602f1beb143d356607446.tar.gz
git-640ee0d1cd771bf6093602f1beb143d356607446.tar.bz2
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.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/read-cache.c b/read-cache.c
index a8f8a6b..54573ce 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.