2 * Copyright (C) the libgit2 contributors. All rights reserved.
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
10 #include "git2/object.h"
11 #include "git2/sys/odb_backend.h"
15 #include "delta-apply.h"
17 #include "repository.h"
19 #include "git2/odb_backend.h"
22 #define GIT_ALTERNATES_FILE "info/alternates"
24 /* TODO: is this correct? */
25 #define GIT_LOOSE_PRIORITY 2
26 #define GIT_PACKED_PRIORITY 1
28 #define GIT_ALTERNATES_MAX_DEPTH 5
32 git_odb_backend
*backend
;
38 static git_cache
*odb_cache(git_odb
*odb
)
40 if (odb
->rc
.owner
!= NULL
) {
41 git_repository
*owner
= odb
->rc
.owner
;
42 return &owner
->objects
;
45 return &odb
->own_cache
;
48 static int load_alternates(git_odb
*odb
, const char *objects_dir
, int alternate_depth
);
50 int git_odb__format_object_header(char *hdr
, size_t n
, size_t obj_len
, git_otype obj_type
)
52 const char *type_str
= git_object_type2string(obj_type
);
53 int len
= p_snprintf(hdr
, n
, "%s %"PRIuZ
, type_str
, obj_len
);
54 assert(len
> 0 && len
<= (int)n
);
58 int git_odb__hashobj(git_oid
*id
, git_rawobj
*obj
)
66 if (!git_object_typeisloose(obj
->type
))
69 if (!obj
->data
&& obj
->len
!= 0)
72 hdrlen
= git_odb__format_object_header(header
, sizeof(header
), obj
->len
, obj
->type
);
76 vec
[1].data
= obj
->data
;
77 vec
[1].len
= obj
->len
;
79 git_hash_vec(id
, vec
, 2);
85 static git_odb_object
*odb_object__alloc(const git_oid
*oid
, git_rawobj
*source
)
87 git_odb_object
*object
= git__calloc(1, sizeof(git_odb_object
));
90 git_oid_cpy(&object
->cached
.oid
, oid
);
91 object
->cached
.type
= source
->type
;
92 object
->cached
.size
= source
->len
;
93 object
->buffer
= source
->data
;
99 void git_odb_object__free(void *object
)
101 if (object
!= NULL
) {
102 git__free(((git_odb_object
*)object
)->buffer
);
107 const git_oid
*git_odb_object_id(git_odb_object
*object
)
109 return &object
->cached
.oid
;
112 const void *git_odb_object_data(git_odb_object
*object
)
114 return object
->buffer
;
117 size_t git_odb_object_size(git_odb_object
*object
)
119 return object
->cached
.size
;
122 git_otype
git_odb_object_type(git_odb_object
*object
)
124 return object
->cached
.type
;
127 int git_odb_object_dup(git_odb_object
**dest
, git_odb_object
*source
)
129 git_cached_obj_incref(source
);
134 void git_odb_object_free(git_odb_object
*object
)
139 git_cached_obj_decref(object
);
142 int git_odb__hashfd(git_oid
*out
, git_file fd
, size_t size
, git_otype type
)
145 char hdr
[64], buffer
[2048];
147 ssize_t read_len
= 0;
150 if (!git_object_typeisloose(type
)) {
151 giterr_set(GITERR_INVALID
, "Invalid object type for hash");
155 if ((error
= git_hash_ctx_init(&ctx
)) < 0)
158 hdr_len
= git_odb__format_object_header(hdr
, sizeof(hdr
), size
, type
);
160 if ((error
= git_hash_update(&ctx
, hdr
, hdr_len
)) < 0)
163 while (size
> 0 && (read_len
= p_read(fd
, buffer
, sizeof(buffer
))) > 0) {
164 if ((error
= git_hash_update(&ctx
, buffer
, read_len
)) < 0)
170 /* If p_read returned an error code, the read obviously failed.
171 * If size is not zero, the file was truncated after we originally
172 * stat'd it, so we consider this a read failure too */
173 if (read_len
< 0 || size
> 0) {
174 giterr_set(GITERR_OS
, "Error reading file for hashing");
180 error
= git_hash_final(out
, &ctx
);
183 git_hash_ctx_cleanup(&ctx
);
187 int git_odb__hashfd_filtered(
188 git_oid
*out
, git_file fd
, size_t size
, git_otype type
, git_filter_list
*fl
)
191 git_buf raw
= GIT_BUF_INIT
;
194 return git_odb__hashfd(out
, fd
, size
, type
);
196 /* size of data is used in header, so we have to read the whole file
197 * into memory to apply filters before beginning to calculate the hash
200 if (!(error
= git_futils_readbuffer_fd(&raw
, fd
, size
))) {
201 git_buf post
= GIT_BUF_INIT
;
203 error
= git_filter_list_apply_to_data(&post
, fl
, &raw
);
208 error
= git_odb_hash(out
, post
.ptr
, post
.size
, type
);
216 int git_odb__hashlink(git_oid
*out
, const char *path
)
222 if (git_path_lstat(path
, &st
) < 0)
227 if (!git__is_sizet(size
)) {
228 giterr_set(GITERR_OS
, "File size overflow for 32-bit systems");
232 if (S_ISLNK(st
.st_mode
)) {
236 link_data
= git__malloc((size_t)(size
+ 1));
237 GITERR_CHECK_ALLOC(link_data
);
239 read_len
= p_readlink(path
, link_data
, (size_t)size
);
240 link_data
[size
] = '\0';
241 if (read_len
!= (ssize_t
)size
) {
242 giterr_set(GITERR_OS
, "Failed to read symlink data for '%s'", path
);
243 git__free(link_data
);
247 result
= git_odb_hash(out
, link_data
, (size_t)size
, GIT_OBJ_BLOB
);
248 git__free(link_data
);
250 int fd
= git_futils_open_ro(path
);
253 result
= git_odb__hashfd(out
, fd
, (size_t)size
, GIT_OBJ_BLOB
);
260 int git_odb_hashfile(git_oid
*out
, const char *path
, git_otype type
)
263 int result
, fd
= git_futils_open_ro(path
);
267 if ((size
= git_futils_filesize(fd
)) < 0 || !git__is_sizet(size
)) {
268 giterr_set(GITERR_OS
, "File size overflow for 32-bit systems");
273 result
= git_odb__hashfd(out
, fd
, (size_t)size
, type
);
278 int git_odb_hash(git_oid
*id
, const void *data
, size_t len
, git_otype type
)
284 raw
.data
= (void *)data
;
288 return git_odb__hashobj(id
, &raw
);
296 git_odb_stream stream
;
298 size_t size
, written
;
302 static int fake_wstream__fwrite(git_odb_stream
*_stream
, const git_oid
*oid
)
304 fake_wstream
*stream
= (fake_wstream
*)_stream
;
305 return _stream
->backend
->write(_stream
->backend
, oid
, stream
->buffer
, stream
->size
, stream
->type
);
308 static int fake_wstream__write(git_odb_stream
*_stream
, const char *data
, size_t len
)
310 fake_wstream
*stream
= (fake_wstream
*)_stream
;
312 if (stream
->written
+ len
> stream
->size
)
315 memcpy(stream
->buffer
+ stream
->written
, data
, len
);
316 stream
->written
+= len
;
320 static void fake_wstream__free(git_odb_stream
*_stream
)
322 fake_wstream
*stream
= (fake_wstream
*)_stream
;
324 git__free(stream
->buffer
);
328 static int init_fake_wstream(git_odb_stream
**stream_p
, git_odb_backend
*backend
, size_t size
, git_otype type
)
330 fake_wstream
*stream
;
332 stream
= git__calloc(1, sizeof(fake_wstream
));
333 GITERR_CHECK_ALLOC(stream
);
337 stream
->buffer
= git__malloc(size
);
338 if (stream
->buffer
== NULL
) {
343 stream
->stream
.backend
= backend
;
344 stream
->stream
.read
= NULL
; /* read only */
345 stream
->stream
.write
= &fake_wstream__write
;
346 stream
->stream
.finalize_write
= &fake_wstream__fwrite
;
347 stream
->stream
.free
= &fake_wstream__free
;
348 stream
->stream
.mode
= GIT_STREAM_WRONLY
;
350 *stream_p
= (git_odb_stream
*)stream
;
354 /***********************************************************
356 * OBJECT DATABASE PUBLIC API
358 * Public calls for the ODB functionality
360 ***********************************************************/
362 static int backend_sort_cmp(const void *a
, const void *b
)
364 const backend_internal
*backend_a
= (const backend_internal
*)(a
);
365 const backend_internal
*backend_b
= (const backend_internal
*)(b
);
367 if (backend_a
->is_alternate
== backend_b
->is_alternate
)
368 return (backend_b
->priority
- backend_a
->priority
);
370 return backend_a
->is_alternate
? 1 : -1;
373 int git_odb_new(git_odb
**out
)
375 git_odb
*db
= git__calloc(1, sizeof(*db
));
376 GITERR_CHECK_ALLOC(db
);
378 if (git_cache_init(&db
->own_cache
) < 0 ||
379 git_vector_init(&db
->backends
, 4, backend_sort_cmp
) < 0) {
385 GIT_REFCOUNT_INC(db
);
389 static int add_backend_internal(
390 git_odb
*odb
, git_odb_backend
*backend
,
391 int priority
, bool is_alternate
, ino_t disk_inode
)
393 backend_internal
*internal
;
395 assert(odb
&& backend
);
397 GITERR_CHECK_VERSION(backend
, GIT_ODB_BACKEND_VERSION
, "git_odb_backend");
399 /* Check if the backend is already owned by another ODB */
400 assert(!backend
->odb
|| backend
->odb
== odb
);
402 internal
= git__malloc(sizeof(backend_internal
));
403 GITERR_CHECK_ALLOC(internal
);
405 internal
->backend
= backend
;
406 internal
->priority
= priority
;
407 internal
->is_alternate
= is_alternate
;
408 internal
->disk_inode
= disk_inode
;
410 if (git_vector_insert(&odb
->backends
, internal
) < 0) {
415 git_vector_sort(&odb
->backends
);
416 internal
->backend
->odb
= odb
;
420 int git_odb_add_backend(git_odb
*odb
, git_odb_backend
*backend
, int priority
)
422 return add_backend_internal(odb
, backend
, priority
, false, 0);
425 int git_odb_add_alternate(git_odb
*odb
, git_odb_backend
*backend
, int priority
)
427 return add_backend_internal(odb
, backend
, priority
, true, 0);
430 size_t git_odb_num_backends(git_odb
*odb
)
433 return odb
->backends
.length
;
436 static int git_odb__error_unsupported_in_backend(const char *action
)
438 giterr_set(GITERR_ODB
,
439 "Cannot %s - unsupported in the loaded odb backends", action
);
444 int git_odb_get_backend(git_odb_backend
**out
, git_odb
*odb
, size_t pos
)
446 backend_internal
*internal
;
449 internal
= git_vector_get(&odb
->backends
, pos
);
451 if (internal
&& internal
->backend
) {
452 *out
= internal
->backend
;
456 giterr_set(GITERR_ODB
, "No ODB backend loaded at index %" PRIuZ
, pos
);
457 return GIT_ENOTFOUND
;
460 static int add_default_backends(
461 git_odb
*db
, const char *objects_dir
,
462 bool as_alternates
, int alternate_depth
)
467 git_odb_backend
*loose
, *packed
;
469 /* TODO: inodes are not really relevant on Win32, so we need to find
470 * a cross-platform workaround for this */
477 if (p_stat(objects_dir
, &st
) < 0) {
481 giterr_set(GITERR_ODB
, "Failed to load object database in '%s'", objects_dir
);
487 for (i
= 0; i
< db
->backends
.length
; ++i
) {
488 backend_internal
*backend
= git_vector_get(&db
->backends
, i
);
489 if (backend
->disk_inode
== inode
)
494 /* add the loose object backend */
495 if (git_odb_backend_loose(&loose
, objects_dir
, -1, 0) < 0 ||
496 add_backend_internal(db
, loose
, GIT_LOOSE_PRIORITY
, as_alternates
, inode
) < 0)
499 /* add the packed file backend */
500 if (git_odb_backend_pack(&packed
, objects_dir
) < 0 ||
501 add_backend_internal(db
, packed
, GIT_PACKED_PRIORITY
, as_alternates
, inode
) < 0)
504 return load_alternates(db
, objects_dir
, alternate_depth
);
507 static int load_alternates(git_odb
*odb
, const char *objects_dir
, int alternate_depth
)
509 git_buf alternates_path
= GIT_BUF_INIT
;
510 git_buf alternates_buf
= GIT_BUF_INIT
;
512 const char *alternate
;
515 /* Git reports an error, we just ignore anything deeper */
516 if (alternate_depth
> GIT_ALTERNATES_MAX_DEPTH
)
519 if (git_buf_joinpath(&alternates_path
, objects_dir
, GIT_ALTERNATES_FILE
) < 0)
522 if (git_path_exists(alternates_path
.ptr
) == false) {
523 git_buf_free(&alternates_path
);
527 if (git_futils_readbuffer(&alternates_buf
, alternates_path
.ptr
) < 0) {
528 git_buf_free(&alternates_path
);
532 buffer
= (char *)alternates_buf
.ptr
;
534 /* add each alternate as a new backend; one alternate per line */
535 while ((alternate
= git__strtok(&buffer
, "\r\n")) != NULL
) {
536 if (*alternate
== '\0' || *alternate
== '#')
540 * Relative path: build based on the current `objects`
541 * folder. However, relative paths are only allowed in
542 * the current repository.
544 if (*alternate
== '.' && !alternate_depth
) {
545 if ((result
= git_buf_joinpath(&alternates_path
, objects_dir
, alternate
)) < 0)
547 alternate
= git_buf_cstr(&alternates_path
);
550 if ((result
= add_default_backends(odb
, alternate
, true, alternate_depth
+ 1)) < 0)
554 git_buf_free(&alternates_path
);
555 git_buf_free(&alternates_buf
);
560 int git_odb_add_disk_alternate(git_odb
*odb
, const char *path
)
562 return add_default_backends(odb
, path
, true, 0);
565 int git_odb_open(git_odb
**out
, const char *objects_dir
)
569 assert(out
&& objects_dir
);
573 if (git_odb_new(&db
) < 0)
576 if (add_default_backends(db
, objects_dir
, 0, 0) < 0) {
585 static void odb_free(git_odb
*db
)
589 for (i
= 0; i
< db
->backends
.length
; ++i
) {
590 backend_internal
*internal
= git_vector_get(&db
->backends
, i
);
591 git_odb_backend
*backend
= internal
->backend
;
593 if (backend
->free
) backend
->free(backend
);
594 else git__free(backend
);
599 git_vector_free(&db
->backends
);
600 git_cache_free(&db
->own_cache
);
602 git__memzero(db
, sizeof(*db
));
606 void git_odb_free(git_odb
*db
)
611 GIT_REFCOUNT_DEC(db
, odb_free
);
614 int git_odb_exists(git_odb
*db
, const git_oid
*id
)
616 git_odb_object
*object
;
622 if ((object
= git_cache_get_raw(odb_cache(db
), id
)) != NULL
) {
623 git_odb_object_free(object
);
627 for (i
= 0; i
< db
->backends
.length
&& !found
; ++i
) {
628 backend_internal
*internal
= git_vector_get(&db
->backends
, i
);
629 git_odb_backend
*b
= internal
->backend
;
631 if (b
->exists
!= NULL
)
632 found
= (bool)b
->exists(b
, id
);
638 int git_odb_read_header(size_t *len_p
, git_otype
*type_p
, git_odb
*db
, const git_oid
*id
)
641 git_odb_object
*object
;
643 error
= git_odb__read_header_or_object(&object
, len_p
, type_p
, db
, id
);
646 git_odb_object_free(object
);
651 int git_odb__read_header_or_object(
652 git_odb_object
**out
, size_t *len_p
, git_otype
*type_p
,
653 git_odb
*db
, const git_oid
*id
)
656 int error
= GIT_ENOTFOUND
;
657 git_odb_object
*object
;
659 assert(db
&& id
&& out
&& len_p
&& type_p
);
661 if ((object
= git_cache_get_raw(odb_cache(db
), id
)) != NULL
) {
662 *len_p
= object
->cached
.size
;
663 *type_p
= object
->cached
.type
;
670 for (i
= 0; i
< db
->backends
.length
&& error
< 0; ++i
) {
671 backend_internal
*internal
= git_vector_get(&db
->backends
, i
);
672 git_odb_backend
*b
= internal
->backend
;
674 if (b
->read_header
!= NULL
)
675 error
= b
->read_header(len_p
, type_p
, b
, id
);
678 if (!error
|| error
== GIT_PASSTHROUGH
)
682 * no backend could read only the header.
683 * try reading the whole object and freeing the contents
685 if ((error
= git_odb_read(&object
, db
, id
)) < 0)
686 return error
; /* error already set - pass along */
688 *len_p
= object
->cached
.size
;
689 *type_p
= object
->cached
.type
;
695 int git_odb_read(git_odb_object
**out
, git_odb
*db
, const git_oid
*id
)
700 git_odb_object
*object
;
702 assert(out
&& db
&& id
);
704 *out
= git_cache_get_raw(odb_cache(db
), id
);
708 error
= GIT_ENOTFOUND
;
710 for (i
= 0; i
< db
->backends
.length
&& error
< 0; ++i
) {
711 backend_internal
*internal
= git_vector_get(&db
->backends
, i
);
712 git_odb_backend
*b
= internal
->backend
;
714 if (b
->read
!= NULL
) {
716 error
= b
->read(&raw
.data
, &raw
.len
, &raw
.type
, b
, id
);
720 if (error
&& error
!= GIT_PASSTHROUGH
) {
722 return git_odb__error_notfound("no match for id", id
);
726 if ((object
= odb_object__alloc(id
, &raw
)) == NULL
)
729 *out
= git_cache_store_raw(odb_cache(db
), object
);
733 int git_odb_read_prefix(
734 git_odb_object
**out
, git_odb
*db
, const git_oid
*short_id
, size_t len
)
737 int error
= GIT_ENOTFOUND
;
738 git_oid found_full_oid
= {{0}};
742 git_odb_object
*object
;
746 if (len
< GIT_OID_MINPREFIXLEN
)
747 return git_odb__error_ambiguous("prefix length too short");
749 if (len
> GIT_OID_HEXSZ
)
752 if (len
== GIT_OID_HEXSZ
) {
753 *out
= git_cache_get_raw(odb_cache(db
), short_id
);
758 for (i
= 0; i
< db
->backends
.length
; ++i
) {
759 backend_internal
*internal
= git_vector_get(&db
->backends
, i
);
760 git_odb_backend
*b
= internal
->backend
;
762 if (b
->read_prefix
!= NULL
) {
764 error
= b
->read_prefix(&full_oid
, &raw
.data
, &raw
.len
, &raw
.type
, b
, short_id
, len
);
765 if (error
== GIT_ENOTFOUND
|| error
== GIT_PASSTHROUGH
)
774 if (found
&& git_oid__cmp(&full_oid
, &found_full_oid
)) {
776 return git_odb__error_ambiguous("multiple matches for prefix");
779 found_full_oid
= full_oid
;
785 return git_odb__error_notfound("no match for prefix", short_id
);
787 if ((object
= odb_object__alloc(&found_full_oid
, &raw
)) == NULL
)
790 *out
= git_cache_store_raw(odb_cache(db
), object
);
794 int git_odb_foreach(git_odb
*db
, git_odb_foreach_cb cb
, void *payload
)
797 backend_internal
*internal
;
799 git_vector_foreach(&db
->backends
, i
, internal
) {
800 git_odb_backend
*b
= internal
->backend
;
801 int error
= b
->foreach(b
, cb
, payload
);
810 git_oid
*oid
, git_odb
*db
, const void *data
, size_t len
, git_otype type
)
813 int error
= GIT_ERROR
;
814 git_odb_stream
*stream
;
818 git_odb_hash(oid
, data
, len
, type
);
819 if (git_odb_exists(db
, oid
))
822 for (i
= 0; i
< db
->backends
.length
&& error
< 0; ++i
) {
823 backend_internal
*internal
= git_vector_get(&db
->backends
, i
);
824 git_odb_backend
*b
= internal
->backend
;
826 /* we don't write in alternates! */
827 if (internal
->is_alternate
)
830 if (b
->write
!= NULL
)
831 error
= b
->write(b
, oid
, data
, len
, type
);
834 if (!error
|| error
== GIT_PASSTHROUGH
)
837 /* if no backends were able to write the object directly, we try a
838 * streaming write to the backends; just write the whole object into the
841 if ((error
= git_odb_open_wstream(&stream
, db
, len
, type
)) != 0)
844 stream
->write(stream
, data
, len
);
845 error
= stream
->finalize_write(stream
, oid
);
846 git_odb_stream_free(stream
);
851 static void hash_header(git_hash_ctx
*ctx
, size_t size
, git_otype type
)
856 hdrlen
= git_odb__format_object_header(header
, sizeof(header
), size
, type
);
857 git_hash_update(ctx
, header
, hdrlen
);
860 int git_odb_open_wstream(
861 git_odb_stream
**stream
, git_odb
*db
, size_t size
, git_otype type
)
863 size_t i
, writes
= 0;
864 int error
= GIT_ERROR
;
867 assert(stream
&& db
);
869 for (i
= 0; i
< db
->backends
.length
&& error
< 0; ++i
) {
870 backend_internal
*internal
= git_vector_get(&db
->backends
, i
);
871 git_odb_backend
*b
= internal
->backend
;
873 /* we don't write in alternates! */
874 if (internal
->is_alternate
)
877 if (b
->writestream
!= NULL
) {
879 error
= b
->writestream(stream
, b
, size
, type
);
880 } else if (b
->write
!= NULL
) {
882 error
= init_fake_wstream(stream
, b
, size
, type
);
886 if (error
== GIT_PASSTHROUGH
)
888 if (error
< 0 && !writes
)
889 error
= git_odb__error_unsupported_in_backend("write object");
891 ctx
= git__malloc(sizeof(git_hash_ctx
));
892 GITERR_CHECK_ALLOC(ctx
);
895 git_hash_ctx_init(ctx
);
896 hash_header(ctx
, size
, type
);
897 (*stream
)->hash_ctx
= ctx
;
899 (*stream
)->declared_size
= size
;
900 (*stream
)->received_bytes
= 0;
905 static int git_odb_stream__invalid_length(
906 const git_odb_stream
*stream
,
909 giterr_set(GITERR_ODB
,
911 "Invalid length. %"PRIuZ
" was expected. The "
912 "total size of the received chunks amounts to %"PRIuZ
".",
913 action
, stream
->declared_size
, stream
->received_bytes
);
918 int git_odb_stream_write(git_odb_stream
*stream
, const char *buffer
, size_t len
)
920 git_hash_update(stream
->hash_ctx
, buffer
, len
);
922 stream
->received_bytes
+= len
;
924 if (stream
->received_bytes
> stream
->declared_size
)
925 return git_odb_stream__invalid_length(stream
,
928 return stream
->write(stream
, buffer
, len
);
931 int git_odb_stream_finalize_write(git_oid
*out
, git_odb_stream
*stream
)
933 if (stream
->received_bytes
!= stream
->declared_size
)
934 return git_odb_stream__invalid_length(stream
,
935 "stream_finalize_write()");
937 git_hash_final(out
, stream
->hash_ctx
);
939 if (git_odb_exists(stream
->backend
->odb
, out
))
942 return stream
->finalize_write(stream
, out
);
945 int git_odb_stream_read(git_odb_stream
*stream
, char *buffer
, size_t len
)
947 return stream
->read(stream
, buffer
, len
);
950 void git_odb_stream_free(git_odb_stream
*stream
)
952 git__free(stream
->hash_ctx
);
953 stream
->free(stream
);
956 int git_odb_open_rstream(git_odb_stream
**stream
, git_odb
*db
, const git_oid
*oid
)
959 int error
= GIT_ERROR
;
961 assert(stream
&& db
);
963 for (i
= 0; i
< db
->backends
.length
&& error
< 0; ++i
) {
964 backend_internal
*internal
= git_vector_get(&db
->backends
, i
);
965 git_odb_backend
*b
= internal
->backend
;
967 if (b
->readstream
!= NULL
) {
969 error
= b
->readstream(stream
, b
, oid
);
973 if (error
== GIT_PASSTHROUGH
)
975 if (error
< 0 && !reads
)
976 error
= git_odb__error_unsupported_in_backend("read object streamed");
981 int git_odb_write_pack(struct git_odb_writepack
**out
, git_odb
*db
, git_transfer_progress_callback progress_cb
, void *progress_payload
)
983 size_t i
, writes
= 0;
984 int error
= GIT_ERROR
;
988 for (i
= 0; i
< db
->backends
.length
&& error
< 0; ++i
) {
989 backend_internal
*internal
= git_vector_get(&db
->backends
, i
);
990 git_odb_backend
*b
= internal
->backend
;
992 /* we don't write in alternates! */
993 if (internal
->is_alternate
)
996 if (b
->writepack
!= NULL
) {
998 error
= b
->writepack(out
, b
, db
, progress_cb
, progress_payload
);
1002 if (error
== GIT_PASSTHROUGH
)
1004 if (error
< 0 && !writes
)
1005 error
= git_odb__error_unsupported_in_backend("write pack");
1010 void *git_odb_backend_malloc(git_odb_backend
*backend
, size_t len
)
1012 GIT_UNUSED(backend
);
1013 return git__malloc(len
);
1016 int git_odb_refresh(struct git_odb
*db
)
1021 for (i
= 0; i
< db
->backends
.length
; ++i
) {
1022 backend_internal
*internal
= git_vector_get(&db
->backends
, i
);
1023 git_odb_backend
*b
= internal
->backend
;
1025 if (b
->refresh
!= NULL
) {
1026 int error
= b
->refresh(b
);
1035 int git_odb__error_notfound(const char *message
, const git_oid
*oid
)
1038 char oid_str
[GIT_OID_HEXSZ
+ 1];
1039 git_oid_tostr(oid_str
, sizeof(oid_str
), oid
);
1040 giterr_set(GITERR_ODB
, "Object not found - %s (%s)", message
, oid_str
);
1042 giterr_set(GITERR_ODB
, "Object not found - %s", message
);
1044 return GIT_ENOTFOUND
;
1047 int git_odb__error_ambiguous(const char *message
)
1049 giterr_set(GITERR_ODB
, "Ambiguous SHA1 prefix - %s", message
);
1050 return GIT_EAMBIGUOUS
;