- while (pos < active_nr) {
- struct cache_entry *other = active_cache[pos];
- if (strncmp(other->name, path, namelen))
- break; /* it is not our "subdirectory" anymore */
- if ((ce_stage(other) == stage) &&
- other->name[namelen] == '/') {
- if (!ok_to_replace)
- return -1;
- fprintf(stderr, "removing file '%s' under '%s' to be replaced with a file\n", other->name, path);
- remove_entry_at(pos);
- replaced = 1;
- continue; /* cycle without updating pos */
+ 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;
+ }
+
+ /*
+ * 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)
+ /* 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++;