]> git.proxmox.com Git - libgit2.git/blob - src/repository.c
Fix object handling in git_repository
[libgit2.git] / src / repository.c
1 /*
2 * This file is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2,
4 * as published by the Free Software Foundation.
5 *
6 * In addition to the permissions in the GNU General Public License,
7 * the authors give you unlimited permission to link the compiled
8 * version of this file into combinations with other programs,
9 * and to distribute those combinations without any restriction
10 * coming from the use of this file. (The General Public License
11 * restrictions do apply in other respects; for example, they cover
12 * modification of the file, and distribution when not linked into
13 * a combined executable.)
14 *
15 * This file is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; see the file COPYING. If not, write to
22 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 */
25
26 #include "common.h"
27 #include "repository.h"
28 #include "commit.h"
29 #include "tag.h"
30
31 static const int default_table_size = 32;
32 static const double max_load_factor = 0.65;
33
34 uint32_t git_repository_object_hash(const void *key)
35 {
36 uint32_t r;
37 git_oid *id;
38
39 id = (git_oid *)key;
40 memcpy(&r, id->id, sizeof(r));
41 return r;
42 }
43
44 int git_repository_object_haskey(void *object, const void *key)
45 {
46 git_repository_object *obj;
47 git_oid *oid;
48
49 obj = (git_repository_object *)object;
50 oid = (git_oid *)key;
51
52 return (git_oid_cmp(oid, &obj->id) == 0);
53 }
54
55 git_repository *git_repository_alloc(git_odb *odb)
56 {
57 git_repository *repo = git__malloc(sizeof(git_repository));
58 if (!repo)
59 return NULL;
60
61 memset(repo, 0x0, sizeof(git_repository));
62
63 repo->objects = git_hashtable_alloc(
64 default_table_size,
65 git_repository_object_hash,
66 git_repository_object_haskey);
67
68 if (repo->objects == NULL) {
69 free(repo);
70 return NULL;
71 }
72
73 repo->db = odb; /* TODO: create ODB manually! */
74
75 return repo;
76 }
77
78 void git_repository_free(git_repository *repo)
79 {
80 git_hashtable_iterator it;
81 git_repository_object *object;
82
83 git_hashtable_iterator_init(repo->objects, &it);
84
85 while ((object = (git_repository_object *)
86 git_hashtable_iterator_next(&it)) != NULL) {
87
88 git_obj_close(&object->dbo);
89
90 switch (object->dbo.type) {
91 case GIT_OBJ_COMMIT:
92 git_commit__free((git_commit *)object);
93 break;
94
95 case GIT_OBJ_TREE:
96 git_tree__free((git_tree *)object);
97 break;
98
99 case GIT_OBJ_TAG:
100 git_tag__free((git_tag *)object);
101 break;
102
103 default:
104 free(object);
105 break;
106 }
107 }
108
109 git_hashtable_free(repo->objects);
110 /* TODO: free odb */
111 free(repo);
112 }
113
114 int git_repository__open_dbo(git_repository_object *object)
115 {
116 int error;
117
118 if (object->dbo_open)
119 return GIT_SUCCESS;
120
121 error = git_odb_read(&object->dbo, object->repo->db, &object->id);
122 if (error < 0)
123 return error;
124
125 object->dbo_open = 1;
126 return GIT_SUCCESS;
127 }
128
129 void git_repository__close_dbo(git_repository_object *object)
130 {
131 if (!object->dbo_open) {
132 git_obj_close(&object->dbo);
133 object->dbo_open = 0;
134 }
135 }
136
137 git_repository_object *git_repository_lookup(git_repository *repo, const git_oid *id, git_otype type)
138 {
139 static const size_t object_sizes[] = {
140 0,
141 sizeof(git_commit),
142 sizeof(git_tree),
143 sizeof(git_repository_object), /* TODO: sizeof(git_blob) */
144 sizeof(git_tag)
145 };
146
147 git_repository_object *object = NULL;
148 git_obj obj_file;
149
150 assert(repo);
151
152 object = git_hashtable_lookup(repo->objects, id);
153 if (object != NULL)
154 return object;
155
156 if (git_odb_read(&obj_file, repo->db, id) < 0)
157 return NULL;
158
159 if (type != GIT_OBJ_ANY && type != obj_file.type)
160 return NULL;
161
162 type = obj_file.type;
163
164 object = git__malloc(object_sizes[type]);
165
166 if (object == NULL)
167 return NULL;
168
169 memset(object, 0x0, object_sizes[type]);
170
171 /* Initialize parent object */
172 git_oid_cpy(&object->id, id);
173 object->repo = repo;
174 object->dbo_open = 1;
175 memcpy(&object->dbo, &obj_file, sizeof(git_obj));
176
177 switch (type) {
178
179 case GIT_OBJ_COMMIT:
180 if (git_commit__parse_basic((git_commit *)object) < 0) {
181 free(object);
182 return NULL;
183 }
184
185 break;
186
187 case GIT_OBJ_TREE:
188 if (git_tree__parse((git_tree *)object) < 0) {
189 free(object);
190 return NULL;
191 }
192
193 break;
194
195 case GIT_OBJ_TAG:
196 if (git_tag__parse((git_tag *)object) < 0) {
197 free(object);
198 return NULL;
199 }
200
201 break;
202
203 default:
204 /* blobs get no parsing */
205 break;
206 }
207
208 git_obj_close(&object->dbo);
209 object->dbo_open = 0;
210
211 git_hashtable_insert(repo->objects, &object->id, object);
212 return object;
213 }