Commit 1eefd356 by Vicent Marti Committed by Edward Thomson

index: Implement folder-file checks

parent 53bec813
...@@ -712,32 +712,29 @@ static git_index_entry *index_entry_dup(const git_index_entry *source_entry) ...@@ -712,32 +712,29 @@ static git_index_entry *index_entry_dup(const git_index_entry *source_entry)
return entry; return entry;
} }
#if 0
static int has_file_name(git_index *index, static int has_file_name(git_index *index,
const git_index_entry *entry, int pos, int ok_to_replace) const git_index_entry *entry, size_t pos, int ok_to_replace)
{ {
int retval = 0; int retval = 0;
int len = ce_namelen(ce); size_t len = strlen(entry->path);
int stage = ce_stage(ce); int stage = GIT_IDXENTRY_STAGE(entry);
const char *name = ce->name; const char *name = entry->path;
while (pos < istate->cache_nr) { while (pos < index->entries.length) {
struct cache_entry *p = istate->cache[pos++]; git_index_entry *p = index->entries.contents[pos++];
if (len >= ce_namelen(p)) if (len >= strlen(p->path))
break; break;
if (memcmp(name, p->name, len)) if (memcmp(name, p->path, len))
break; break;
if (ce_stage(p) != stage) if (GIT_IDXENTRY_STAGE(p) != stage)
continue;
if (p->name[len] != '/')
continue; continue;
if (p->ce_flags & CE_REMOVE) if (p->path[len] != '/')
continue; continue;
retval = -1; retval = -1;
if (!ok_to_replace) if (!ok_to_replace)
break; break;
remove_index_entry_at(istate, --pos); git_vector_remove(&index->entries, --pos);
} }
return retval; return retval;
} }
...@@ -750,67 +747,65 @@ static int has_dir_name(git_index *index, ...@@ -750,67 +747,65 @@ static int has_dir_name(git_index *index,
const git_index_entry *entry, int ok_to_replace) const git_index_entry *entry, int ok_to_replace)
{ {
int retval = 0; int retval = 0;
int stage = ce_stage(ce); int stage = GIT_IDXENTRY_STAGE(entry);
const char *name = ce->name; const char *name = entry->path;
const char *slash = name + ce_namelen(ce); const char *slash = name + strlen(name);
for (;;) { for (;;) {
int len; size_t len, position;
for (;;) { for (;;) {
if (*--slash == '/') if (*--slash == '/')
break; break;
if (slash <= ce->name) if (slash <= entry->path)
return retval; return retval;
} }
len = slash - name; len = slash - name;
pos = index_name_stage_pos(istate, name, len, stage); if (git_index__find(&position, index, name, len, stage) == 0) {
if (pos >= 0) { retval = -1;
/* if (!ok_to_replace)
* Found one, but not so fast. This could break;
* be a marker that says "I was here, but
* I am being removed". Such an entry is git_vector_remove(&index->entries, position);
* not a part of the resulting tree, and continue;
* it is Ok to have a directory at the same
* path.
*/
if (!(istate->cache[pos]->ce_flags & CE_REMOVE)) {
retval = -1;
if (!ok_to_replace)
break;
remove_index_entry_at(istate, pos);
continue;
}
} }
else
pos = -pos-1;
/* /*
* Trivial optimization: if we find an entry that * Trivial optimization: if we find an entry that
* already matches the sub-directory, then we know * already matches the sub-directory, then we know
* we're ok, and we can exit. * we're ok, and we can exit.
*/ */
while (pos < istate->cache_nr) { while (position < index->entries.length) {
struct cache_entry *p = istate->cache[pos]; git_index_entry *p = index->entries.contents[position];
if ((ce_namelen(p) <= len) ||
(p->name[len] != '/') || if ((strlen(p->path) <= len) ||
memcmp(p->name, name, len)) (p->path[len] != '/') ||
memcmp(p->path, name, len))
break; /* not our subdirectory */ break; /* not our subdirectory */
if (ce_stage(p) == stage && !(p->ce_flags & CE_REMOVE))
/* if (GIT_IDXENTRY_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; return retval;
pos++;
position++;
} }
} }
return retval; return retval;
} }
#endif
static int check_file_directory_conflict(git_index *index,
git_index_entry *entry, size_t pos, int ok_to_replace)
{
int retval = has_file_name(index, entry, pos, ok_to_replace);
retval = retval + has_dir_name(index, entry, ok_to_replace);
if (retval) {
giterr_set(GITERR_INDEX, "'%s' appears as both a file an a directory", entry->path);
return -1;
}
return 0;
}
static int index_insert(git_index *index, git_index_entry *entry, int replace) static int index_insert(git_index *index, git_index_entry *entry, int replace)
{ {
...@@ -838,6 +833,9 @@ static int index_insert(git_index *index, git_index_entry *entry, int replace) ...@@ -838,6 +833,9 @@ static int index_insert(git_index *index, git_index_entry *entry, int replace)
entry->mode = index_merge_mode(index, *existing, entry->mode); entry->mode = index_merge_mode(index, *existing, entry->mode);
} }
if (check_file_directory_conflict(index, entry, position, replace) < 0)
return -1;
/* if replacing is not requested or no existing entry exists, just /* if replacing is not requested or no existing entry exists, just
* insert entry at the end; the index is no longer sorted * insert entry at the end; the index is no longer sorted
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment