/* FIXME: maybe we don't want to free this already?
* the user may want to access it again */
- git_object_close((git_object *)blob);
+ GIT_OBJECT_DECREF(repo, blob);
return GIT_SUCCESS;
}
for (i = 0; i < commit->parents.length; ++i) {
git_commit *parent = git_vector_get(&commit->parents, i);
- git_object_close((git_object *)parent);
+ GIT_OBJECT_DECREF(commit->object.repo, parent);
}
git_vector_clear(&commit->parents);
git_signature_free(commit->author);
git_signature_free(commit->committer);
- git_object_close((git_object *)commit->tree);
+ GIT_OBJECT_DECREF(commit->object.repo, commit->tree);
free(commit->message);
free(commit->message_short);
if ((error = git__parse_oid(&oid, &buffer, buffer_end, "tree ")) < GIT_SUCCESS)
return error;
- git_object_close((git_object *)commit->tree);
+ GIT_OBJECT_DECREF(commit->object.repo, commit->tree);
if ((error = git_object_lookup((git_object **)&commit->tree, commit->object.repo, &oid, GIT_OBJ_TREE)) < GIT_SUCCESS)
return error;
if (!commit->object.in_memory && commit->tree == NULL)
git_commit__parse_full(commit);
- GIT_OBJECT_INCREF(commit->tree);
+ GIT_OBJECT_INCREF(commit->object.repo, commit->tree);
return commit->tree;
}
assert(commit);
parent = git_vector_get(&commit->parents, n);
- GIT_OBJECT_INCREF(parent);
+ GIT_OBJECT_INCREF(commit->object.repo, parent);
return parent;
}
commit->object.modified = 1;
CHECK_FULL_PARSE();
- git_object_close((git_object *)commit->tree);
- GIT_OBJECT_INCREF(tree);
+ GIT_OBJECT_DECREF(commit->object.repo, commit->tree);
+ GIT_OBJECT_INCREF(commit->object.repo, tree);
commit->tree = tree;
}
CHECK_FULL_PARSE();
commit->object.modified = 1;
- GIT_OBJECT_INCREF(new_parent);
+ GIT_OBJECT_INCREF(commit->object.repo, new_parent);
return git_vector_insert(&commit->parents, new_parent);
}
object = git_hashtable_lookup(repo->objects, id);
if (object != NULL) {
*object_out = object;
- GIT_OBJECT_INCREF(object);
+ GIT_OBJECT_INCREF(repo, object);
return GIT_SUCCESS;
}
git_object__source_close(object);
git_hashtable_insert(repo->objects, &object->id, object);
- GIT_OBJECT_INCREF(object);
+ GIT_OBJECT_INCREF(repo, object);
*object_out = object;
return GIT_SUCCESS;
}
git_object__source_close(object);
- if (object->repo != NULL) {
- if (object->in_memory) {
- int idx = git_vector_search(&object->repo->memory_objects, object);
- git_vector_remove(&object->repo->memory_objects, idx);
- } else {
- git_hashtable_remove(object->repo->objects, &object->id);
- }
- }
-
switch (object->source.raw.type) {
case GIT_OBJ_COMMIT:
git_commit__free((git_commit *)object);
if (object == NULL)
return;
- if (--object->refcount <= 0)
+ if (--object->refcount <= 0) {
+ if (object->repo != NULL) {
+ if (object->in_memory) {
+ int idx = git_vector_search(&object->repo->memory_objects, object);
+ git_vector_remove(&object->repo->memory_objects, idx);
+ } else {
+ git_hashtable_remove(object->repo->objects, &object->id);
+ }
+ }
+
git_object__free(object);
+ }
}
const git_oid *git_object_id(const git_object *obj)
return NULL;
}
+ repo->gc_enabled = 1;
return repo;
}
if (repo == NULL)
return;
- /* Increment the refcount of all the objects in the repository
- * to prevent freeing dependencies */
- GIT_HASHTABLE_FOREACH(repo->objects, _unused, object,
- GIT_OBJECT_INCREF(object);
- );
+ repo->gc_enabled = 0;
/* force free all the objects */
GIT_HASHTABLE_FOREACH(repo->objects, _unused, object,
#include "git2/oid.h"
#include "git2/odb.h"
#include "git2/repository.h"
+#include "git2/object.h"
#include "hashtable.h"
#include "index.h"
char *path_odb;
char *path_workdir;
- unsigned is_bare:1;
+ unsigned is_bare:1, gc_enabled:1;
};
int git_object__source_open(git_object *object);
int git__parse_oid(git_oid *oid, char **buffer_out, const char *buffer_end, const char *header);
int git__write_oid(git_odb_source *src, const char *header, const git_oid *oid);
-#define GIT_OBJECT_INCREF(ob) git_object__incref((git_object *)(ob))
+#define GIT_OBJECT_INCREF(repo, ob) git_object__incref((repo), (git_object *)(ob))
+#define GIT_OBJECT_DECREF(repo, ob) git_object__decref((repo), (git_object *)(ob))
-GIT_INLINE(void) git_object__incref(struct git_object *object)
+GIT_INLINE(void) git_object__incref(git_repository *repo, struct git_object *object)
{
- if (object)
+ if (repo && repo->gc_enabled && object)
object->refcount++;
}
+GIT_INLINE(void) git_object__decref(git_repository *repo, struct git_object *object)
+{
+ if (repo && repo->gc_enabled && object)
+ git_object_close(object);
+}
+
#endif
memset(commit, 0x0, sizeof(git_revwalk_commit));
commit->commit_object = commit_object;
- GIT_OBJECT_INCREF(commit_object);
+ GIT_OBJECT_INCREF(walk->repo, commit_object);
git_hashtable_insert(walk->commits, commit_object, commit);
while ((next = walk->next(&walk->iterator)) != NULL) {
if (!next->uninteresting) {
*commit = next->commit_object;
- GIT_OBJECT_INCREF(*commit);
+ GIT_OBJECT_INCREF(walk->repo, *commit);
return GIT_SUCCESS;
}
}
assert(walk);
GIT_HASHTABLE_FOREACH(walk->commits, _unused, commit, {
- git_object_close((git_object *)commit->commit_object);
+ GIT_OBJECT_DECREF(walk->repo, commit->commit_object);
git_revwalk_list_clear(&commit->parents);
free(commit);
});
void git_tag__free(git_tag *tag)
{
git_signature_free(tag->tagger);
- git_object_close(tag->target);
+ GIT_OBJECT_DECREF(tag->object.repo, tag->target);
free(tag->message);
free(tag->tag_name);
free(tag);
const git_object *git_tag_target(git_tag *t)
{
assert(t);
- GIT_OBJECT_INCREF(t->target);
+ GIT_OBJECT_INCREF(t->object.repo, t->target);
return t->target;
}
{
assert(tag && target);
- git_object_close(tag->target);
- GIT_OBJECT_INCREF(target);
+ GIT_OBJECT_DECREF(tag->object.repo, tag->target);
+ GIT_OBJECT_INCREF(tag->object.repo, target);
tag->object.modified = 1;
tag->target = target;