]> git.proxmox.com Git - libgit2.git/blame - src/odb.c
New upstream version 1.4.3+dfsg.1
[libgit2.git] / src / odb.c
CommitLineData
c15648cb 1/*
359fc2d2 2 * Copyright (C) the libgit2 contributors. All rights reserved.
c15648cb 3 *
bb742ede
VM
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.
c15648cb
SP
6 */
7
eae0bfdc
PP
8#include "odb.h"
9
0c3bae62 10#include <zlib.h>
44908fe7 11#include "git2/object.h"
83cc70d9 12#include "git2/sys/odb_backend.h"
22a2d3d5 13#include "futils.h"
c960d6a3 14#include "hash.h"
6a2d2f8a 15#include "delta.h"
60b9d3fc 16#include "filter.h"
5df18424 17#include "repository.h"
ac3d33df 18#include "blob.h"
e579e0f7 19#include "oid.h"
c15648cb 20
44908fe7 21#include "git2/odb_backend.h"
c07d9c95 22#include "git2/oid.h"
6c04269c 23#include "git2/oidarray.h"
7b6e8067 24
5a800efc
VM
25#define GIT_ALTERNATES_FILE "info/alternates"
26
c25aa7cd
PP
27#define GIT_ALTERNATES_MAX_DEPTH 5
28
b0d7f329
CMN
29/*
30 * We work under the assumption that most objects for long-running
31 * operations will be packed
32 */
c25aa7cd
PP
33int git_odb__loose_priority = GIT_ODB_DEFAULT_LOOSE_PRIORITY;
34int git_odb__packed_priority = GIT_ODB_DEFAULT_PACKED_PRIORITY;
85e7efa1 35
35079f50
PS
36bool git_odb__strict_hash_verification = true;
37
d4b5a4e2
VM
38typedef struct
39{
40 git_odb_backend *backend;
41 int priority;
a29c6b5f
VM
42 bool is_alternate;
43 ino_t disk_inode;
d4b5a4e2
VM
44} backend_internal;
45
5df18424
VM
46static git_cache *odb_cache(git_odb *odb)
47{
22a2d3d5
UG
48 git_repository *owner = GIT_REFCOUNT_OWNER(odb);
49 if (owner != NULL) {
5df18424
VM
50 return &owner->objects;
51 }
52
53 return &odb->own_cache;
54}
f5e28202 55
ac3d33df 56static int odb_otype_fast(git_object_t *type_p, git_odb *db, const git_oid *id);
85e7efa1 57static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth);
eae0bfdc 58static int error_null_oid(int error, const char *message);
85e7efa1 59
ac3d33df 60static git_object_t odb_hardcoded_type(const git_oid *id)
4416aa77 61{
e579e0f7 62 if (!git_oid_cmp(id, &git_oid__empty_tree_sha1))
ac3d33df 63 return GIT_OBJECT_TREE;
4416aa77 64
ac3d33df 65 return GIT_OBJECT_INVALID;
4416aa77
VM
66}
67
eae0bfdc 68static int odb_read_hardcoded(bool *found, git_rawobj *raw, const git_oid *id)
4416aa77 69{
ac3d33df 70 git_object_t type;
eae0bfdc
PP
71
72 *found = false;
73
ac3d33df 74 if ((type = odb_hardcoded_type(id)) == GIT_OBJECT_INVALID)
eae0bfdc 75 return 0;
4416aa77
VM
76
77 raw->type = type;
78 raw->len = 0;
79 raw->data = git__calloc(1, sizeof(uint8_t));
ac3d33df 80 GIT_ERROR_CHECK_ALLOC(raw->data);
eae0bfdc
PP
81
82 *found = true;
4416aa77
VM
83 return 0;
84}
85
eae0bfdc
PP
86int git_odb__format_object_header(
87 size_t *written,
88 char *hdr,
89 size_t hdr_size,
22a2d3d5 90 git_object_size_t obj_len,
ac3d33df 91 git_object_t obj_type)
c960d6a3 92{
c52736fa 93 const char *type_str = git_object_type2string(obj_type);
eae0bfdc
PP
94 int hdr_max = (hdr_size > INT_MAX-2) ? (INT_MAX-2) : (int)hdr_size;
95 int len;
96
ac3d33df 97 len = p_snprintf(hdr, hdr_max, "%s %"PRId64, type_str, (int64_t)obj_len);
eae0bfdc
PP
98
99 if (len < 0 || len >= hdr_max) {
ac3d33df 100 git_error_set(GIT_ERROR_OS, "object header creation failed");
eae0bfdc
PP
101 return -1;
102 }
103
104 *written = (size_t)(len + 1);
105 return 0;
c960d6a3
RJ
106}
107
18e5b854 108int git_odb__hashobj(git_oid *id, git_rawobj *obj)
c960d6a3 109{
e579e0f7 110 git_str_vec vec[2];
c85e08b1 111 char header[64];
eae0bfdc
PP
112 size_t hdrlen;
113 int error;
c960d6a3 114
c25aa7cd
PP
115 GIT_ASSERT_ARG(id);
116 GIT_ASSERT_ARG(obj);
c960d6a3 117
eae0bfdc 118 if (!git_object_typeisloose(obj->type)) {
ac3d33df 119 git_error_set(GIT_ERROR_INVALID, "invalid object type");
ae9e29fd 120 return -1;
eae0bfdc 121 }
8842c75f 122
eae0bfdc 123 if (!obj->data && obj->len != 0) {
ac3d33df 124 git_error_set(GIT_ERROR_INVALID, "invalid object");
ae9e29fd 125 return -1;
eae0bfdc 126 }
c960d6a3 127
eae0bfdc
PP
128 if ((error = git_odb__format_object_header(&hdrlen,
129 header, sizeof(header), obj->len, obj->type)) < 0)
130 return error;
c960d6a3 131
c85e08b1 132 vec[0].data = header;
87d9869f 133 vec[0].len = hdrlen;
c960d6a3 134 vec[1].data = obj->data;
87d9869f 135 vec[1].len = obj->len;
c960d6a3 136
e579e0f7 137 return git_hash_vec(id->id, vec, 2, GIT_HASH_ALGORITHM_SHA1);
c960d6a3
RJ
138}
139
d12299fe 140
78606263 141static git_odb_object *odb_object__alloc(const git_oid *oid, git_rawobj *source)
e17a3f56 142{
78606263 143 git_odb_object *object = git__calloc(1, sizeof(git_odb_object));
e17a3f56 144
78606263
RB
145 if (object != NULL) {
146 git_oid_cpy(&object->cached.oid, oid);
147 object->cached.type = source->type;
148 object->cached.size = source->len;
149 object->buffer = source->data;
150 }
e17a3f56 151
72a3fe42 152 return object;
3d3552e8
RJ
153}
154
78606263 155void git_odb_object__free(void *object)
3d3552e8 156{
72a3fe42 157 if (object != NULL) {
78606263 158 git__free(((git_odb_object *)object)->buffer);
3286c408 159 git__free(object);
72a3fe42
VM
160 }
161}
3d3552e8 162
1881f078
VM
163const git_oid *git_odb_object_id(git_odb_object *object)
164{
165 return &object->cached.oid;
166}
167
168const void *git_odb_object_data(git_odb_object *object)
169{
8842c75f 170 return object->buffer;
1881f078
VM
171}
172
173size_t git_odb_object_size(git_odb_object *object)
174{
8842c75f 175 return object->cached.size;
1881f078
VM
176}
177
ac3d33df 178git_object_t git_odb_object_type(git_odb_object *object)
1881f078 179{
8842c75f 180 return object->cached.type;
1881f078
VM
181}
182
98fec8a9
VM
183int git_odb_object_dup(git_odb_object **dest, git_odb_object *source)
184{
185 git_cached_obj_incref(source);
186 *dest = source;
187 return 0;
188}
189
45e79e37 190void git_odb_object_free(git_odb_object *object)
72a3fe42 191{
edca6c8f
MS
192 if (object == NULL)
193 return;
194
5df18424 195 git_cached_obj_decref(object);
72a3fe42 196}
3d3552e8 197
ac3d33df 198int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_object_t type)
c52736fa 199{
eae0bfdc 200 size_t hdr_len;
7dd22538 201 char hdr[64], buffer[FILEIO_BUFSIZE];
603bee07 202 git_hash_ctx ctx;
addc9be4 203 ssize_t read_len = 0;
d6fb0924 204 int error = 0;
c52736fa 205
a13fb55a 206 if (!git_object_typeisloose(type)) {
ac3d33df 207 git_error_set(GIT_ERROR_INVALID, "invalid object type for hash");
a13fb55a
RB
208 return -1;
209 }
210
e579e0f7 211 if ((error = git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1)) < 0)
eae0bfdc 212 return error;
c52736fa 213
eae0bfdc
PP
214 if ((error = git_odb__format_object_header(&hdr_len, hdr,
215 sizeof(hdr), size, type)) < 0)
216 goto done;
d6fb0924 217
603bee07 218 if ((error = git_hash_update(&ctx, hdr, hdr_len)) < 0)
d6fb0924 219 goto done;
c52736fa 220
c859184b 221 while (size > 0 && (read_len = p_read(fd, buffer, sizeof(buffer))) > 0) {
603bee07 222 if ((error = git_hash_update(&ctx, buffer, read_len)) < 0)
d6fb0924
ET
223 goto done;
224
c52736fa
VM
225 size -= read_len;
226 }
227
c859184b
VM
228 /* If p_read returned an error code, the read obviously failed.
229 * If size is not zero, the file was truncated after we originally
230 * stat'd it, so we consider this a read failure too */
231 if (read_len < 0 || size > 0) {
ac3d33df 232 git_error_set(GIT_ERROR_OS, "error reading file for hashing");
d6fb0924
ET
233 error = -1;
234
235 goto done;
c859184b
VM
236 }
237
e579e0f7 238 error = git_hash_final(out->id, &ctx);
c52736fa 239
d6fb0924 240done:
603bee07 241 git_hash_ctx_cleanup(&ctx);
d6fb0924 242 return error;
c52736fa
VM
243}
244
60b9d3fc 245int git_odb__hashfd_filtered(
ac3d33df 246 git_oid *out, git_file fd, size_t size, git_object_t type, git_filter_list *fl)
60b9d3fc
RB
247{
248 int error;
e579e0f7 249 git_str raw = GIT_STR_INIT;
60b9d3fc 250
85d54812 251 if (!fl)
60b9d3fc
RB
252 return git_odb__hashfd(out, fd, size, type);
253
254 /* size of data is used in header, so we have to read the whole file
255 * into memory to apply filters before beginning to calculate the hash
256 */
257
2a7d224f 258 if (!(error = git_futils_readbuffer_fd(&raw, fd, size))) {
e579e0f7 259 git_str post = GIT_STR_INIT;
60b9d3fc 260
c25aa7cd 261 error = git_filter_list__convert_buf(&post, fl, &raw);
60b9d3fc 262
2a7d224f
RB
263 if (!error)
264 error = git_odb_hash(out, post.ptr, post.size, type);
265
e579e0f7 266 git_str_dispose(&post);
2a7d224f 267 }
60b9d3fc
RB
268
269 return error;
270}
271
f19e3ca2
VM
272int git_odb__hashlink(git_oid *out, const char *path)
273{
274 struct stat st;
f1453c59 275 int size;
ae9e29fd 276 int result;
f19e3ca2 277
e579e0f7 278 if (git_fs_path_lstat(path, &st) < 0)
ae9e29fd 279 return -1;
f19e3ca2 280
f1453c59 281 if (!git__is_int(st.st_size) || (int)st.st_size < 0) {
ac3d33df 282 git_error_set(GIT_ERROR_FILESYSTEM, "file size overflow for 32-bit systems");
ae9e29fd
RB
283 return -1;
284 }
f19e3ca2 285
f1453c59 286 size = (int)st.st_size;
15d54fdd 287
f19e3ca2
VM
288 if (S_ISLNK(st.st_mode)) {
289 char *link_data;
f1453c59
ET
290 int read_len;
291 size_t alloc_size;
f19e3ca2 292
ac3d33df 293 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_size, size, 1);
f1453c59 294 link_data = git__malloc(alloc_size);
ac3d33df 295 GIT_ERROR_CHECK_ALLOC(link_data);
f19e3ca2 296
15d54fdd 297 read_len = p_readlink(path, link_data, size);
c25aa7cd 298 if (read_len == -1) {
ac3d33df 299 git_error_set(GIT_ERROR_OS, "failed to read symlink data for '%s'", path);
c6451624 300 git__free(link_data);
ae9e29fd
RB
301 return -1;
302 }
c25aa7cd
PP
303 GIT_ASSERT(read_len <= size);
304 link_data[read_len] = '\0';
f19e3ca2 305
c25aa7cd 306 result = git_odb_hash(out, link_data, read_len, GIT_OBJECT_BLOB);
2bc8fa02 307 git__free(link_data);
60b9d3fc 308 } else {
ae9e29fd
RB
309 int fd = git_futils_open_ro(path);
310 if (fd < 0)
311 return -1;
ac3d33df 312 result = git_odb__hashfd(out, fd, size, GIT_OBJECT_BLOB);
f19e3ca2
VM
313 p_close(fd);
314 }
315
ae9e29fd 316 return result;
f19e3ca2
VM
317}
318
ac3d33df 319int git_odb_hashfile(git_oid *out, const char *path, git_object_t type)
18e5b854 320{
22a2d3d5
UG
321 uint64_t size;
322 int fd, error = 0;
323
324 if ((fd = git_futils_open_ro(path)) < 0)
e1de726c 325 return fd;
18e5b854 326
22a2d3d5
UG
327 if ((error = git_futils_filesize(&size, fd)) < 0)
328 goto done;
329
330 if (!git__is_sizet(size)) {
ac3d33df 331 git_error_set(GIT_ERROR_OS, "file size overflow for 32-bit systems");
22a2d3d5
UG
332 error = -1;
333 goto done;
18e5b854
VM
334 }
335
22a2d3d5
UG
336 error = git_odb__hashfd(out, fd, (size_t)size, type);
337
338done:
18e5b854 339 p_close(fd);
22a2d3d5 340 return error;
18e5b854
VM
341}
342
ac3d33df 343int git_odb_hash(git_oid *id, const void *data, size_t len, git_object_t type)
72a3fe42 344{
72a3fe42 345 git_rawobj raw;
3d3552e8 346
c25aa7cd 347 GIT_ASSERT_ARG(id);
3d3552e8 348
72a3fe42
VM
349 raw.data = (void *)data;
350 raw.len = len;
351 raw.type = type;
3d3552e8 352
18e5b854 353 return git_odb__hashobj(id, &raw);
3d3552e8
RJ
354}
355
d69d0185
VM
356/**
357 * FAKE WSTREAM
358 */
359
360typedef struct {
361 git_odb_stream stream;
362 char *buffer;
363 size_t size, written;
ac3d33df 364 git_object_t type;
d69d0185
VM
365} fake_wstream;
366
fe0c6d4e 367static int fake_wstream__fwrite(git_odb_stream *_stream, const git_oid *oid)
d69d0185
VM
368{
369 fake_wstream *stream = (fake_wstream *)_stream;
fe0c6d4e 370 return _stream->backend->write(_stream->backend, oid, stream->buffer, stream->size, stream->type);
d69d0185
VM
371}
372
373static int fake_wstream__write(git_odb_stream *_stream, const char *data, size_t len)
374{
375 fake_wstream *stream = (fake_wstream *)_stream;
376
c25aa7cd 377 GIT_ASSERT(stream->written + len <= stream->size);
d69d0185
VM
378
379 memcpy(stream->buffer + stream->written, data, len);
380 stream->written += len;
ae9e29fd 381 return 0;
d69d0185
VM
382}
383
384static void fake_wstream__free(git_odb_stream *_stream)
385{
386 fake_wstream *stream = (fake_wstream *)_stream;
387
3286c408
VM
388 git__free(stream->buffer);
389 git__free(stream);
d69d0185
VM
390}
391
22a2d3d5 392static int init_fake_wstream(git_odb_stream **stream_p, git_odb_backend *backend, git_object_size_t size, git_object_t type)
d69d0185
VM
393{
394 fake_wstream *stream;
ac3d33df 395 size_t blobsize;
d69d0185 396
ac3d33df
JK
397 GIT_ERROR_CHECK_BLOBSIZE(size);
398 blobsize = (size_t)size;
77b339f7 399
d69d0185 400 stream = git__calloc(1, sizeof(fake_wstream));
ac3d33df 401 GIT_ERROR_CHECK_ALLOC(stream);
d69d0185 402
ac3d33df 403 stream->size = blobsize;
d69d0185 404 stream->type = type;
ac3d33df 405 stream->buffer = git__malloc(blobsize);
d69d0185 406 if (stream->buffer == NULL) {
3286c408 407 git__free(stream);
ae9e29fd 408 return -1;
d69d0185
VM
409 }
410
411 stream->stream.backend = backend;
412 stream->stream.read = NULL; /* read only */
413 stream->stream.write = &fake_wstream__write;
414 stream->stream.finalize_write = &fake_wstream__fwrite;
415 stream->stream.free = &fake_wstream__free;
416 stream->stream.mode = GIT_STREAM_WRONLY;
417
418 *stream_p = (git_odb_stream *)stream;
ae9e29fd 419 return 0;
d69d0185 420}
3d3552e8 421
7d7cd885
VM
422/***********************************************************
423 *
424 * OBJECT DATABASE PUBLIC API
425 *
426 * Public calls for the ODB functionality
427 *
428 ***********************************************************/
3d3552e8 429
39e1032c 430static int backend_sort_cmp(const void *a, const void *b)
7d7cd885 431{
de18f276
VM
432 const backend_internal *backend_a = (const backend_internal *)(a);
433 const backend_internal *backend_b = (const backend_internal *)(b);
d4b5a4e2 434
a0a1b19a
VM
435 if (backend_b->priority == backend_a->priority) {
436 if (backend_a->is_alternate)
437 return -1;
438 if (backend_b->is_alternate)
439 return 1;
440 return 0;
441 }
442 return (backend_b->priority - backend_a->priority);
3d3552e8
RJ
443}
444
7d7cd885 445int git_odb_new(git_odb **out)
3d3552e8 446{
7d7cd885 447 git_odb *db = git__calloc(1, sizeof(*db));
ac3d33df 448 GIT_ERROR_CHECK_ALLOC(db);
3d3552e8 449
c25aa7cd
PP
450 if (git_mutex_init(&db->lock) < 0) {
451 git__free(db);
452 return -1;
453 }
6147f643 454 if (git_cache_init(&db->own_cache) < 0) {
c25aa7cd 455 git_mutex_free(&db->lock);
6147f643
PP
456 git__free(db);
457 return -1;
458 }
459 if (git_vector_init(&db->backends, 4, backend_sort_cmp) < 0) {
22a2d3d5 460 git_cache_dispose(&db->own_cache);
c25aa7cd 461 git_mutex_free(&db->lock);
3286c408 462 git__free(db);
ae9e29fd 463 return -1;
7d7cd885 464 }
3d3552e8 465
7d7cd885 466 *out = db;
9462c471 467 GIT_REFCOUNT_INC(db);
ae9e29fd 468 return 0;
3d3552e8
RJ
469}
470
a29c6b5f
VM
471static int add_backend_internal(
472 git_odb *odb, git_odb_backend *backend,
473 int priority, bool is_alternate, ino_t disk_inode)
e17a3f56 474{
d4b5a4e2
VM
475 backend_internal *internal;
476
c25aa7cd
PP
477 GIT_ASSERT_ARG(odb);
478 GIT_ASSERT_ARG(backend);
e17a3f56 479
ac3d33df 480 GIT_ERROR_CHECK_VERSION(backend, GIT_ODB_BACKEND_VERSION, "git_odb_backend");
55f6f21b 481
998f7b3d 482 /* Check if the backend is already owned by another ODB */
c25aa7cd 483 GIT_ASSERT(!backend->odb || backend->odb == odb);
e17a3f56 484
d4b5a4e2 485 internal = git__malloc(sizeof(backend_internal));
ac3d33df 486 GIT_ERROR_CHECK_ALLOC(internal);
d4b5a4e2
VM
487
488 internal->backend = backend;
489 internal->priority = priority;
490 internal->is_alternate = is_alternate;
a29c6b5f 491 internal->disk_inode = disk_inode;
e17a3f56 492
c25aa7cd
PP
493 if (git_mutex_lock(&odb->lock) < 0) {
494 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
495 return -1;
496 }
d4b5a4e2 497 if (git_vector_insert(&odb->backends, internal) < 0) {
c25aa7cd 498 git_mutex_unlock(&odb->lock);
3286c408 499 git__free(internal);
ae9e29fd 500 return -1;
d4b5a4e2 501 }
7d7cd885 502 git_vector_sort(&odb->backends);
d4b5a4e2 503 internal->backend->odb = odb;
c25aa7cd 504 git_mutex_unlock(&odb->lock);
ae9e29fd 505 return 0;
e17a3f56
RJ
506}
507
d4b5a4e2
VM
508int git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority)
509{
a29c6b5f 510 return add_backend_internal(odb, backend, priority, false, 0);
d4b5a4e2
VM
511}
512
513int git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority)
514{
a29c6b5f 515 return add_backend_internal(odb, backend, priority, true, 0);
d4b5a4e2
VM
516}
517
83cc70d9
RB
518size_t git_odb_num_backends(git_odb *odb)
519{
c25aa7cd
PP
520 size_t length;
521 bool locked = true;
522
523 GIT_ASSERT_ARG(odb);
524
525 if (git_mutex_lock(&odb->lock) < 0) {
526 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
527 locked = false;
528 }
529 length = odb->backends.length;
530 if (locked)
531 git_mutex_unlock(&odb->lock);
532 return length;
83cc70d9
RB
533}
534
f063f578
RB
535static int git_odb__error_unsupported_in_backend(const char *action)
536{
ac3d33df 537 git_error_set(GIT_ERROR_ODB,
909d5494 538 "cannot %s - unsupported in the loaded odb backends", action);
f063f578
RB
539 return -1;
540}
541
542
83cc70d9
RB
543int git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t pos)
544{
545 backend_internal *internal;
c25aa7cd 546 int error;
83cc70d9 547
c25aa7cd
PP
548 GIT_ASSERT_ARG(out);
549 GIT_ASSERT_ARG(odb);
550
551
552 if ((error = git_mutex_lock(&odb->lock)) < 0) {
553 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
554 return error;
555 }
83cc70d9
RB
556 internal = git_vector_get(&odb->backends, pos);
557
c25aa7cd
PP
558 if (!internal || !internal->backend) {
559 git_mutex_unlock(&odb->lock);
560
561 git_error_set(GIT_ERROR_ODB, "no ODB backend loaded at index %" PRIuZ, pos);
562 return GIT_ENOTFOUND;
83cc70d9 563 }
c25aa7cd
PP
564 *out = internal->backend;
565 git_mutex_unlock(&odb->lock);
83cc70d9 566
c25aa7cd 567 return 0;
83cc70d9
RB
568}
569
1c04a96b 570int git_odb__add_default_backends(
a29c6b5f
VM
571 git_odb *db, const char *objects_dir,
572 bool as_alternates, int alternate_depth)
5a800efc 573{
c25aa7cd 574 size_t i = 0;
a29c6b5f 575 struct stat st;
c8a4e8a5 576 ino_t inode;
5a800efc 577 git_odb_backend *loose, *packed;
5a800efc 578
4ef2c79c
VM
579 /* TODO: inodes are not really relevant on Win32, so we need to find
580 * a cross-platform workaround for this */
c8a4e8a5
ET
581#ifdef GIT_WIN32
582 GIT_UNUSED(i);
c25aa7cd 583 GIT_UNUSED(&st);
c8a4e8a5
ET
584
585 inode = 0;
586#else
a29c6b5f 587 if (p_stat(objects_dir, &st) < 0) {
dfec726b 588 if (as_alternates)
22a2d3d5 589 /* this should warn */
dfec726b
VM
590 return 0;
591
ac3d33df 592 git_error_set(GIT_ERROR_ODB, "failed to load object database in '%s'", objects_dir);
a29c6b5f
VM
593 return -1;
594 }
595
c8a4e8a5
ET
596 inode = st.st_ino;
597
c25aa7cd
PP
598 if (git_mutex_lock(&db->lock) < 0) {
599 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
600 return -1;
601 }
a29c6b5f
VM
602 for (i = 0; i < db->backends.length; ++i) {
603 backend_internal *backend = git_vector_get(&db->backends, i);
c25aa7cd
PP
604 if (backend->disk_inode == inode) {
605 git_mutex_unlock(&db->lock);
a29c6b5f 606 return 0;
c25aa7cd 607 }
a29c6b5f 608 }
c25aa7cd 609 git_mutex_unlock(&db->lock);
4ef2c79c 610#endif
f063f578 611
5a800efc 612 /* add the loose object backend */
1c04a96b 613 if (git_odb_backend_loose(&loose, objects_dir, -1, db->do_fsync, 0, 0) < 0 ||
c25aa7cd 614 add_backend_internal(db, loose, git_odb__loose_priority, as_alternates, inode) < 0)
ae9e29fd 615 return -1;
5a800efc
VM
616
617 /* add the packed file backend */
ae9e29fd 618 if (git_odb_backend_pack(&packed, objects_dir) < 0 ||
c25aa7cd
PP
619 add_backend_internal(db, packed, git_odb__packed_priority, as_alternates, inode) < 0)
620 return -1;
621
622 if (git_mutex_lock(&db->lock) < 0) {
623 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
624 return -1;
625 }
626 if (!db->cgraph && git_commit_graph_new(&db->cgraph, objects_dir, false) < 0) {
627 git_mutex_unlock(&db->lock);
ae9e29fd 628 return -1;
c25aa7cd
PP
629 }
630 git_mutex_unlock(&db->lock);
5a800efc 631
85e7efa1 632 return load_alternates(db, objects_dir, alternate_depth);
5a800efc
VM
633}
634
85e7efa1 635static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth)
5a800efc 636{
e579e0f7
MB
637 git_str alternates_path = GIT_STR_INIT;
638 git_str alternates_buf = GIT_STR_INIT;
97769280 639 char *buffer;
97769280 640 const char *alternate;
ae9e29fd 641 int result = 0;
5a800efc 642
85e7efa1 643 /* Git reports an error, we just ignore anything deeper */
f063f578 644 if (alternate_depth > GIT_ALTERNATES_MAX_DEPTH)
85e7efa1 645 return 0;
85e7efa1 646
e579e0f7 647 if (git_str_joinpath(&alternates_path, objects_dir, GIT_ALTERNATES_FILE) < 0)
ae9e29fd 648 return -1;
5a800efc 649
e579e0f7
MB
650 if (git_fs_path_exists(alternates_path.ptr) == false) {
651 git_str_dispose(&alternates_path);
ae9e29fd 652 return 0;
97769280 653 }
5a800efc 654
ae9e29fd 655 if (git_futils_readbuffer(&alternates_buf, alternates_path.ptr) < 0) {
e579e0f7 656 git_str_dispose(&alternates_path);
ae9e29fd 657 return -1;
97769280 658 }
5a800efc 659
13224ea4 660 buffer = (char *)alternates_buf.ptr;
5a800efc
VM
661
662 /* add each alternate as a new backend; one alternate per line */
0291b5b7 663 while ((alternate = git__strtok(&buffer, "\r\n")) != NULL) {
0291b5b7
VM
664 if (*alternate == '\0' || *alternate == '#')
665 continue;
666
85e7efa1
CMN
667 /*
668 * Relative path: build based on the current `objects`
669 * folder. However, relative paths are only allowed in
670 * the current repository.
671 */
672 if (*alternate == '.' && !alternate_depth) {
e579e0f7 673 if ((result = git_str_joinpath(&alternates_path, objects_dir, alternate)) < 0)
97769280 674 break;
e579e0f7 675 alternate = git_str_cstr(&alternates_path);
0291b5b7
VM
676 }
677
1c04a96b 678 if ((result = git_odb__add_default_backends(odb, alternate, true, alternate_depth + 1)) < 0)
0291b5b7
VM
679 break;
680 }
5a800efc 681
e579e0f7
MB
682 git_str_dispose(&alternates_path);
683 git_str_dispose(&alternates_buf);
13224ea4 684
ae9e29fd 685 return result;
5a800efc 686}
e17a3f56 687
9507a434
VM
688int git_odb_add_disk_alternate(git_odb *odb, const char *path)
689{
1c04a96b 690 return git_odb__add_default_backends(odb, path, true, 0);
9507a434
VM
691}
692
c25aa7cd
PP
693int git_odb_set_commit_graph(git_odb *odb, git_commit_graph *cgraph)
694{
695 int error = 0;
696
697 GIT_ASSERT_ARG(odb);
698
699 if ((error = git_mutex_lock(&odb->lock)) < 0) {
700 git_error_set(GIT_ERROR_ODB, "failed to acquire the db lock");
701 return error;
702 }
703 git_commit_graph_free(odb->cgraph);
704 odb->cgraph = cgraph;
705 git_mutex_unlock(&odb->lock);
706
707 return error;
708}
709
7d7cd885 710int git_odb_open(git_odb **out, const char *objects_dir)
e17a3f56 711{
7d7cd885 712 git_odb *db;
e17a3f56 713
c25aa7cd
PP
714 GIT_ASSERT_ARG(out);
715 GIT_ASSERT_ARG(objects_dir);
5a800efc
VM
716
717 *out = NULL;
718
ae9e29fd
RB
719 if (git_odb_new(&db) < 0)
720 return -1;
e17a3f56 721
1c04a96b 722 if (git_odb__add_default_backends(db, objects_dir, 0, 0) < 0) {
ae9e29fd
RB
723 git_odb_free(db);
724 return -1;
725 }
e17a3f56 726
7d7cd885 727 *out = db;
ae9e29fd 728 return 0;
7d7cd885 729}
e17a3f56 730
1c04a96b
ET
731int git_odb__set_caps(git_odb *odb, int caps)
732{
733 if (caps == GIT_ODB_CAP_FROM_OWNER) {
22a2d3d5 734 git_repository *repo = GIT_REFCOUNT_OWNER(odb);
1c04a96b
ET
735 int val;
736
737 if (!repo) {
ac3d33df 738 git_error_set(GIT_ERROR_ODB, "cannot access repository to set odb caps");
1c04a96b
ET
739 return -1;
740 }
741
22a2d3d5 742 if (!git_repository__configmap_lookup(&val, repo, GIT_CONFIGMAP_FSYNCOBJECTFILES))
1c04a96b
ET
743 odb->do_fsync = !!val;
744 }
745
746 return 0;
747}
748
9462c471 749static void odb_free(git_odb *db)
a7c60cfc 750{
10c06114 751 size_t i;
c25aa7cd 752 bool locked = true;
a7c60cfc 753
c25aa7cd
PP
754 if (git_mutex_lock(&db->lock) < 0) {
755 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
756 locked = false;
757 }
7d7cd885 758 for (i = 0; i < db->backends.length; ++i) {
d4b5a4e2
VM
759 backend_internal *internal = git_vector_get(&db->backends, i);
760 git_odb_backend *backend = internal->backend;
a7c60cfc 761
d3b29fb9 762 backend->free(backend);
d4b5a4e2 763
3286c408 764 git__free(internal);
a7c60cfc 765 }
c25aa7cd
PP
766 if (locked)
767 git_mutex_unlock(&db->lock);
a7c60cfc 768
c25aa7cd 769 git_commit_graph_free(db->cgraph);
7d7cd885 770 git_vector_free(&db->backends);
22a2d3d5 771 git_cache_dispose(&db->own_cache);
c25aa7cd 772 git_mutex_free(&db->lock);
f658dc43 773
6de9b2ee 774 git__memzero(db, sizeof(*db));
3286c408 775 git__free(db);
608d33fa
RJ
776}
777
9462c471
VM
778void git_odb_free(git_odb *db)
779{
780 if (db == NULL)
781 return;
782
783 GIT_REFCOUNT_DEC(db, odb_free);
784}
785
8f09a98e
ET
786static int odb_exists_1(
787 git_odb *db,
788 const git_oid *id,
789 bool only_refreshed)
608d33fa 790{
10c06114 791 size_t i;
ae9e29fd 792 bool found = false;
c25aa7cd 793 int error;
608d33fa 794
c25aa7cd
PP
795 if ((error = git_mutex_lock(&db->lock)) < 0) {
796 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
797 return error;
798 }
7d7cd885 799 for (i = 0; i < db->backends.length && !found; ++i) {
d4b5a4e2
VM
800 backend_internal *internal = git_vector_get(&db->backends, i);
801 git_odb_backend *b = internal->backend;
a7c60cfc 802
43820f20
VM
803 if (only_refreshed && !b->refresh)
804 continue;
805
b1a6c316 806 if (b->exists != NULL)
66566516 807 found = (bool)b->exists(b, id);
608d33fa 808 }
c25aa7cd 809 git_mutex_unlock(&db->lock);
608d33fa 810
ae9e29fd 811 return (int)found;
2cdc4544
RJ
812}
813
c25aa7cd
PP
814int git_odb__get_commit_graph_file(git_commit_graph_file **out, git_odb *db)
815{
816 int error = 0;
817 git_commit_graph_file *result = NULL;
818
819 if ((error = git_mutex_lock(&db->lock)) < 0) {
820 git_error_set(GIT_ERROR_ODB, "failed to acquire the db lock");
821 return error;
822 }
823 if (!db->cgraph) {
824 error = GIT_ENOTFOUND;
825 goto done;
826 }
827 error = git_commit_graph_get_file(&result, db->cgraph);
828 if (error)
829 goto done;
830 *out = result;
831
832done:
833 git_mutex_unlock(&db->lock);
834 return error;
835}
836
8f09a98e
ET
837static int odb_freshen_1(
838 git_odb *db,
839 const git_oid *id,
840 bool only_refreshed)
841{
842 size_t i;
843 bool found = false;
c25aa7cd 844 int error;
8f09a98e 845
c25aa7cd
PP
846 if ((error = git_mutex_lock(&db->lock)) < 0) {
847 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
848 return error;
849 }
8f09a98e
ET
850 for (i = 0; i < db->backends.length && !found; ++i) {
851 backend_internal *internal = git_vector_get(&db->backends, i);
852 git_odb_backend *b = internal->backend;
853
854 if (only_refreshed && !b->refresh)
855 continue;
856
857 if (b->freshen != NULL)
858 found = !b->freshen(b, id);
859 else if (b->exists != NULL)
860 found = b->exists(b, id);
861 }
c25aa7cd 862 git_mutex_unlock(&db->lock);
8f09a98e
ET
863
864 return (int)found;
865}
866
52d03f37 867int git_odb__freshen(git_odb *db, const git_oid *id)
8f09a98e 868{
c25aa7cd
PP
869 GIT_ASSERT_ARG(db);
870 GIT_ASSERT_ARG(id);
8f09a98e
ET
871
872 if (odb_freshen_1(db, id, false))
873 return 1;
874
875 if (!git_odb_refresh(db))
876 return odb_freshen_1(db, id, true);
877
878 /* Failed to refresh, hence not found */
879 return 0;
880}
881
43820f20 882int git_odb_exists(git_odb *db, const git_oid *id)
e579e0f7
MB
883{
884 return git_odb_exists_ext(db, id, 0);
885}
886
887int git_odb_exists_ext(git_odb *db, const git_oid *id, unsigned int flags)
f5753999 888{
43820f20 889 git_odb_object *object;
f5753999 890
c25aa7cd
PP
891 GIT_ASSERT_ARG(db);
892 GIT_ASSERT_ARG(id);
f5753999 893
22a2d3d5 894 if (git_oid_is_zero(id))
eae0bfdc
PP
895 return 0;
896
43820f20
VM
897 if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
898 git_odb_object_free(object);
6c04269c 899 return 1;
f5753999
RB
900 }
901
43820f20
VM
902 if (odb_exists_1(db, id, false))
903 return 1;
904
e579e0f7 905 if (!(flags & GIT_ODB_LOOKUP_NO_REFRESH) && !git_odb_refresh(db))
43820f20
VM
906 return odb_exists_1(db, id, true);
907
908 /* Failed to refresh, hence not found */
909 return 0;
910}
911
912static int odb_exists_prefix_1(git_oid *out, git_odb *db,
913 const git_oid *key, size_t len, bool only_refreshed)
914{
915 size_t i;
916 int error = GIT_ENOTFOUND, num_found = 0;
917 git_oid last_found = {{0}}, found;
89499078 918
c25aa7cd
PP
919 if ((error = git_mutex_lock(&db->lock)) < 0) {
920 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
921 return error;
922 }
923 error = GIT_ENOTFOUND;
f5753999
RB
924 for (i = 0; i < db->backends.length; ++i) {
925 backend_internal *internal = git_vector_get(&db->backends, i);
926 git_odb_backend *b = internal->backend;
927
43820f20
VM
928 if (only_refreshed && !b->refresh)
929 continue;
930
f5753999
RB
931 if (!b->exists_prefix)
932 continue;
933
43820f20 934 error = b->exists_prefix(&found, b, key, len);
f5753999
RB
935 if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH)
936 continue;
c25aa7cd
PP
937 if (error) {
938 git_mutex_unlock(&db->lock);
f5753999 939 return error;
c25aa7cd 940 }
f5753999
RB
941
942 /* make sure found item doesn't introduce ambiguity */
943 if (num_found) {
c25aa7cd
PP
944 if (git_oid__cmp(&last_found, &found)) {
945 git_mutex_unlock(&db->lock);
f5753999 946 return git_odb__error_ambiguous("multiple matches for prefix");
c25aa7cd 947 }
f5753999
RB
948 } else {
949 git_oid_cpy(&last_found, &found);
950 num_found++;
951 }
952 }
c25aa7cd 953 git_mutex_unlock(&db->lock);
f5753999
RB
954
955 if (!num_found)
43820f20
VM
956 return GIT_ENOTFOUND;
957
f5753999
RB
958 if (out)
959 git_oid_cpy(out, &last_found);
960
89499078 961 return 0;
f5753999
RB
962}
963
43820f20
VM
964int git_odb_exists_prefix(
965 git_oid *out, git_odb *db, const git_oid *short_id, size_t len)
966{
967 int error;
eae0bfdc 968 git_oid key = {{0}};
43820f20 969
c25aa7cd
PP
970 GIT_ASSERT_ARG(db);
971 GIT_ASSERT_ARG(short_id);
43820f20
VM
972
973 if (len < GIT_OID_MINPREFIXLEN)
974 return git_odb__error_ambiguous("prefix length too short");
43820f20 975
6c04269c 976 if (len >= GIT_OID_HEXSZ) {
43820f20
VM
977 if (git_odb_exists(db, short_id)) {
978 if (out)
979 git_oid_cpy(out, short_id);
980 return 0;
981 } else {
e10144ae
ET
982 return git_odb__error_notfound(
983 "no match for id prefix", short_id, len);
43820f20
VM
984 }
985 }
986
6c04269c 987 git_oid__cpy_prefix(&key, short_id, len);
43820f20
VM
988
989 error = odb_exists_prefix_1(out, db, &key, len, false);
990
991 if (error == GIT_ENOTFOUND && !git_odb_refresh(db))
992 error = odb_exists_prefix_1(out, db, &key, len, true);
993
994 if (error == GIT_ENOTFOUND)
e10144ae 995 return git_odb__error_notfound("no match for id prefix", &key, len);
43820f20
VM
996
997 return error;
998}
999
4b1f0f79 1000int git_odb_expand_ids(
6c04269c 1001 git_odb *db,
62484f52
ET
1002 git_odb_expand_id *ids,
1003 size_t count)
6c04269c 1004{
4416aa77 1005 size_t i;
6c04269c 1006
c25aa7cd
PP
1007 GIT_ASSERT_ARG(db);
1008 GIT_ASSERT_ARG(ids);
6c04269c 1009
62484f52
ET
1010 for (i = 0; i < count; i++) {
1011 git_odb_expand_id *query = &ids[i];
9a786650 1012 int error = GIT_EAMBIGUOUS;
6c04269c 1013
e78d2ac9 1014 if (!query->type)
ac3d33df 1015 query->type = GIT_OBJECT_ANY;
e78d2ac9
VM
1016
1017 /* if we have a short OID, expand it first */
1018 if (query->length >= GIT_OID_MINPREFIXLEN && query->length < GIT_OID_HEXSZ) {
1019 git_oid actual_id;
1020
1021 error = odb_exists_prefix_1(&actual_id, db, &query->id, query->length, false);
1022 if (!error) {
1023 git_oid_cpy(&query->id, &actual_id);
1024 query->length = GIT_OID_HEXSZ;
1025 }
6c04269c
ET
1026 }
1027
9a786650 1028 /*
e78d2ac9
VM
1029 * now we ought to have a 40-char OID, either because we've expanded it
1030 * or because the user passed a full OID. Ensure its type is right.
6c04269c 1031 */
e78d2ac9 1032 if (query->length >= GIT_OID_HEXSZ) {
ac3d33df 1033 git_object_t actual_type;
6c04269c 1034
e78d2ac9
VM
1035 error = odb_otype_fast(&actual_type, db, &query->id);
1036 if (!error) {
ac3d33df 1037 if (query->type != GIT_OBJECT_ANY && query->type != actual_type)
e78d2ac9
VM
1038 error = GIT_ENOTFOUND;
1039 else
1040 query->type = actual_type;
1041 }
1042 }
4b1f0f79 1043
9a786650 1044 switch (error) {
e78d2ac9 1045 /* no errors, so we've successfully expanded the OID */
9a786650 1046 case 0:
e78d2ac9 1047 continue;
9a786650
VM
1048
1049 /* the object is missing or ambiguous */
1050 case GIT_ENOTFOUND:
1051 case GIT_EAMBIGUOUS:
62484f52
ET
1052 memset(&query->id, 0, sizeof(git_oid));
1053 query->length = 0;
1054 query->type = 0;
9a786650
VM
1055 break;
1056
1057 /* something went very wrong with the ODB; bail hard */
1058 default:
1059 return error;
6c04269c
ET
1060 }
1061 }
1062
ac3d33df 1063 git_error_clear();
9a786650 1064 return 0;
6c04269c
ET
1065}
1066
ac3d33df 1067int git_odb_read_header(size_t *len_p, git_object_t *type_p, git_odb *db, const git_oid *id)
c6ac28fd
RB
1068{
1069 int error;
1070 git_odb_object *object;
1071
1072 error = git_odb__read_header_or_object(&object, len_p, type_p, db, id);
1073
1074 if (object)
1075 git_odb_object_free(object);
1076
1077 return error;
1078}
1079
4416aa77 1080static int odb_read_header_1(
ac3d33df 1081 size_t *len_p, git_object_t *type_p, git_odb *db,
4416aa77
VM
1082 const git_oid *id, bool only_refreshed)
1083{
1084 size_t i;
ac3d33df 1085 git_object_t ht;
1bbcb2b2
VM
1086 bool passthrough = false;
1087 int error;
4416aa77 1088
ac3d33df 1089 if (!only_refreshed && (ht = odb_hardcoded_type(id)) != GIT_OBJECT_INVALID) {
4416aa77
VM
1090 *type_p = ht;
1091 *len_p = 0;
1092 return 0;
1093 }
1094
c25aa7cd
PP
1095 if ((error = git_mutex_lock(&db->lock)) < 0) {
1096 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
1097 return error;
1098 }
1bbcb2b2 1099 for (i = 0; i < db->backends.length; ++i) {
4416aa77
VM
1100 backend_internal *internal = git_vector_get(&db->backends, i);
1101 git_odb_backend *b = internal->backend;
1102
1103 if (only_refreshed && !b->refresh)
1104 continue;
1105
1bbcb2b2
VM
1106 if (!b->read_header) {
1107 passthrough = true;
1108 continue;
1109 }
1110
1111 error = b->read_header(len_p, type_p, b, id);
1112
1113 switch (error) {
1114 case GIT_PASSTHROUGH:
1115 passthrough = true;
1116 break;
1117 case GIT_ENOTFOUND:
1118 break;
1119 default:
c25aa7cd 1120 git_mutex_unlock(&db->lock);
1bbcb2b2
VM
1121 return error;
1122 }
4416aa77 1123 }
c25aa7cd 1124 git_mutex_unlock(&db->lock);
4416aa77 1125
1bbcb2b2 1126 return passthrough ? GIT_PASSTHROUGH : GIT_ENOTFOUND;
4416aa77
VM
1127}
1128
c6ac28fd 1129int git_odb__read_header_or_object(
ac3d33df 1130 git_odb_object **out, size_t *len_p, git_object_t *type_p,
c6ac28fd 1131 git_odb *db, const git_oid *id)
a7c60cfc 1132{
904b67e6 1133 int error = GIT_ENOTFOUND;
72a3fe42 1134 git_odb_object *object;
a7c60cfc 1135
c25aa7cd
PP
1136 GIT_ASSERT_ARG(db);
1137 GIT_ASSERT_ARG(id);
1138 GIT_ASSERT_ARG(out);
1139 GIT_ASSERT_ARG(len_p);
1140 GIT_ASSERT_ARG(type_p);
72a3fe42 1141
eae0bfdc
PP
1142 *out = NULL;
1143
22a2d3d5 1144 if (git_oid_is_zero(id))
eae0bfdc
PP
1145 return error_null_oid(GIT_ENOTFOUND, "cannot read object");
1146
5df18424 1147 if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
8842c75f
VM
1148 *len_p = object->cached.size;
1149 *type_p = object->cached.type;
c6ac28fd 1150 *out = object;
ae9e29fd 1151 return 0;
72a3fe42 1152 }
608d33fa 1153
4416aa77 1154 error = odb_read_header_1(len_p, type_p, db, id, false);
c6ac28fd 1155
4416aa77
VM
1156 if (error == GIT_ENOTFOUND && !git_odb_refresh(db))
1157 error = odb_read_header_1(len_p, type_p, db, id, true);
608d33fa 1158
4416aa77
VM
1159 if (error == GIT_ENOTFOUND)
1160 return git_odb__error_notfound("cannot read header for", id, GIT_OID_HEXSZ);
608d33fa 1161
4416aa77
VM
1162 /* we found the header; return early */
1163 if (!error)
ae9e29fd 1164 return 0;
984ed6b6 1165
4416aa77
VM
1166 if (error == GIT_PASSTHROUGH) {
1167 /*
1168 * no backend has header-reading functionality
1169 * so try using `git_odb_read` instead
1170 */
1171 error = git_odb_read(&object, db, id);
1172 if (!error) {
1173 *len_p = object->cached.size;
1174 *type_p = object->cached.type;
1175 *out = object;
1176 }
e1ac0101 1177 }
4416aa77
VM
1178
1179 return error;
e1ac0101
CMN
1180}
1181
43820f20
VM
1182static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
1183 bool only_refreshed)
a7c60cfc 1184{
43820f20 1185 size_t i;
72a3fe42 1186 git_rawobj raw;
78606263 1187 git_odb_object *object;
28a0741f 1188 git_oid hashed;
43820f20 1189 bool found = false;
7776db51 1190 int error = 0;
a7c60cfc 1191
eae0bfdc
PP
1192 if (!only_refreshed) {
1193 if ((error = odb_read_hardcoded(&found, &raw, id)) < 0)
1194 return error;
1195 }
4a863c06 1196
c25aa7cd
PP
1197 if ((error = git_mutex_lock(&db->lock)) < 0) {
1198 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
1199 return error;
1200 }
43820f20 1201 for (i = 0; i < db->backends.length && !found; ++i) {
d4b5a4e2
VM
1202 backend_internal *internal = git_vector_get(&db->backends, i);
1203 git_odb_backend *b = internal->backend;
7d7cd885 1204
43820f20
VM
1205 if (only_refreshed && !b->refresh)
1206 continue;
1207
b1a6c316 1208 if (b->read != NULL) {
28a0741f 1209 error = b->read(&raw.data, &raw.len, &raw.type, b, id);
43820f20
VM
1210 if (error == GIT_PASSTHROUGH || error == GIT_ENOTFOUND)
1211 continue;
1212
c25aa7cd
PP
1213 if (error < 0) {
1214 git_mutex_unlock(&db->lock);
43820f20 1215 return error;
c25aa7cd 1216 }
43820f20
VM
1217
1218 found = true;
f063f578 1219 }
72a3fe42 1220 }
c25aa7cd 1221 git_mutex_unlock(&db->lock);
72a3fe42 1222
43820f20
VM
1223 if (!found)
1224 return GIT_ENOTFOUND;
7d7cd885 1225
35079f50
PS
1226 if (git_odb__strict_hash_verification) {
1227 if ((error = git_odb_hash(&hashed, raw.data, raw.len, raw.type)) < 0)
1228 goto out;
28a0741f 1229
35079f50
PS
1230 if (!git_oid_equal(id, &hashed)) {
1231 error = git_odb__error_mismatch(id, &hashed);
1232 goto out;
1233 }
28a0741f
PS
1234 }
1235
ac3d33df 1236 git_error_clear();
eae0bfdc
PP
1237 if ((object = odb_object__alloc(id, &raw)) == NULL) {
1238 error = -1;
28a0741f 1239 goto out;
eae0bfdc 1240 }
78606263
RB
1241
1242 *out = git_cache_store_raw(odb_cache(db), object);
28a0741f
PS
1243
1244out:
1245 if (error)
1246 git__free(raw.data);
1247 return error;
2cdc4544
RJ
1248}
1249
43820f20
VM
1250int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
1251{
1252 int error;
1253
c25aa7cd
PP
1254 GIT_ASSERT_ARG(out);
1255 GIT_ASSERT_ARG(db);
1256 GIT_ASSERT_ARG(id);
43820f20 1257
22a2d3d5 1258 if (git_oid_is_zero(id))
eae0bfdc
PP
1259 return error_null_oid(GIT_ENOTFOUND, "cannot read object");
1260
43820f20
VM
1261 *out = git_cache_get_raw(odb_cache(db), id);
1262 if (*out != NULL)
1263 return 0;
1264
1265 error = odb_read_1(out, db, id, false);
1266
1267 if (error == GIT_ENOTFOUND && !git_odb_refresh(db))
1268 error = odb_read_1(out, db, id, true);
1269
1270 if (error == GIT_ENOTFOUND)
e10144ae 1271 return git_odb__error_notfound("no match for id", id, GIT_OID_HEXSZ);
43820f20
VM
1272
1273 return error;
1274}
1275
ac3d33df 1276static int odb_otype_fast(git_object_t *type_p, git_odb *db, const git_oid *id)
4416aa77
VM
1277{
1278 git_odb_object *object;
1279 size_t _unused;
1280 int error;
1281
22a2d3d5 1282 if (git_oid_is_zero(id))
eae0bfdc
PP
1283 return error_null_oid(GIT_ENOTFOUND, "cannot get object type");
1284
4416aa77
VM
1285 if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
1286 *type_p = object->cached.type;
6147f643 1287 git_odb_object_free(object);
4416aa77
VM
1288 return 0;
1289 }
eae0bfdc 1290
4416aa77
VM
1291 error = odb_read_header_1(&_unused, type_p, db, id, false);
1292
1293 if (error == GIT_PASSTHROUGH) {
1294 error = odb_read_1(&object, db, id, false);
1295 if (!error)
1296 *type_p = object->cached.type;
1297 git_odb_object_free(object);
1298 }
1299
1300 return error;
1301}
1302
43820f20
VM
1303static int read_prefix_1(git_odb_object **out, git_odb *db,
1304 const git_oid *key, size_t len, bool only_refreshed)
dd453c4d 1305{
10c06114 1306 size_t i;
7776db51 1307 int error = 0;
43820f20 1308 git_oid found_full_oid = {{0}};
14109620 1309 git_rawobj raw = {0};
c06e0003 1310 void *data = NULL;
b1a6c316 1311 bool found = false;
78606263 1312 git_odb_object *object;
dd453c4d 1313
c25aa7cd
PP
1314 if ((error = git_mutex_lock(&db->lock)) < 0) {
1315 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
1316 return error;
1317 }
24634c6f 1318 for (i = 0; i < db->backends.length; ++i) {
dd453c4d
MP
1319 backend_internal *internal = git_vector_get(&db->backends, i);
1320 git_odb_backend *b = internal->backend;
1321
43820f20
VM
1322 if (only_refreshed && !b->refresh)
1323 continue;
1324
b1a6c316 1325 if (b->read_prefix != NULL) {
24634c6f 1326 git_oid full_oid;
43820f20 1327 error = b->read_prefix(&full_oid, &raw.data, &raw.len, &raw.type, b, key, len);
cb3010c5
ET
1328
1329 if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH) {
1330 error = 0;
24634c6f 1331 continue;
cb3010c5 1332 }
24634c6f 1333
c25aa7cd
PP
1334 if (error) {
1335 git_mutex_unlock(&db->lock);
14109620 1336 goto out;
c25aa7cd 1337 }
24634c6f 1338
c06e0003
CMN
1339 git__free(data);
1340 data = raw.data;
4a863c06 1341
e54cfb9b 1342 if (found && git_oid__cmp(&full_oid, &found_full_oid)) {
e579e0f7 1343 git_str buf = GIT_STR_INIT;
14109620 1344
e579e0f7 1345 git_str_printf(&buf, "multiple matches for prefix: %s",
14109620 1346 git_oid_tostr_s(&full_oid));
e579e0f7 1347 git_str_printf(&buf, " %s",
14109620
PS
1348 git_oid_tostr_s(&found_full_oid));
1349
1350 error = git_odb__error_ambiguous(buf.ptr);
e579e0f7 1351 git_str_dispose(&buf);
c25aa7cd 1352 git_mutex_unlock(&db->lock);
14109620 1353 goto out;
e54cfb9b 1354 }
4a863c06 1355
24634c6f
HWN
1356 found_full_oid = full_oid;
1357 found = true;
dd453c4d
MP
1358 }
1359 }
c25aa7cd 1360 git_mutex_unlock(&db->lock);
dd453c4d 1361
24634c6f 1362 if (!found)
43820f20 1363 return GIT_ENOTFOUND;
dd453c4d 1364
e0973bc0
PS
1365 if (git_odb__strict_hash_verification) {
1366 git_oid hash;
1367
1368 if ((error = git_odb_hash(&hash, raw.data, raw.len, raw.type)) < 0)
1369 goto out;
1370
1371 if (!git_oid_equal(&found_full_oid, &hash)) {
1372 error = git_odb__error_mismatch(&found_full_oid, &hash);
1373 goto out;
1374 }
1375 }
1376
eae0bfdc
PP
1377 if ((object = odb_object__alloc(&found_full_oid, &raw)) == NULL) {
1378 error = -1;
14109620 1379 goto out;
eae0bfdc 1380 }
78606263
RB
1381
1382 *out = git_cache_store_raw(odb_cache(db), object);
14109620
PS
1383
1384out:
1385 if (error)
1386 git__free(raw.data);
1387
1388 return error;
dd453c4d
MP
1389}
1390
43820f20
VM
1391int git_odb_read_prefix(
1392 git_odb_object **out, git_odb *db, const git_oid *short_id, size_t len)
1393{
1394 git_oid key = {{0}};
1395 int error;
1396
c25aa7cd
PP
1397 GIT_ASSERT_ARG(out);
1398 GIT_ASSERT_ARG(db);
43820f20
VM
1399
1400 if (len < GIT_OID_MINPREFIXLEN)
1401 return git_odb__error_ambiguous("prefix length too short");
1402
1403 if (len > GIT_OID_HEXSZ)
1404 len = GIT_OID_HEXSZ;
1405
1406 if (len == GIT_OID_HEXSZ) {
1407 *out = git_cache_get_raw(odb_cache(db), short_id);
1408 if (*out != NULL)
1409 return 0;
1410 }
1411
6c04269c 1412 git_oid__cpy_prefix(&key, short_id, len);
43820f20
VM
1413
1414 error = read_prefix_1(out, db, &key, len, false);
1415
1416 if (error == GIT_ENOTFOUND && !git_odb_refresh(db))
1417 error = read_prefix_1(out, db, &key, len, true);
1418
1419 if (error == GIT_ENOTFOUND)
e10144ae 1420 return git_odb__error_notfound("no match for prefix", &key, len);
43820f20
VM
1421
1422 return error;
1423}
1424
2e76b5fc 1425int git_odb_foreach(git_odb *db, git_odb_foreach_cb cb, void *payload)
521aedad
CMN
1426{
1427 unsigned int i;
c25aa7cd 1428 git_vector backends = GIT_VECTOR_INIT;
521aedad 1429 backend_internal *internal;
c25aa7cd
PP
1430 int error = 0;
1431
1432 /* Make a copy of the backends vector to invoke the callback without holding the lock. */
1433 if ((error = git_mutex_lock(&db->lock)) < 0) {
1434 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
1435 goto cleanup;
1436 }
1437 error = git_vector_dup(&backends, &db->backends, NULL);
1438 git_mutex_unlock(&db->lock);
1439
1440 if (error < 0)
1441 goto cleanup;
5dca2010 1442
c25aa7cd 1443 git_vector_foreach(&backends, i, internal) {
521aedad 1444 git_odb_backend *b = internal->backend;
c25aa7cd 1445 error = b->foreach(b, cb, payload);
ac3d33df 1446 if (error != 0)
c25aa7cd 1447 goto cleanup;
521aedad
CMN
1448 }
1449
c25aa7cd
PP
1450cleanup:
1451 git_vector_free(&backends);
1452
1453 return error;
521aedad
CMN
1454}
1455
e1de726c 1456int git_odb_write(
ac3d33df 1457 git_oid *oid, git_odb *db, const void *data, size_t len, git_object_t type)
f6f72d7e 1458{
10c06114 1459 size_t i;
22a2d3d5 1460 int error;
984ed6b6 1461 git_odb_stream *stream;
f6f72d7e 1462
c25aa7cd
PP
1463 GIT_ASSERT_ARG(oid);
1464 GIT_ASSERT_ARG(db);
f6f72d7e 1465
22a2d3d5
UG
1466 if ((error = git_odb_hash(oid, data, len, type)) < 0)
1467 return error;
eae0bfdc 1468
22a2d3d5 1469 if (git_oid_is_zero(oid))
eae0bfdc
PP
1470 return error_null_oid(GIT_EINVALID, "cannot write object");
1471
52d03f37 1472 if (git_odb__freshen(db, oid))
4d185dd9
DMB
1473 return 0;
1474
c25aa7cd
PP
1475 if ((error = git_mutex_lock(&db->lock)) < 0) {
1476 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
1477 return error;
1478 }
22a2d3d5 1479 for (i = 0, error = GIT_ERROR; i < db->backends.length && error < 0; ++i) {
f6f72d7e
VM
1480 backend_internal *internal = git_vector_get(&db->backends, i);
1481 git_odb_backend *b = internal->backend;
1482
1483 /* we don't write in alternates! */
1484 if (internal->is_alternate)
1485 continue;
1486
1487 if (b->write != NULL)
fe0c6d4e 1488 error = b->write(b, oid, data, len, type);
f6f72d7e 1489 }
c25aa7cd 1490 git_mutex_unlock(&db->lock);
f6f72d7e 1491
e172cf08 1492 if (!error || error == GIT_PASSTHROUGH)
e1de726c 1493 return 0;
984ed6b6 1494
f063f578
RB
1495 /* if no backends were able to write the object directly, we try a
1496 * streaming write to the backends; just write the whole object into the
1497 * stream in one push
1498 */
e1de726c
RB
1499 if ((error = git_odb_open_wstream(&stream, db, len, type)) != 0)
1500 return error;
f6f72d7e 1501
e579e0f7
MB
1502 if ((error = stream->write(stream, data, len)) == 0)
1503 error = stream->finalize_write(stream, oid);
e1de726c 1504
e579e0f7 1505 git_odb_stream_free(stream);
e1de726c 1506 return error;
f6f72d7e
VM
1507}
1508
22a2d3d5 1509static int hash_header(git_hash_ctx *ctx, git_object_size_t size, git_object_t type)
8380b39a
CMN
1510{
1511 char header[64];
eae0bfdc
PP
1512 size_t hdrlen;
1513 int error;
8380b39a 1514
eae0bfdc
PP
1515 if ((error = git_odb__format_object_header(&hdrlen,
1516 header, sizeof(header), size, type)) < 0)
1517 return error;
1518
1519 return git_hash_update(ctx, header, hdrlen);
8380b39a
CMN
1520}
1521
e1de726c 1522int git_odb_open_wstream(
22a2d3d5 1523 git_odb_stream **stream, git_odb *db, git_object_size_t size, git_object_t type)
a7c60cfc 1524{
f063f578 1525 size_t i, writes = 0;
7d7cd885 1526 int error = GIT_ERROR;
7bd2f401 1527 git_hash_ctx *ctx = NULL;
bed3229b 1528
c25aa7cd
PP
1529 GIT_ASSERT_ARG(stream);
1530 GIT_ASSERT_ARG(db);
bed3229b 1531
c25aa7cd
PP
1532 if ((error = git_mutex_lock(&db->lock)) < 0) {
1533 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
1534 return error;
1535 }
1536 error = GIT_ERROR;
7d7cd885 1537 for (i = 0; i < db->backends.length && error < 0; ++i) {
d4b5a4e2
VM
1538 backend_internal *internal = git_vector_get(&db->backends, i);
1539 git_odb_backend *b = internal->backend;
1540
1541 /* we don't write in alternates! */
1542 if (internal->is_alternate)
1543 continue;
255a0dab 1544
f063f578
RB
1545 if (b->writestream != NULL) {
1546 ++writes;
72a3fe42 1547 error = b->writestream(stream, b, size, type);
f063f578
RB
1548 } else if (b->write != NULL) {
1549 ++writes;
d69d0185 1550 error = init_fake_wstream(stream, b, size, type);
f063f578 1551 }
72a3fe42 1552 }
c25aa7cd 1553 git_mutex_unlock(&db->lock);
72a3fe42 1554
7bd2f401
ET
1555 if (error < 0) {
1556 if (error == GIT_PASSTHROUGH)
1557 error = 0;
1558 else if (!writes)
1559 error = git_odb__error_unsupported_in_backend("write object");
1560
1561 goto done;
1562 }
984ed6b6 1563
8380b39a 1564 ctx = git__malloc(sizeof(git_hash_ctx));
ac3d33df 1565 GIT_ERROR_CHECK_ALLOC(ctx);
8380b39a 1566
e579e0f7 1567 if ((error = git_hash_ctx_init(ctx, GIT_HASH_ALGORITHM_SHA1)) < 0 ||
eae0bfdc 1568 (error = hash_header(ctx, size, type)) < 0)
7bd2f401 1569 goto done;
8380b39a 1570
8380b39a 1571 (*stream)->hash_ctx = ctx;
031f3f80 1572 (*stream)->declared_size = size;
1573 (*stream)->received_bytes = 0;
1574
7bd2f401 1575done:
eae0bfdc
PP
1576 if (error)
1577 git__free(ctx);
e1de726c 1578 return error;
72a3fe42
VM
1579}
1580
031f3f80 1581static int git_odb_stream__invalid_length(
1582 const git_odb_stream *stream,
1583 const char *action)
1584{
ac3d33df 1585 git_error_set(GIT_ERROR_ODB,
909d5494 1586 "cannot %s - "
6c7cee42
RD
1587 "Invalid length. %"PRId64" was expected. The "
1588 "total size of the received chunks amounts to %"PRId64".",
8d93a11c 1589 action, stream->declared_size, stream->received_bytes);
031f3f80 1590
1591 return -1;
1592}
1593
376e6c9f
CMN
1594int git_odb_stream_write(git_odb_stream *stream, const char *buffer, size_t len)
1595{
8380b39a 1596 git_hash_update(stream->hash_ctx, buffer, len);
031f3f80 1597
1598 stream->received_bytes += len;
1599
1600 if (stream->received_bytes > stream->declared_size)
1601 return git_odb_stream__invalid_length(stream,
1602 "stream_write()");
1603
376e6c9f
CMN
1604 return stream->write(stream, buffer, len);
1605}
1606
1607int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream)
1608{
031f3f80 1609 if (stream->received_bytes != stream->declared_size)
1610 return git_odb_stream__invalid_length(stream,
1611 "stream_finalize_write()");
1612
e579e0f7 1613 git_hash_final(out->id, stream->hash_ctx);
4047950f 1614
52d03f37 1615 if (git_odb__freshen(stream->backend->odb, out))
4047950f 1616 return 0;
1617
fe0c6d4e 1618 return stream->finalize_write(stream, out);
376e6c9f
CMN
1619}
1620
1621int git_odb_stream_read(git_odb_stream *stream, char *buffer, size_t len)
1622{
1623 return stream->read(stream, buffer, len);
1624}
1625
1626void git_odb_stream_free(git_odb_stream *stream)
1627{
ae3b6d61
BR
1628 if (stream == NULL)
1629 return;
1630
c251f3bb 1631 git_hash_ctx_cleanup(stream->hash_ctx);
8380b39a 1632 git__free(stream->hash_ctx);
376e6c9f
CMN
1633 stream->free(stream);
1634}
1635
eae0bfdc
PP
1636int git_odb_open_rstream(
1637 git_odb_stream **stream,
1638 size_t *len,
ac3d33df 1639 git_object_t *type,
eae0bfdc
PP
1640 git_odb *db,
1641 const git_oid *oid)
72a3fe42 1642{
f063f578 1643 size_t i, reads = 0;
72a3fe42
VM
1644 int error = GIT_ERROR;
1645
c25aa7cd
PP
1646 GIT_ASSERT_ARG(stream);
1647 GIT_ASSERT_ARG(db);
72a3fe42 1648
c25aa7cd
PP
1649 if ((error = git_mutex_lock(&db->lock)) < 0) {
1650 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
1651 return error;
1652 }
1653 error = GIT_ERROR;
72a3fe42
VM
1654 for (i = 0; i < db->backends.length && error < 0; ++i) {
1655 backend_internal *internal = git_vector_get(&db->backends, i);
1656 git_odb_backend *b = internal->backend;
1657
f063f578
RB
1658 if (b->readstream != NULL) {
1659 ++reads;
eae0bfdc 1660 error = b->readstream(stream, len, type, b, oid);
f063f578 1661 }
adc0327a 1662 }
c25aa7cd 1663 git_mutex_unlock(&db->lock);
adc0327a 1664
e172cf08 1665 if (error == GIT_PASSTHROUGH)
e1de726c 1666 error = 0;
f063f578
RB
1667 if (error < 0 && !reads)
1668 error = git_odb__error_unsupported_in_backend("read object streamed");
984ed6b6 1669
e1de726c
RB
1670 return error;
1671}
1672
22a2d3d5 1673int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_indexer_progress_cb progress_cb, void *progress_payload)
09cc0b92 1674{
f063f578 1675 size_t i, writes = 0;
09cc0b92
ET
1676 int error = GIT_ERROR;
1677
c25aa7cd
PP
1678 GIT_ASSERT_ARG(out);
1679 GIT_ASSERT_ARG(db);
09cc0b92 1680
c25aa7cd
PP
1681 if ((error = git_mutex_lock(&db->lock)) < 0) {
1682 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
1683 return error;
1684 }
1685 error = GIT_ERROR;
09cc0b92
ET
1686 for (i = 0; i < db->backends.length && error < 0; ++i) {
1687 backend_internal *internal = git_vector_get(&db->backends, i);
1688 git_odb_backend *b = internal->backend;
1689
1690 /* we don't write in alternates! */
1691 if (internal->is_alternate)
1692 continue;
1693
f063f578
RB
1694 if (b->writepack != NULL) {
1695 ++writes;
0b33fca0 1696 error = b->writepack(out, b, db, progress_cb, progress_payload);
f063f578 1697 }
09cc0b92 1698 }
c25aa7cd 1699 git_mutex_unlock(&db->lock);
09cc0b92
ET
1700
1701 if (error == GIT_PASSTHROUGH)
1702 error = 0;
f063f578
RB
1703 if (error < 0 && !writes)
1704 error = git_odb__error_unsupported_in_backend("write pack");
09cc0b92
ET
1705
1706 return error;
1707}
1708
c25aa7cd
PP
1709int git_odb_write_multi_pack_index(git_odb *db)
1710{
1711 size_t i, writes = 0;
1712 int error = GIT_ERROR;
1713
1714 GIT_ASSERT_ARG(db);
1715
1716 for (i = 0; i < db->backends.length && error < 0; ++i) {
1717 backend_internal *internal = git_vector_get(&db->backends, i);
1718 git_odb_backend *b = internal->backend;
1719
1720 /* we don't write in alternates! */
1721 if (internal->is_alternate)
1722 continue;
1723
1724 if (b->writemidx != NULL) {
1725 ++writes;
1726 error = b->writemidx(b);
1727 }
1728 }
1729
1730 if (error == GIT_PASSTHROUGH)
1731 error = 0;
1732 if (error < 0 && !writes)
1733 error = git_odb__error_unsupported_in_backend("write multi-pack-index");
1734
1735 return error;
1736}
1737
22a2d3d5 1738void *git_odb_backend_data_alloc(git_odb_backend *backend, size_t len)
c49d328c 1739{
0e9f2fce 1740 GIT_UNUSED(backend);
c49d328c
PK
1741 return git__malloc(len);
1742}
1743
22a2d3d5
UG
1744#ifndef GIT_DEPRECATE_HARD
1745void *git_odb_backend_malloc(git_odb_backend *backend, size_t len)
1746{
1747 return git_odb_backend_data_alloc(backend, len);
1748}
1749#endif
1750
1751void git_odb_backend_data_free(git_odb_backend *backend, void *data)
1752{
1753 GIT_UNUSED(backend);
1754 git__free(data);
1755}
1756
4a863c06
VM
1757int git_odb_refresh(struct git_odb *db)
1758{
10c06114 1759 size_t i;
c25aa7cd
PP
1760 int error;
1761
1762 GIT_ASSERT_ARG(db);
4a863c06 1763
c25aa7cd
PP
1764 if ((error = git_mutex_lock(&db->lock)) < 0) {
1765 git_error_set(GIT_ERROR_ODB, "failed to acquire the odb lock");
1766 return error;
1767 }
4a863c06
VM
1768 for (i = 0; i < db->backends.length; ++i) {
1769 backend_internal *internal = git_vector_get(&db->backends, i);
1770 git_odb_backend *b = internal->backend;
1771
1772 if (b->refresh != NULL) {
1773 int error = b->refresh(b);
c25aa7cd
PP
1774 if (error < 0) {
1775 git_mutex_unlock(&db->lock);
4a863c06 1776 return error;
c25aa7cd 1777 }
4a863c06
VM
1778 }
1779 }
c25aa7cd
PP
1780 if (db->cgraph)
1781 git_commit_graph_refresh(db->cgraph);
1782 git_mutex_unlock(&db->lock);
4a863c06
VM
1783
1784 return 0;
1785}
1786
28a0741f
PS
1787int git_odb__error_mismatch(const git_oid *expected, const git_oid *actual)
1788{
1789 char expected_oid[GIT_OID_HEXSZ + 1], actual_oid[GIT_OID_HEXSZ + 1];
1790
1791 git_oid_tostr(expected_oid, sizeof(expected_oid), expected);
1792 git_oid_tostr(actual_oid, sizeof(actual_oid), actual);
1793
ac3d33df 1794 git_error_set(GIT_ERROR_ODB, "object hash mismatch - expected %s but got %s",
28a0741f
PS
1795 expected_oid, actual_oid);
1796
1797 return GIT_EMISMATCH;
1798}
1799
e10144ae
ET
1800int git_odb__error_notfound(
1801 const char *message, const git_oid *oid, size_t oid_len)
e1de726c 1802{
282283ac
RB
1803 if (oid != NULL) {
1804 char oid_str[GIT_OID_HEXSZ + 1];
2076d329 1805 git_oid_tostr(oid_str, oid_len+1, oid);
ac3d33df 1806 git_error_set(GIT_ERROR_ODB, "object not found - %s (%.*s)",
901434b0 1807 message, (int) oid_len, oid_str);
282283ac 1808 } else
ac3d33df 1809 git_error_set(GIT_ERROR_ODB, "object not found - %s", message);
282283ac 1810
904b67e6 1811 return GIT_ENOTFOUND;
e1de726c
RB
1812}
1813
eae0bfdc
PP
1814static int error_null_oid(int error, const char *message)
1815{
ac3d33df 1816 git_error_set(GIT_ERROR_ODB, "odb: %s: null OID cannot exist", message);
eae0bfdc
PP
1817 return error;
1818}
1819
e1de726c
RB
1820int git_odb__error_ambiguous(const char *message)
1821{
ac3d33df 1822 git_error_set(GIT_ERROR_ODB, "ambiguous SHA1 prefix - %s", message);
904b67e6 1823 return GIT_EAMBIGUOUS;
7b6e8067
RJ
1824}
1825
bc91347b 1826int git_odb_init_backend(git_odb_backend *backend, unsigned int version)
b9f81997 1827{
bc91347b
RB
1828 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
1829 backend, version, git_odb_backend, GIT_ODB_BACKEND_INIT);
1830 return 0;
b9f81997 1831}