X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=src%2Findex.c;h=d5afc9bb695a2a9e7d7ffbbca03cad13154ce57a;hb=22a2d3d5efc740ba0dc69175b8bbb1e715e0257e;hp=7f865c2c75168cceeb2c56db77c041586773bb9b;hpb=b6832cbfa8d8c29e01c9a97276a8d05a70ccc268;p=libgit2.git diff --git a/src/index.c b/src/index.c index 7f865c2c7..d5afc9bb6 100644 --- a/src/index.c +++ b/src/index.c @@ -27,29 +27,6 @@ #include "git2/config.h" #include "git2/sys/index.h" -#define INSERT_IN_MAP_EX(idx, map, e, err) do { \ - if ((idx)->ignore_case) \ - git_idxmap_icase_insert((git_idxmap_icase *) (map), (e), (e), (err)); \ - else \ - git_idxmap_insert((map), (e), (e), (err)); \ - } while (0) - -#define INSERT_IN_MAP(idx, e, err) INSERT_IN_MAP_EX(idx, (idx)->entries_map, e, err) - -#define LOOKUP_IN_MAP(p, idx, k) do { \ - if ((idx)->ignore_case) \ - (p) = git_idxmap_icase_lookup_index((git_idxmap_icase *) index->entries_map, (k)); \ - else \ - (p) = git_idxmap_lookup_index(index->entries_map, (k)); \ - } while (0) - -#define DELETE_IN_MAP(idx, e) do { \ - if ((idx)->ignore_case) \ - git_idxmap_icase_delete((git_idxmap_icase *) (idx)->entries_map, (e)); \ - else \ - git_idxmap_delete((idx)->entries_map, (e)); \ - } while (0) - static int index_apply_to_wd_diff(git_index *index, int action, const git_strarray *paths, unsigned int flags, git_index_matched_path_cb cb, void *payload); @@ -148,6 +125,30 @@ static int write_index(git_oid *checksum, git_index *index, git_filebuf *file); static void index_entry_free(git_index_entry *entry); static void index_entry_reuc_free(git_index_reuc_entry *reuc); +GIT_INLINE(int) index_map_set(git_idxmap *map, git_index_entry *e, bool ignore_case) +{ + if (ignore_case) + return git_idxmap_icase_set((git_idxmap_icase *) map, e, e); + else + return git_idxmap_set(map, e, e); +} + +GIT_INLINE(int) index_map_delete(git_idxmap *map, git_index_entry *e, bool ignore_case) +{ + if (ignore_case) + return git_idxmap_icase_delete((git_idxmap_icase *) map, e); + else + return git_idxmap_delete(map, e); +} + +GIT_INLINE(int) index_map_resize(git_idxmap *map, size_t count, bool ignore_case) +{ + if (ignore_case) + return git_idxmap_icase_resize((git_idxmap_icase *) map, count); + else + return git_idxmap_resize(map, count); +} + int git_index_entry_srch(const void *key, const void *array_member) { const struct entry_srch_key *srch_key = key; @@ -410,7 +411,8 @@ int git_index_open(git_index **index_out, const char *index_path) index = git__calloc(1, sizeof(git_index)); GIT_ERROR_CHECK_ALLOC(index); - git_pool_init(&index->tree_pool, 1); + if (git_pool_init(&index->tree_pool, 1) < 0) + goto fail; if (index_path != NULL) { index->index_file_path = git__strdup(index_path); @@ -423,10 +425,10 @@ int git_index_open(git_index **index_out, const char *index_path) } if (git_vector_init(&index->entries, 32, git_index_entry_cmp) < 0 || - git_idxmap_alloc(&index->entries_map) < 0 || - git_vector_init(&index->names, 8, conflict_name_cmp) < 0 || - git_vector_init(&index->reuc, 8, reuc_cmp) < 0 || - git_vector_init(&index->deleted, 8, git_index_entry_cmp) < 0) + git_idxmap_new(&index->entries_map) < 0 || + git_vector_init(&index->names, 8, conflict_name_cmp) < 0 || + git_vector_init(&index->reuc, 8, reuc_cmp) < 0 || + git_vector_init(&index->deleted, 8, git_index_entry_cmp) < 0) goto fail; index->entries_cmp_path = git__strcmp_cb; @@ -507,7 +509,7 @@ static int index_remove_entry(git_index *index, size_t pos) if (entry != NULL) { git_tree_cache_invalidate_path(index->tree, entry->path); - DELETE_IN_MAP(index, entry); + index_map_delete(index->entries_map, entry, index->ignore_case); } error = git_vector_remove(&index->entries, pos); @@ -538,13 +540,19 @@ int git_index_clear(git_index *index) git_idxmap_clear(index->entries_map); while (!error && index->entries.length > 0) error = index_remove_entry(index, index->entries.length - 1); + + if (error) + goto done; + index_free_deleted(index); - git_index_reuc_clear(index); - git_index_name_clear(index); + if ((error = git_index_name_clear(index)) < 0 || + (error = git_index_reuc_clear(index)) < 0) + goto done; git_futils_filestamp_set(&index->stamp, NULL); +done: return error; } @@ -570,11 +578,11 @@ int git_index_set_caps(git_index *index, int caps) return create_index_error( -1, "cannot access repository to set index caps"); - if (!git_repository__cvar(&val, repo, GIT_CVAR_IGNORECASE)) + if (!git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_IGNORECASE)) index->ignore_case = (val != 0); - if (!git_repository__cvar(&val, repo, GIT_CVAR_FILEMODE)) + if (!git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_FILEMODE)) index->distrust_filemode = (val == 0); - if (!git_repository__cvar(&val, repo, GIT_CVAR_SYMLINKS)) + if (!git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_SYMLINKS)) index->no_symlinks = (val == 0); } else { @@ -852,20 +860,24 @@ const git_index_entry *git_index_get_bypath( git_index *index, const char *path, int stage) { git_index_entry key = {{ 0 }}; - size_t pos; + git_index_entry *value; assert(index); key.path = path; GIT_INDEX_ENTRY_STAGE_SET(&key, stage); - LOOKUP_IN_MAP(pos, index, &key); + if (index->ignore_case) + value = git_idxmap_icase_get((git_idxmap_icase *) index->entries_map, &key); + else + value = git_idxmap_get(index->entries_map, &key); - if (git_idxmap_valid_index(index->entries_map, pos)) - return git_idxmap_value_at(index->entries_map, pos); + if (!value) { + git_error_set(GIT_ERROR_INDEX, "index does not contain '%s'", path); + return NULL; + } - git_error_set(GIT_ERROR_INDEX, "index does not contain '%s'", path); - return NULL; + return value; } void git_index_entry__init_from_stat( @@ -1398,10 +1410,9 @@ static int index_insert( * at the sorted position. (Since we re-sort after each insert to * check for dups, this is actually cheaper in the long run.) */ - if ((error = git_vector_insert_sorted(&index->entries, entry, index_no_dups)) < 0) + if ((error = git_vector_insert_sorted(&index->entries, entry, index_no_dups)) < 0 || + (error = index_map_set(index->entries_map, entry, index->ignore_case)) < 0) goto out; - - INSERT_IN_MAP(index, entry, &error); } index->dirty = 1; @@ -1453,7 +1464,7 @@ GIT_INLINE(bool) valid_filemode(const int filemode) return (is_file_or_link(filemode) || filemode == GIT_FILEMODE_COMMIT); } -int git_index_add_frombuffer( +int git_index_add_from_buffer( git_index *index, const git_index_entry *source_entry, const void *buffer, size_t len) { @@ -1473,17 +1484,22 @@ int git_index_add_frombuffer( return -1; } + if (len > UINT32_MAX) { + git_error_set(GIT_ERROR_INDEX, "buffer is too large"); + return -1; + } + if (index_entry_dup(&entry, index, source_entry) < 0) return -1; - error = git_blob_create_frombuffer(&id, INDEX_OWNER(index), buffer, len); + error = git_blob_create_from_buffer(&id, INDEX_OWNER(index), buffer, len); if (error < 0) { index_entry_free(entry); return error; } git_oid_cpy(&entry->id, &id); - entry->file_size = len; + entry->file_size = (uint32_t)len; if ((error = index_insert(index, &entry, 1, true, true, true)) < 0) return error; @@ -1610,41 +1626,42 @@ int git_index_remove_bypath(git_index *index, const char *path) int git_index__fill(git_index *index, const git_vector *source_entries) { const git_index_entry *source_entry = NULL; + int error = 0; size_t i; - int ret = 0; assert(index); if (!source_entries->length) return 0; - git_vector_size_hint(&index->entries, source_entries->length); - git_idxmap_resize(index->entries_map, (size_t)(source_entries->length * 1.3)); + if (git_vector_size_hint(&index->entries, source_entries->length) < 0 || + index_map_resize(index->entries_map, (size_t)(source_entries->length * 1.3), + index->ignore_case) < 0) + return -1; git_vector_foreach(source_entries, i, source_entry) { git_index_entry *entry = NULL; - if ((ret = index_entry_dup(&entry, index, source_entry)) < 0) + if ((error = index_entry_dup(&entry, index, source_entry)) < 0) break; index_entry_adjust_namemask(entry, ((struct entry_internal *)entry)->pathlen); entry->flags_extended |= GIT_INDEX_ENTRY_UPTODATE; entry->mode = git_index__create_mode(entry->mode); - if ((ret = git_vector_insert(&index->entries, entry)) < 0) + if ((error = git_vector_insert(&index->entries, entry)) < 0) break; - INSERT_IN_MAP(index, entry, &ret); - if (ret < 0) + if ((error = index_map_set(index->entries_map, entry, index->ignore_case)) < 0) break; index->dirty = 1; } - if (!ret) + if (!error) git_vector_sort(&index->entries); - return ret; + return error; } @@ -1677,7 +1694,7 @@ int git_index_remove(git_index *index, const char *path, int stage) remove_key.path = path; GIT_INDEX_ENTRY_STAGE_SET(&remove_key, stage); - DELETE_IN_MAP(index, &remove_key); + index_map_delete(index->entries_map, &remove_key, index->ignore_case); if (index_find(&position, index, path, 0, stage) < 0) { git_error_set( @@ -2126,7 +2143,7 @@ int git_index_name_add(git_index *index, return 0; } -void git_index_name_clear(git_index *index) +int git_index_name_clear(git_index *index) { size_t i; git_index_name_entry *conflict_name; @@ -2139,6 +2156,8 @@ void git_index_name_clear(git_index *index) git_vector_clear(&index->names); index->dirty = 1; + + return 0; } size_t git_index_reuc_entrycount(git_index *index) @@ -2235,7 +2254,7 @@ int git_index_reuc_remove(git_index *index, size_t position) return error; } -void git_index_reuc_clear(git_index *index) +int git_index_reuc_clear(git_index *index) { size_t i; @@ -2247,6 +2266,8 @@ void git_index_reuc_clear(git_index *index) git_vector_clear(&index->reuc); index->dirty = 1; + + return 0; } static int index_error_invalid(const char *message) @@ -2607,10 +2628,8 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) assert(!index->entries.length); - if (index->ignore_case) - git_idxmap_icase_resize((git_idxmap_icase *) index->entries_map, header.entry_count); - else - git_idxmap_resize(index->entries_map, header.entry_count); + if ((error = index_map_resize(index->entries_map, header.entry_count, index->ignore_case)) < 0) + return error; /* Parse all the entries */ for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) { @@ -2627,9 +2646,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) goto done; } - INSERT_IN_MAP(index, entry, &error); - - if (error < 0) { + if ((error = index_map_set(index->entries_map, entry, index->ignore_case)) < 0) { index_entry_free(entry); goto done; } @@ -2728,7 +2745,7 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha ++same_len; } path_len -= same_len; - varint_len = git_encode_varint(NULL, 0, same_len); + varint_len = git_encode_varint(NULL, 0, strlen(last) - same_len); } disk_size = index_entry_size(path_len, varint_len, entry->flags); @@ -2764,22 +2781,24 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha ondisk.flags = htons(entry->flags); if (entry->flags & GIT_INDEX_ENTRY_EXTENDED) { + const size_t path_offset = offsetof(struct entry_long, path); struct entry_long ondisk_ext; memcpy(&ondisk_ext, &ondisk, sizeof(struct entry_short)); ondisk_ext.flags_extended = htons(entry->flags_extended & GIT_INDEX_ENTRY_EXTENDED_FLAGS); - memcpy(mem, &ondisk_ext, offsetof(struct entry_long, path)); - path = ((struct entry_long*)mem)->path; - disk_size -= offsetof(struct entry_long, path); + memcpy(mem, &ondisk_ext, path_offset); + path = (char *)mem + path_offset; + disk_size -= path_offset; } else { - memcpy(mem, &ondisk, offsetof(struct entry_short, path)); - path = ((struct entry_short*)mem)->path; - disk_size -= offsetof(struct entry_short, path); + const size_t path_offset = offsetof(struct entry_short, path); + memcpy(mem, &ondisk, path_offset); + path = (char *)mem + path_offset; + disk_size -= path_offset; } if (last) { varint_len = git_encode_varint((unsigned char *) path, - disk_size, same_len); + disk_size, strlen(last) - same_len); assert(varint_len > 0); path += varint_len; disk_size -= varint_len; @@ -3106,7 +3125,7 @@ int git_index_read_tree(git_index *index, const git_tree *tree) size_t i; git_index_entry *e; - if (git_idxmap_alloc(&entries_map) < 0) + if (git_idxmap_new(&entries_map) < 0) return -1; git_vector_set_cmp(&entries, index->entries._cmp); /* match sort */ @@ -3124,15 +3143,11 @@ int git_index_read_tree(git_index *index, const git_tree *tree) if ((error = git_tree_walk(tree, GIT_TREEWALK_POST, read_tree_cb, &data)) < 0) goto cleanup; - if (index->ignore_case) - git_idxmap_icase_resize((git_idxmap_icase *) entries_map, entries.length); - else - git_idxmap_resize(entries_map, entries.length); + if ((error = index_map_resize(entries_map, entries.length, index->ignore_case)) < 0) + goto cleanup; git_vector_foreach(&entries, i, e) { - INSERT_IN_MAP_EX(index, entries_map, e, &error); - - if (error < 0) { + if ((error = index_map_set(entries_map, e, index->ignore_case)) < 0) { git_error_set(GIT_ERROR_INDEX, "failed to insert entry into map"); return error; } @@ -3180,14 +3195,13 @@ static int git_index_read_iterator( assert((new_iterator->flags & GIT_ITERATOR_DONT_IGNORE_CASE)); if ((error = git_vector_init(&new_entries, new_length_hint, index->entries._cmp)) < 0 || - (error = git_vector_init(&remove_entries, index->entries.length, NULL)) < 0 || - (error = git_idxmap_alloc(&new_entries_map)) < 0) + (error = git_vector_init(&remove_entries, index->entries.length, NULL)) < 0 || + (error = git_idxmap_new(&new_entries_map)) < 0) goto done; - if (index->ignore_case && new_length_hint) - git_idxmap_icase_resize((git_idxmap_icase *) new_entries_map, new_length_hint); - else if (new_length_hint) - git_idxmap_resize(new_entries_map, new_length_hint); + if (new_length_hint && (error = index_map_resize(new_entries_map, new_length_hint, + index->ignore_case)) < 0) + goto done; opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE | GIT_ITERATOR_INCLUDE_CONFLICTS; @@ -3251,7 +3265,8 @@ static int git_index_read_iterator( if (add_entry) { if ((error = git_vector_insert(&new_entries, add_entry)) == 0) - INSERT_IN_MAP_EX(index, new_entries_map, add_entry, &error); + error = index_map_set(new_entries_map, add_entry, + index->ignore_case); } if (remove_entry && error >= 0) @@ -3275,8 +3290,9 @@ static int git_index_read_iterator( } } - git_index_name_clear(index); - git_index_reuc_clear(index); + if ((error = git_index_name_clear(index)) < 0 || + (error = git_index_reuc_clear(index)) < 0) + goto done; git_vector_swap(&new_entries, &index->entries); new_entries_map = git__swap(index->entries_map, new_entries_map); @@ -3700,3 +3716,14 @@ void git_indexwriter_cleanup(git_indexwriter *writer) git_index_free(writer->index); writer->index = NULL; } + +/* Deprecated functions */ + +#ifndef GIT_DEPRECATE_HARD +int git_index_add_frombuffer( + git_index *index, const git_index_entry *source_entry, + const void *buffer, size_t len) +{ + return git_index_add_from_buffer(index, source_entry, buffer, len); +} +#endif