diff options
| author | Russell Belfer <rb@github.com> | 2012-04-25 10:36:01 -0700 |
|---|---|---|
| committer | Russell Belfer <rb@github.com> | 2012-04-25 11:18:08 -0700 |
| commit | 01fed0a8f9b80e80c8f76cde29fc0d66cb77fff7 (patch) | |
| tree | 817dbac7a66529c1a25d26cc256b819564b6cb03 /src/refs.c | |
| parent | ada488bfe720d0df8187b5b58e326a13b7bdc678 (diff) | |
| download | libgit2-01fed0a8f9b80e80c8f76cde29fc0d66cb77fff7.tar.gz | |
Convert hashtable usage over to khash
This updates khash.h with some extra features (like error checking
on allocations, ability to use wrapped malloc, foreach calls, etc),
creates two high-level wrappers around khash: `git_khash_str` and
`git_khash_oid` for string-to-void-ptr and oid-to-void-ptr tables,
then converts all of the old usage of `git_hashtable` over to use
these new hashtables.
For `git_khash_str`, I've tried to create a set of macros that
yield an API not too unlike the old `git_hashtable` API. Since
the oid hashtable is only used in one file, I haven't bother to
set up all those macros and just use the khash APIs directly for
now.
Diffstat (limited to 'src/refs.c')
| -rw-r--r-- | src/refs.c | 72 |
1 files changed, 45 insertions, 27 deletions
diff --git a/src/refs.c b/src/refs.c index 447f3a7b6..7050b4af9 100644 --- a/src/refs.c +++ b/src/refs.c @@ -15,6 +15,8 @@ #include <git2/tag.h> #include <git2/object.h> +GIT_KHASH_STR__IMPLEMENTATION; + #define DEFAULT_NESTING_LEVEL 5 #define MAX_NESTING_LEVEL 10 @@ -30,8 +32,6 @@ struct packref { char name[GIT_FLEX_ARRAY]; }; -static const int default_table_size = 32; - static int reference_read( git_buf *file_content, time_t *mtime, @@ -423,9 +423,7 @@ static int packed_load(git_repository *repo) /* First we make sure we have allocated the hash table */ if (ref_cache->packfile == NULL) { - ref_cache->packfile = git_hashtable_alloc( - default_table_size, git_hash__strhash_cb, git_hash__strcmp_cb); - + ref_cache->packfile = git_khash_str_alloc(); GITERR_CHECK_ALLOC(ref_cache->packfile); } @@ -440,7 +438,7 @@ static int packed_load(git_repository *repo) * refresh the packed refs. */ if (result == GIT_ENOTFOUND) { - git_hashtable_clear(ref_cache->packfile); + git_khash_str_clear(ref_cache->packfile); return 0; } @@ -454,7 +452,7 @@ static int packed_load(git_repository *repo) * At this point, we want to refresh the packed refs. We already * have the contents in our buffer. */ - git_hashtable_clear(ref_cache->packfile); + git_khash_str_clear(ref_cache->packfile); buffer_start = (const char *)packfile.ptr; buffer_end = (const char *)(buffer_start) + packfile.size; @@ -468,6 +466,7 @@ static int packed_load(git_repository *repo) } while (buffer_start < buffer_end) { + int err; struct packref *ref = NULL; if (packed_parse_oid(&ref, &buffer_start, buffer_end) < 0) @@ -478,15 +477,16 @@ static int packed_load(git_repository *repo) goto parse_failed; } - if (git_hashtable_insert(ref_cache->packfile, ref->name, ref) < 0) - return -1; + git_khash_str_insert(ref_cache->packfile, ref->name, ref, err); + if (err < 0) + goto parse_failed; } git_buf_free(&packfile); return 0; parse_failed: - git_hashtable_free(ref_cache->packfile); + git_khash_str_free(ref_cache->packfile); ref_cache->packfile = NULL; git_buf_free(&packfile); return -1; @@ -512,7 +512,7 @@ static int _dirent_loose_listall(void *_data, git_buf *full_path) /* do not add twice a reference that exists already in the packfile */ if ((data->list_flags & GIT_REF_PACKED) != 0 && - git_hashtable_lookup(data->repo->references.packfile, file_path) != NULL) + git_khash_str_exists(data->repo->references.packfile, file_path)) return 0; if (data->list_flags != GIT_REF_LISTALL) { @@ -529,6 +529,7 @@ static int _dirent_loose_load(void *data, git_buf *full_path) void *old_ref = NULL; struct packref *ref; const char *file_path; + int err; if (git_path_isdir(full_path->ptr) == true) return git_path_direach(full_path, _dirent_loose_load, repository); @@ -538,8 +539,9 @@ static int _dirent_loose_load(void *data, git_buf *full_path) if (loose_lookup_to_packfile(&ref, repository, file_path) < 0) return -1; - if (git_hashtable_insert2(repository->references.packfile, - ref->name, ref, &old_ref) < 0) { + git_khash_str_insert2( + repository->references.packfile, ref->name, ref, old_ref, err); + if (err < 0) { git__free(ref); return -1; } @@ -734,7 +736,8 @@ static int packed_write(git_repository *repo) assert(repo && repo->references.packfile); - total_refs = (unsigned int)repo->references.packfile->key_count; + total_refs = + (unsigned int)git_khash_str_num_entries(repo->references.packfile); if (git_vector_init(&packing_list, total_refs, packed_sort) < 0) return -1; @@ -743,10 +746,10 @@ static int packed_write(git_repository *repo) { struct packref *reference; - GIT_HASHTABLE_FOREACH_VALUE(repo->references.packfile, reference, - /* cannot fail: vector already has the right size */ + /* cannot fail: vector already has the right size */ + git_khash_str_foreach_value(repo->references.packfile, reference, { git_vector_insert(&packing_list, reference); - ); + }); } /* sort the vector so the entries appear sorted on the packfile */ @@ -870,7 +873,8 @@ static int reference_exists(int *exists, git_repository *repo, const char *ref_n return -1; if (git_path_isfile(ref_path.ptr) == true || - git_hashtable_lookup(repo->references.packfile, ref_path.ptr) != NULL) { + git_khash_str_exists(repo->references.packfile, ref_path.ptr)) + { *exists = 1; } else { *exists = 0; @@ -936,6 +940,8 @@ static int reference_can_write( static int packed_lookup(git_reference *ref) { struct packref *pack_ref = NULL; + git_khash_str *packfile_refs; + khiter_t pos; if (packed_load(ref->owner) < 0) return -1; @@ -952,12 +958,15 @@ static int packed_lookup(git_reference *ref) } /* Look up on the packfile */ - pack_ref = git_hashtable_lookup(ref->owner->references.packfile, ref->name); - if (pack_ref == NULL) { + packfile_refs = ref->owner->references.packfile; + pos = git_khash_str_lookup_index(packfile_refs, ref->name); + if (!git_khash_str_valid_index(packfile_refs, pos)) { giterr_set(GITERR_REFERENCE, "Reference '%s' not found", ref->name); return GIT_ENOTFOUND; } + pack_ref = git_khash_str_value_at(packfile_refs, pos); + ref->flags = GIT_REF_OID | GIT_REF_PACKED; ref->mtime = ref->owner->references.packfile_time; git_oid_cpy(&ref->target.oid, &pack_ref->oid); @@ -1002,18 +1011,25 @@ static int reference_delete(git_reference *ref) * We need to reload the packfile, remove the reference from the * packing list, and repack */ if (ref->flags & GIT_REF_PACKED) { + git_khash_str *packfile_refs; struct packref *packref; + khiter_t pos; + /* load the existing packfile */ if (packed_load(ref->owner) < 0) return -1; - if (git_hashtable_remove2(ref->owner->references.packfile, - ref->name, (void **) &packref) < 0) { + packfile_refs = ref->owner->references.packfile; + pos = git_khash_str_lookup_index(packfile_refs, ref->name); + if (!git_khash_str_valid_index(packfile_refs, pos)) { giterr_set(GITERR_REFERENCE, "Reference %s stopped existing in the packfile", ref->name); return -1; } + packref = git_khash_str_value_at(packfile_refs, pos); + git_khash_str_delete_at(packfile_refs, pos); + git__free(packref); if (packed_write(ref->owner) < 0) return -1; @@ -1467,14 +1483,15 @@ int git_reference_foreach( /* list all the packed references first */ if (list_flags & GIT_REF_PACKED) { const char *ref_name; + void *ref; if (packed_load(repo) < 0) return -1; - GIT_HASHTABLE_FOREACH_KEY(repo->references.packfile, ref_name, + git_khash_str_foreach(repo->references.packfile, ref_name, ref, { if (callback(ref_name, payload) < 0) return 0; - ); + }); } /* now list the loose references, trying not to @@ -1538,10 +1555,11 @@ void git_repository__refcache_free(git_refcache *refs) if (refs->packfile) { struct packref *reference; - GIT_HASHTABLE_FOREACH_VALUE( - refs->packfile, reference, git__free(reference)); + git_khash_str_foreach_value(refs->packfile, reference, { + git__free(reference); + }); - git_hashtable_free(refs->packfile); + git_khash_str_free(refs->packfile); } } |
