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>
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 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
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);