]>
git.proxmox.com Git - libgit2.git/blob - src/object.c
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.
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.)
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.
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.
27 #include "git2/object.h"
30 #include "repository.h"
37 static const int OBJECT_BASE_SIZE
= 4096;
40 const char *str
; /* type name string */
41 int loose
; /* valid loose object type flag */
42 size_t size
; /* size in bytes of the object structure */
43 } git_objects_table
[] = {
44 /* 0 = GIT_OBJ__EXT1 */
47 /* 1 = GIT_OBJ_COMMIT */
48 { "commit", 1, sizeof(struct git_commit
)},
50 /* 2 = GIT_OBJ_TREE */
51 { "tree", 1, sizeof(struct git_tree
) },
53 /* 3 = GIT_OBJ_BLOB */
54 { "blob", 1, sizeof(struct git_blob
) },
57 { "tag", 1, sizeof(struct git_tag
) },
59 /* 5 = GIT_OBJ__EXT2 */
62 /* 6 = GIT_OBJ_OFS_DELTA */
63 { "OFS_DELTA", 0, 0 },
65 /* 7 = GIT_OBJ_REF_DELTA */
70 * Object source methods
72 * Abstract buffer methods that allow the writeback system
73 * to prepare the contents of any git file in-memory before
74 * writing them to disk.
76 static int source_resize(git_odb_source
*src
)
78 size_t write_offset
, new_size
;
81 write_offset
= (size_t)((char *)src
->write_ptr
- (char *)src
->raw
.data
);
83 new_size
= src
->raw
.len
* 2;
84 if ((new_data
= git__malloc(new_size
)) == NULL
)
87 memcpy(new_data
, src
->raw
.data
, src
->written_bytes
);
90 src
->raw
.data
= new_data
;
91 src
->raw
.len
= new_size
;
92 src
->write_ptr
= (char *)new_data
+ write_offset
;
97 int git__source_printf(git_odb_source
*source
, const char *format
, ...)
102 assert(source
->open
&& source
->write_ptr
);
104 va_start(arglist
, format
);
106 len
= vsnprintf(source
->write_ptr
, source
->raw
.len
- source
->written_bytes
, format
, arglist
);
108 while (source
->written_bytes
+ len
>= source
->raw
.len
) {
109 if (source_resize(source
) < GIT_SUCCESS
)
112 len
= vsnprintf(source
->write_ptr
, source
->raw
.len
- source
->written_bytes
, format
, arglist
);
115 source
->write_ptr
= (char *)source
->write_ptr
+ len
;
116 source
->written_bytes
+= len
;
121 int git__source_write(git_odb_source
*source
, const void *bytes
, size_t len
)
125 assert(source
->open
&& source
->write_ptr
);
127 while (source
->written_bytes
+ len
>= source
->raw
.len
) {
128 if (source_resize(source
) < GIT_SUCCESS
)
132 memcpy(source
->write_ptr
, bytes
, len
);
133 source
->write_ptr
= (char *)source
->write_ptr
+ len
;
134 source
->written_bytes
+= len
;
139 static void prepare_write(git_object
*object
)
141 if (object
->source
.write_ptr
!= NULL
|| object
->source
.open
)
142 git_object__source_close(object
);
144 /* TODO: proper size calculation */
145 object
->source
.raw
.data
= git__malloc(OBJECT_BASE_SIZE
);
146 object
->source
.raw
.len
= OBJECT_BASE_SIZE
;
148 object
->source
.write_ptr
= object
->source
.raw
.data
;
149 object
->source
.written_bytes
= 0;
151 object
->source
.open
= 1;
154 static int write_back(git_object
*object
)
161 assert(object
->source
.open
);
162 assert(object
->modified
);
164 object
->source
.raw
.len
= object
->source
.written_bytes
;
166 if ((error
= git_odb_write(&new_id
, object
->repo
->db
, &object
->source
.raw
)) < GIT_SUCCESS
)
169 if (object
->in_memory
) {
170 int idx
= git_vector_search(&object
->repo
->memory_objects
, object
);
171 git_vector_remove(&object
->repo
->memory_objects
, idx
);
173 git_hashtable_remove(object
->repo
->objects
, &object
->id
);
176 git_oid_cpy(&object
->id
, &new_id
);
177 git_hashtable_insert(object
->repo
->objects
, &object
->id
, object
);
179 object
->source
.write_ptr
= NULL
;
180 object
->source
.written_bytes
= 0;
182 object
->modified
= 0;
183 object
->in_memory
= 0;
185 git_object__source_close(object
);
189 int git_object__source_open(git_object
*object
)
193 assert(object
&& !object
->in_memory
);
195 if (object
->source
.open
)
196 git_object__source_close(object
);
198 error
= git_odb_read(&object
->source
.raw
, object
->repo
->db
, &object
->id
);
199 if (error
< GIT_SUCCESS
)
202 object
->source
.open
= 1;
206 void git_object__source_close(git_object
*object
)
210 if (object
->source
.open
) {
211 git_rawobj_close(&object
->source
.raw
);
212 object
->source
.open
= 0;
216 static int create_object(git_object
**object_out
, git_otype type
)
218 git_object
*object
= NULL
;
228 object
= git__malloc(git_object__size(type
));
231 memset(object
, 0x0, git_object__size(type
));
235 object
= (git_object
*)git_tree__new();
241 return GIT_EINVALIDTYPE
;
244 *object_out
= object
;
248 int git_object_new(git_object
**object_out
, git_repository
*repo
, git_otype type
)
250 git_object
*object
= NULL
;
253 assert(object_out
&& repo
);
255 if ((error
= create_object(&object
, type
)) < GIT_SUCCESS
)
259 object
->in_memory
= 1;
260 object
->modified
= 1;
262 object
->source
.raw
.type
= type
;
265 *object_out
= object
;
269 int git_object_lookup(git_object
**object_out
, git_repository
*repo
, const git_oid
*id
, git_otype type
)
271 git_object
*object
= NULL
;
273 int error
= GIT_SUCCESS
;
275 assert(repo
&& object_out
&& id
);
277 object
= git_hashtable_lookup(repo
->objects
, id
);
278 if (object
!= NULL
) {
279 *object_out
= object
;
280 GIT_OBJECT_INCREF(repo
, object
);
284 error
= git_odb_read(&obj_file
, repo
->db
, id
);
285 if (error
< GIT_SUCCESS
)
288 if (type
!= GIT_OBJ_ANY
&& type
!= obj_file
.type
) {
289 git_rawobj_close(&obj_file
);
290 return GIT_EINVALIDTYPE
;
293 type
= obj_file
.type
;
295 if ((error
= create_object(&object
, type
)) < GIT_SUCCESS
)
298 /* Initialize parent object */
299 git_oid_cpy(&object
->id
, id
);
301 memcpy(&object
->source
.raw
, &obj_file
, sizeof(git_rawobj
));
302 object
->source
.open
= 1;
306 error
= git_commit__parse((git_commit
*)object
);
310 error
= git_tree__parse((git_tree
*)object
);
314 error
= git_tag__parse((git_tag
*)object
);
318 error
= git_blob__parse((git_blob
*)object
);
325 if (error
< GIT_SUCCESS
) {
326 git_object__free(object
);
330 git_object__source_close(object
);
331 git_hashtable_insert(repo
->objects
, &object
->id
, object
);
333 GIT_OBJECT_INCREF(repo
, object
);
334 *object_out
= object
;
338 int git_object_write(git_object
*object
)
341 git_odb_source
*source
;
345 if (object
->modified
== 0)
348 prepare_write(object
);
349 source
= &object
->source
;
351 switch (source
->raw
.type
) {
353 error
= git_commit__writeback((git_commit
*)object
, source
);
357 error
= git_tree__writeback((git_tree
*)object
, source
);
361 error
= git_tag__writeback((git_tag
*)object
, source
);
365 error
= git_blob__writeback((git_blob
*)object
, source
);
373 if (error
< GIT_SUCCESS
) {
374 git_object__source_close(object
);
378 return write_back(object
);
381 void git_object__free(git_object
*object
)
385 git_object__source_close(object
);
387 switch (object
->source
.raw
.type
) {
389 git_commit__free((git_commit
*)object
);
393 git_tree__free((git_tree
*)object
);
397 git_tag__free((git_tag
*)object
);
401 git_blob__free((git_blob
*)object
);
410 void git_object_close(git_object
*object
)
415 if (--object
->refcount
<= 0) {
416 if (object
->repo
!= NULL
) {
417 if (object
->in_memory
) {
418 int idx
= git_vector_search(&object
->repo
->memory_objects
, object
);
419 git_vector_remove(&object
->repo
->memory_objects
, idx
);
421 git_hashtable_remove(object
->repo
->objects
, &object
->id
);
425 git_object__free(object
);
429 const git_oid
*git_object_id(const git_object
*obj
)
439 git_otype
git_object_type(const git_object
*obj
)
442 return obj
->source
.raw
.type
;
445 git_repository
*git_object_owner(const git_object
*obj
)
451 const char *git_object_type2string(git_otype type
)
453 if (type
< 0 || ((size_t) type
) >= ARRAY_SIZE(git_objects_table
))
456 return git_objects_table
[type
].str
;
459 git_otype
git_object_string2type(const char *str
)
466 for (i
= 0; i
< ARRAY_SIZE(git_objects_table
); i
++)
467 if (!strcmp(str
, git_objects_table
[i
].str
))
473 int git_object_typeisloose(git_otype type
)
475 if (type
< 0 || ((size_t) type
) >= ARRAY_SIZE(git_objects_table
))
478 return git_objects_table
[type
].loose
;
481 size_t git_object__size(git_otype type
)
483 if (type
< 0 || ((size_t) type
) >= ARRAY_SIZE(git_objects_table
))
486 return git_objects_table
[type
].size
;