diff options
author | Vicent Marti <tanoku@gmail.com> | 2014-01-29 18:44:29 +0100 |
---|---|---|
committer | Edward Thomson <ethomson@microsoft.com> | 2014-01-29 13:15:52 -0800 |
commit | 1eefd3561225bfdedfe52a7e9faa6e7c88d7a046 (patch) | |
tree | 7b9de46ebb5d607a8479dc35aec26669e9b87d03 /src/index.c | |
parent | 53bec813a81cb0e1e970df69281ab4a3e6c2a47c (diff) | |
download | libgit2-1eefd3561225bfdedfe52a7e9faa6e7c88d7a046.tar.gz |
index: Implement folder-file checks
Diffstat (limited to 'src/index.c')
-rw-r--r-- | src/index.c | 102 |
1 files changed, 50 insertions, 52 deletions
diff --git a/src/index.c b/src/index.c index e16529d74..aa30f9d32 100644 --- a/src/index.c +++ b/src/index.c @@ -712,32 +712,29 @@ static git_index_entry *index_entry_dup(const git_index_entry *source_entry) return entry; } -#if 0 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 len = ce_namelen(ce); - int stage = ce_stage(ce); - const char *name = ce->name; + size_t len = strlen(entry->path); + int stage = GIT_IDXENTRY_STAGE(entry); + const char *name = entry->path; - while (pos < istate->cache_nr) { - struct cache_entry *p = istate->cache[pos++]; + while (pos < index->entries.length) { + git_index_entry *p = index->entries.contents[pos++]; - if (len >= ce_namelen(p)) + if (len >= strlen(p->path)) break; - if (memcmp(name, p->name, len)) + if (memcmp(name, p->path, len)) break; - if (ce_stage(p) != stage) - continue; - if (p->name[len] != '/') + if (GIT_IDXENTRY_STAGE(p) != stage) continue; - if (p->ce_flags & CE_REMOVE) + if (p->path[len] != '/') continue; retval = -1; if (!ok_to_replace) break; - remove_index_entry_at(istate, --pos); + git_vector_remove(&index->entries, --pos); } return retval; } @@ -750,67 +747,65 @@ static int has_dir_name(git_index *index, const git_index_entry *entry, int ok_to_replace) { int retval = 0; - int stage = ce_stage(ce); - const char *name = ce->name; - const char *slash = name + ce_namelen(ce); + int stage = GIT_IDXENTRY_STAGE(entry); + const char *name = entry->path; + const char *slash = name + strlen(name); for (;;) { - int len; + size_t len, position; for (;;) { if (*--slash == '/') break; - if (slash <= ce->name) + if (slash <= entry->path) return retval; } len = slash - name; - pos = index_name_stage_pos(istate, name, len, stage); - if (pos >= 0) { - /* - * 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 (!(istate->cache[pos]->ce_flags & CE_REMOVE)) { - retval = -1; - if (!ok_to_replace) - break; - remove_index_entry_at(istate, pos); - continue; - } + if (git_index__find(&position, index, name, len, stage) == 0) { + retval = -1; + if (!ok_to_replace) + break; + + git_vector_remove(&index->entries, position); + 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. */ - while (pos < istate->cache_nr) { - struct cache_entry *p = istate->cache[pos]; - if ((ce_namelen(p) <= len) || - (p->name[len] != '/') || - memcmp(p->name, name, len)) + while (position < index->entries.length) { + git_index_entry *p = index->entries.contents[position]; + + if ((strlen(p->path) <= len) || + (p->path[len] != '/') || + memcmp(p->path, name, len)) break; /* not our subdirectory */ - if (ce_stage(p) == stage && !(p->ce_flags & CE_REMOVE)) - /* - * 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. - */ + + if (GIT_IDXENTRY_STAGE(p) == stage) return retval; - pos++; + + position++; } } 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) { @@ -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); } + if (check_file_directory_conflict(index, entry, position, replace) < 0) + return -1; + /* if replacing is not requested or no existing entry exists, just * insert entry at the end; the index is no longer sorted */ |