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>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
diff --git a/src/git/repository.h b/src/git/repository.h
index 3b6981d..001e4e9 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 4006a87..242a6fa 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 622a260..cd390b9 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 58f29ce..86f2216 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[] = {