Commit c8f5ff8f65617e6e097dd779492bd7af47232d4f

Vicent Marti 2011-01-20T14:43:27

Fix initialization of in-memory trees In-memory tree objects were not being properly initialized, because the internal entries vector was created on the 'parse' method. Signed-off-by: Vicent Marti <tanoku@gmail.com>

diff --git a/src/repository.c b/src/repository.c
index 7e56a4b..97a7e15 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -379,31 +379,48 @@ git_odb *git_repository_database(git_repository *repo)
 	return repo->db;
 }
 
-int git_repository_newobject(git_object **object_out, git_repository *repo, git_otype type)
+static int create_object(git_object **object_out, git_otype type)
 {
 	git_object *object = NULL;
 
-	assert(object_out && repo);
+	assert(object_out);
 
 	*object_out = NULL;
 
 	switch (type) {
 	case GIT_OBJ_COMMIT:
 	case GIT_OBJ_TAG:
-	case GIT_OBJ_TREE:
 	case GIT_OBJ_BLOB:
+		object = git__malloc(git_object__size(type));
+		if (object == NULL)
+			return GIT_ENOMEM;
+		memset(object, 0x0, git_object__size(type));
+		break;
+		
+	case GIT_OBJ_TREE:
+		object = (git_object *)git_tree__new();
+		if (object == NULL)
+			return GIT_ENOMEM;
 		break;
 
 	default:
 		return GIT_EINVALIDTYPE;
 	}
 
-	object = git__malloc(git_object__size(type));
+	*object_out = object;
+	return GIT_SUCCESS;
+}
 
-	if (object == NULL)
-		return GIT_ENOMEM;
+int git_repository_newobject(git_object **object_out, git_repository *repo, git_otype type)
+{
+	git_object *object = NULL;
+	int error;
+
+	assert(object_out && repo);
+
+	if ((error = create_object(&object, type)) < GIT_SUCCESS)
+		return error;
 
-	memset(object, 0x0, git_object__size(type));
 	object->repo = repo;
 	object->in_memory = 1;
 	object->modified = 1;
@@ -439,12 +456,8 @@ int git_repository_lookup(git_object **object_out, git_repository *repo, const g
 
 	type = obj_file.type;
 
-	object = git__malloc(git_object__size(type));
-
-	if (object == NULL)
-		return GIT_ENOMEM;
-
-	memset(object, 0x0, git_object__size(type));
+	if ((error = create_object(&object, type)) < GIT_SUCCESS)
+		return error;
 
 	/* Initialize parent object */
 	git_oid_cpy(&object->id, id);
@@ -453,7 +466,6 @@ int git_repository_lookup(git_object **object_out, git_repository *repo, const g
 	object->source.open = 1;
 
 	switch (type) {
-
 	case GIT_OBJ_COMMIT:
 		error = git_commit__parse((git_commit *)object);
 		break;
diff --git a/src/tree.c b/src/tree.c
index 4655dc7..d160a79 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -30,6 +30,8 @@
 #include "git2/repository.h"
 #include "git2/object.h"
 
+#define DEFAULT_TREE_SIZE 16
+
 int entry_search_cmp(const void *key, const void *array_member)
 {
 	const char *filename = (const char *)key;
@@ -46,7 +48,7 @@ int entry_sort_cmp(const void *a, const void *b)
 	return strcmp(entry_a->filename, entry_b->filename);
 }
 
-static void free_tree_entries(git_tree *tree)
+static void clear_entries(git_tree *tree)
 {
 	unsigned int i;
 
@@ -61,14 +63,35 @@ static void free_tree_entries(git_tree *tree)
 		free(e);
 	}
 
-	git_vector_free(&tree->entries);
+	git_vector_clear(&tree->entries);
 }
 
 
+git_tree *git_tree__new(void)
+{
+	git_tree *tree;
+
+	tree = git__malloc(sizeof(struct git_tree));
+	if (tree == NULL)
+		return NULL;
+
+	memset(tree, 0x0, sizeof(struct git_tree));
+
+	if (git_vector_init(&tree->entries, 
+				DEFAULT_TREE_SIZE,
+				entry_sort_cmp,
+				entry_search_cmp) < GIT_SUCCESS) {
+		free(tree);
+		return NULL;
+	}
+
+	return tree;
+}
 
 void git_tree__free(git_tree *tree)
 {
-	free_tree_entries(tree);
+	clear_entries(tree);
+	git_vector_free(&tree->entries);
 	free(tree);
 }
 
@@ -243,9 +266,7 @@ static int tree_parse_buffer(git_tree *tree, char *buffer, char *buffer_end)
 
 	expected_size = (tree->object.source.raw.len / avg_entry_size) + 1;
 
-	free_tree_entries(tree);
-	if (git_vector_init(&tree->entries, expected_size, entry_sort_cmp, entry_search_cmp) < GIT_SUCCESS)
-		return GIT_ENOMEM;
+	clear_entries(tree);
 
 	while (buffer < buffer_end) {
 		git_tree_entry *entry;
diff --git a/src/tree.h b/src/tree.h
index 5f532f8..78500c4 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -19,6 +19,7 @@ struct git_tree {
 };
 
 void git_tree__free(git_tree *tree);
+git_tree *git_tree__new(void);
 int git_tree__parse(git_tree *tree);
 int git_tree__writeback(git_tree *tree, git_odb_source *src);