mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-11 16:34:33 +00:00
index: Implement folder-file checks
This commit is contained in:
parent
53bec813a8
commit
1eefd35612
102
src/index.c
102
src/index.c
@ -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;
|
continue;
|
||||||
if (p->name[len] != '/')
|
if (p->path[len] != '/')
|
||||||
continue;
|
|
||||||
if (p->ce_flags & CE_REMOVE)
|
|
||||||
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,
|
|||||||
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)
|
|||||||
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
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user