summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2010-08-12 23:40:54 +0200
committerVicent Marti <tanoku@gmail.com>2010-08-12 23:40:54 +0200
commit9c9f4fc11c85d621dc5fdcf46bbcb5b5da9ed73f (patch)
treeb74a41b8df31f0fc88809d1d479742b3f5b3c192
parentf2408cc2efc1752bb34011a655f6acdab4e9e602 (diff)
downloadlibgit2-9c9f4fc11c85d621dc5fdcf46bbcb5b5da9ed73f.tar.gz
Add support for manually freeing repo objects
A new method 'git_repository_object_free' allows to manually force the freeing of a repository object, even though they are still automatically managed by the repository and don't need to be freed by the user. Signed-off-by: Vicent Marti <tanoku@gmail.com>
-rw-r--r--src/git/repository.h15
-rw-r--r--src/hashtable.c31
-rw-r--r--src/hashtable.h1
-rw-r--r--src/repository.c48
4 files changed, 73 insertions, 22 deletions
diff --git a/src/git/repository.h b/src/git/repository.h
index 3b6981d50..001e4e9fb 100644
--- a/src/git/repository.h
+++ b/src/git/repository.h
@@ -49,6 +49,21 @@ GIT_EXTERN(git_repository *) git_repository_alloc(git_odb *odb);
*/
GIT_EXTERN(git_repository_object *) git_repository_lookup(git_repository *repo, const git_oid *id, git_otype type);
+
+/**
+ * Free a reference to one of the objects in the repostory.
+ *
+ * Repository objects are managed automatically by the library,
+ * but this method can be used to force freeing one of the
+ * objects.
+ *
+ * Careful: freeing objects in the middle of a repository
+ * traversal will most likely cause errors.
+ *
+ * @param object the object to free
+ */
+GIT_EXTERN(void) git_repository_object_free(git_repository_object *object);
+
/**
* Free a previously allocated repository
* @param repo repository handle to close. If NULL nothing occurs.
diff --git a/src/hashtable.c b/src/hashtable.c
index 4006a8714..242a6fa1d 100644
--- a/src/hashtable.c
+++ b/src/hashtable.c
@@ -183,6 +183,37 @@ void *git_hashtable_lookup(git_hashtable *table, const void *key)
return NULL;
}
+int git_hashtable_remove(git_hashtable *table, const void *key)
+{
+ git_hashtable_node *node, *prev_node;
+ uint32_t index, hash;
+
+ assert(table);
+
+ hash = table->hash(key);
+ index = (hash & table->size_mask);
+ node = table->nodes[index];
+
+ prev_node = NULL;
+
+ while (node != NULL) {
+ if (node->hash == hash && table->key_equal(node->object, key)) {
+ if (prev_node == NULL)
+ table->nodes[index] = node->next;
+ else
+ prev_node->next = node->next;
+
+ free(node);
+ return GIT_SUCCESS;
+ }
+
+ prev_node = node;
+ node = node->next;
+ }
+
+ return GIT_ENOTFOUND;
+}
+
void git_hashtable_iterator_init(git_hashtable *table, git_hashtable_iterator *it)
diff --git a/src/hashtable.h b/src/hashtable.h
index 622a260e1..cd390b9e9 100644
--- a/src/hashtable.h
+++ b/src/hashtable.h
@@ -42,6 +42,7 @@ git_hashtable *git_hashtable_alloc(unsigned int min_size,
git_hash_keyeq_ptr key_eq);
int git_hashtable_insert(git_hashtable *h, const void *key, void *value);
void *git_hashtable_lookup(git_hashtable *h, const void *key);
+int git_hashtable_remove(git_hashtable *table, const void *key);
void git_hashtable_free(git_hashtable *h);
void git_hashtable_clear(git_hashtable *h);
diff --git a/src/repository.c b/src/repository.c
index 58f29ce44..86f2216cb 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -83,28 +83,8 @@ void git_repository_free(git_repository *repo)
git_hashtable_iterator_init(repo->objects, &it);
while ((object = (git_repository_object *)
- git_hashtable_iterator_next(&it)) != NULL) {
-
- git_obj_close(&object->dbo);
-
- switch (object->dbo.type) {
- case GIT_OBJ_COMMIT:
- git_commit__free((git_commit *)object);
- break;
-
- case GIT_OBJ_TREE:
- git_tree__free((git_tree *)object);
- break;
-
- case GIT_OBJ_TAG:
- git_tag__free((git_tag *)object);
- break;
-
- default:
- free(object);
- break;
- }
- }
+ git_hashtable_iterator_next(&it)) != NULL)
+ git_repository_object_free(object);
git_hashtable_free(repo->objects);
/* TODO: free odb */
@@ -134,6 +114,30 @@ void git_repository__close_dbo(git_repository_object *object)
}
}
+void git_repository_object_free(git_repository_object *object)
+{
+ git_hashtable_remove(object->repo->objects, &object->id);
+ git_obj_close(&object->dbo);
+
+ switch (object->dbo.type) {
+ case GIT_OBJ_COMMIT:
+ git_commit__free((git_commit *)object);
+ break;
+
+ case GIT_OBJ_TREE:
+ git_tree__free((git_tree *)object);
+ break;
+
+ case GIT_OBJ_TAG:
+ git_tag__free((git_tag *)object);
+ break;
+
+ default:
+ free(object);
+ break;
+ }
+}
+
git_repository_object *git_repository_lookup(git_repository *repo, const git_oid *id, git_otype type)
{
static const size_t object_sizes[] = {