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.
33 #define GIT_PACK_NAME_MAX (5 + 40 + 1)
38 /** Functions to access idx_map. */
44 /** The .idx file, mapped into memory. */
48 unsigned char *im_oid
;
50 uint32_t *im_offset32
;
51 uint32_t *im_offset64
;
53 /** Number of objects in this pack. */
56 /** Number of git_packlist we appear in. */
59 /** Number of active users of the idx_map data. */
62 invalid
:1 /* the pack is unable to be read by libgit2 */
65 /** Name of the pack file(s), without extension ("pack-abc"). */
66 char pack_name
[GIT_PACK_NAME_MAX
];
68 typedef struct git_pack git_pack
;
73 git_pack
*packs
[GIT_FLEX_ARRAY
];
79 /** Path to the "objects" directory. */
82 /** Known pack files from ${objects_dir}/packs. */
83 git_packlist
*packlist
;
85 /** Alternate databases to search. */
89 /** loose object zlib compression level. */
90 int object_zlib_level
;
91 /** loose object file fsync flag. */
92 int fsync_object_files
;
95 typedef struct { /* object header data */
96 git_otype type
; /* object type */
97 size_t size
; /* object size */
101 const char *str
; /* type name string */
102 int loose
; /* valid loose object type flag */
103 } obj_type_table
[] = {
104 { "", 0 }, /* 0 = GIT_OBJ__EXT1 */
105 { "commit", 1 }, /* 1 = GIT_OBJ_COMMIT */
106 { "tree", 1 }, /* 2 = GIT_OBJ_TREE */
107 { "blob", 1 }, /* 3 = GIT_OBJ_BLOB */
108 { "tag", 1 }, /* 4 = GIT_OBJ_TAG */
109 { "", 0 }, /* 5 = GIT_OBJ__EXT2 */
110 { "OFS_DELTA", 0 }, /* 6 = GIT_OBJ_OFS_DELTA */
111 { "REF_DELTA", 0 } /* 7 = GIT_OBJ_REF_DELTA */
114 GIT_INLINE(uint32_t) decode32(void *b
)
116 return ntohl(*((uint32_t*)b
));
119 GIT_INLINE(uint64_t) decode64(void *b
)
122 return (((uint64_t)ntohl(p
[0])) << 32) | ntohl(p
[1]);
125 const char *git_obj_type_to_string(git_otype type
)
127 if (type
< 0 || type
>= ARRAY_SIZE(obj_type_table
))
129 return obj_type_table
[type
].str
;
132 git_otype
git_obj_string_to_type(const char *str
)
139 for (i
= 0; i
< ARRAY_SIZE(obj_type_table
); i
++)
140 if (!strcmp(str
, obj_type_table
[i
].str
))
141 return (git_otype
) i
;
146 int git_obj__loose_object_type(git_otype type
)
148 if (type
< 0 || type
>= ARRAY_SIZE(obj_type_table
))
150 return obj_type_table
[type
].loose
;
153 static int format_object_header(char *hdr
, size_t n
, git_obj
*obj
)
155 const char *type_str
= git_obj_type_to_string(obj
->type
);
156 int len
= snprintf(hdr
, n
, "%s %"PRIuZ
, type_str
, obj
->len
);
158 assert(len
> 0); /* otherwise snprintf() is broken */
159 assert(len
< n
); /* otherwise the caller is broken! */
161 if (len
< 0 || len
>= n
)
166 static int hash_obj(git_oid
*id
, char *hdr
, size_t n
, int *len
, git_obj
*obj
)
171 assert(id
&& hdr
&& len
&& obj
);
173 if (!git_obj__loose_object_type(obj
->type
))
176 if (!obj
->data
&& obj
->len
!= 0)
179 if ((hdrlen
= format_object_header(hdr
, n
, obj
)) < 0)
186 vec
[1].data
= obj
->data
;
187 vec
[1].len
= obj
->len
;
189 git_hash_vec(id
, vec
, 2);
194 int git_obj_hash(git_oid
*id
, git_obj
*obj
)
201 return hash_obj(id
, hdr
, sizeof(hdr
), &hdrlen
, obj
);
204 static size_t object_file_name(char *name
, size_t n
, char *dir
, const git_oid
*id
)
206 size_t len
= strlen(dir
);
208 /* check length: 43 = 40 hex sha1 chars + 2 * '/' + '\0' */
212 /* the object dir: eg $GIT_DIR/objects */
214 if (name
[len
-1] != '/')
217 /* loose object filename: aa/aaa... (41 bytes) */
218 git_oid_pathfmt(&name
[len
], id
);
224 static int is_zlib_compressed_data(unsigned char *data
)
228 w
= ((unsigned int)(data
[0]) << 8) + data
[1];
229 return data
[0] == 0x78 && !(w
%31);
232 static size_t get_binary_object_header(obj_hdr
*hdr
, gitfo_buf
*obj
)
235 unsigned char *data
= obj
->data
;
236 size_t shift
, size
, used
= 0;
242 hdr
->type
= (c
>> 4) & 7;
247 if (obj
->len
<= used
)
249 if (sizeof(size_t) * 8 <= shift
)
252 size
+= (c
& 0x7f) << shift
;
260 static size_t get_object_header(obj_hdr
*hdr
, unsigned char *data
)
262 char c
, typename
[10];
263 size_t size
, used
= 0;
266 * type name string followed by space.
268 while ((c
= data
[used
]) != ' ') {
269 typename
[used
++] = c
;
270 if (used
>= sizeof(typename
))
276 hdr
->type
= git_obj_string_to_type(typename
);
277 used
++; /* consume the space */
280 * length follows immediately in decimal (without
283 size
= data
[used
++] - '0';
287 while ((c
= data
[used
]) != '\0') {
292 size
= size
* 10 + d
;
298 * the length must be followed by a zero byte
300 if (data
[used
++] != '\0')
306 static void init_stream(z_stream
*s
, void *out
, size_t len
)
308 memset(s
, 0, sizeof(*s
));
313 static void set_stream_input(z_stream
*s
, void *in
, size_t len
)
319 static void set_stream_output(z_stream
*s
, void *out
, size_t len
)
325 static int start_inflate(z_stream
*s
, gitfo_buf
*obj
, void *out
, size_t len
)
329 init_stream(s
, out
, len
);
330 set_stream_input(s
, obj
->data
, obj
->len
);
332 if ((status
= inflateInit(s
)) < Z_OK
)
335 return inflate(s
, 0);
338 static int finish_inflate(z_stream
*s
)
342 while (status
== Z_OK
)
343 status
= inflate(s
, Z_FINISH
);
347 if ((status
!= Z_STREAM_END
) || (s
->avail_in
!= 0))
353 static void *inflate_tail(z_stream
*s
, void *hb
, size_t used
, obj_hdr
*hdr
)
355 unsigned char *buf
, *head
= hb
;
359 * allocate a buffer to hold the inflated data and copy the
360 * initial sequence of inflated data from the tail of the
361 * head buffer, if any.
363 if ((buf
= git__malloc(hdr
->size
+ 1)) == NULL
) {
367 tail
= s
->total_out
- used
;
368 if (used
> 0 && tail
> 0) {
369 if (tail
> hdr
->size
)
371 memcpy(buf
, head
+ used
, tail
);
376 * inflate the remainder of the object data, if any
378 if (hdr
->size
< used
)
381 set_stream_output(s
, buf
+ used
, hdr
->size
- used
);
382 if (finish_inflate(s
)) {
391 static int inflate_buffer(void *in
, size_t inlen
, void *out
, size_t outlen
)
396 init_stream(&zs
, out
, outlen
);
397 set_stream_input(&zs
, in
, inlen
);
399 if (inflateInit(&zs
) < Z_OK
)
402 while (status
== Z_OK
)
403 status
= inflate(&zs
, Z_FINISH
);
407 if ((status
!= Z_STREAM_END
) || (zs
.avail_in
!= 0))
410 if (zs
.total_out
!= outlen
)
417 * At one point, there was a loose object format that was intended to
418 * mimic the format used in pack-files. This was to allow easy copying
419 * of loose object data into packs. This format is no longer used, but
420 * we must still read it.
422 static int inflate_packlike_loose_disk_obj(git_obj
*out
, gitfo_buf
*obj
)
424 unsigned char *in
, *buf
;
429 * read the object header, which is an (uncompressed)
430 * binary encoding of the object type and size.
432 if ((used
= get_binary_object_header(&hdr
, obj
)) == 0)
435 if (!git_obj__loose_object_type(hdr
.type
))
439 * allocate a buffer and inflate the data into it
441 buf
= git__malloc(hdr
.size
+ 1);
445 in
= ((unsigned char *)obj
->data
) + used
;
446 len
= obj
->len
- used
;
447 if (inflate_buffer(in
, len
, buf
, hdr
.size
)) {
451 buf
[hdr
.size
] = '\0';
455 out
->type
= hdr
.type
;
460 static int inflate_disk_obj(git_obj
*out
, gitfo_buf
*obj
)
462 unsigned char head
[64], *buf
;
469 * check for a pack-like loose object
471 if (!is_zlib_compressed_data(obj
->data
))
472 return inflate_packlike_loose_disk_obj(out
, obj
);
475 * inflate the initial part of the io buffer in order
476 * to parse the object header (type and size).
478 if ((z_status
= start_inflate(&zs
, obj
, head
, sizeof(head
))) < Z_OK
)
481 if ((used
= get_object_header(&hdr
, head
)) == 0)
484 if (!git_obj__loose_object_type(hdr
.type
))
488 * allocate a buffer and inflate the object data into it
489 * (including the initial sequence in the head buffer).
491 if ((buf
= inflate_tail(&zs
, head
, used
, &hdr
)) == NULL
)
493 buf
[hdr
.size
] = '\0';
497 out
->type
= hdr
.type
;
502 static int make_temp_file(git_file
*fd
, char *tmp
, size_t n
, char *file
)
504 char *template = "/tmp_obj_XXXXXX";
505 size_t tmplen
= strlen(template);
508 if ((dirlen
= git__dirname(tmp
, n
, file
)) < 0)
511 if ((dirlen
+ tmplen
) >= n
)
514 strcpy(tmp
+ dirlen
, (dirlen
) ? template : template + 1);
516 *fd
= gitfo_mkstemp(tmp
);
517 if (*fd
< 0 && dirlen
) {
518 /* create directory if it doesn't exist */
520 if ((gitfo_exists(tmp
) < 0) && gitfo_mkdir(tmp
, 0755))
523 strcpy(tmp
+ dirlen
, template);
524 *fd
= gitfo_mkstemp(tmp
);
532 static int deflate_buf(z_stream
*s
, void *in
, size_t len
, int flush
)
536 set_stream_input(s
, in
, len
);
537 while (status
== Z_OK
) {
538 status
= deflate(s
, flush
);
539 if (s
->avail_in
== 0)
545 static int deflate_obj(gitfo_buf
*buf
, char *hdr
, int hdrlen
, git_obj
*obj
, int level
)
551 assert(buf
&& !buf
->data
&& hdr
&& obj
);
552 assert(level
== Z_DEFAULT_COMPRESSION
|| (level
>= 0 && level
<= 9));
556 init_stream(&zs
, NULL
, 0);
558 if (deflateInit(&zs
, level
) < Z_OK
)
561 size
= deflateBound(&zs
, hdrlen
+ obj
->len
);
563 if ((buf
->data
= git__malloc(size
)) == NULL
) {
568 set_stream_output(&zs
, buf
->data
, size
);
570 /* compress the header */
571 status
= deflate_buf(&zs
, hdr
, hdrlen
, Z_NO_FLUSH
);
573 /* if header compressed OK, compress the object */
575 status
= deflate_buf(&zs
, obj
->data
, obj
->len
, Z_FINISH
);
577 if (status
!= Z_STREAM_END
) {
584 buf
->len
= zs
.total_out
;
590 static int write_obj(gitfo_buf
*buf
, git_oid
*id
, git_odb
*db
)
592 char file
[GIT_PATH_MAX
];
593 char temp
[GIT_PATH_MAX
];
596 if (object_file_name(file
, sizeof(file
), db
->objects_dir
, id
))
599 if (make_temp_file(&fd
, temp
, sizeof(temp
), file
) < 0)
602 if (gitfo_write(fd
, buf
->data
, buf
->len
) < 0) {
608 if (db
->fsync_object_files
)
611 gitfo_chmod(temp
, 0444);
613 if (gitfo_move_file(temp
, file
) < 0) {
621 static int open_alternates(git_odb
*db
)
625 gitlck_lock(&db
->lock
);
626 if (db
->alternates
) {
627 gitlck_unlock(&db
->lock
);
631 db
->alternates
= git__malloc(sizeof(*db
->alternates
) * (n
+ 1));
632 if (!db
->alternates
) {
633 gitlck_unlock(&db
->lock
);
637 db
->alternates
[n
] = NULL
;
638 db
->n_alternates
= n
;
639 gitlck_unlock(&db
->lock
);
643 static int pack_openidx_map(git_pack
*p
)
645 char pb
[GIT_PATH_MAX
];
648 if (git__fmt(pb
, sizeof(pb
), "%s/pack/%s.idx",
653 if ((p
->idx_fd
= gitfo_open(pb
, O_RDONLY
)) < 0)
656 if ((len
= gitfo_size(p
->idx_fd
)) < 0
657 || !git__is_sizet(len
)
658 || gitfo_map_ro(&p
->idx_map
, p
->idx_fd
, 0, (size_t)len
)) {
659 gitfo_close(p
->idx_fd
);
666 static int idxv1_search(off_t
*out
, git_pack
*p
, const git_oid
*id
)
668 unsigned char *data
= p
->im_oid
;
669 size_t lo
= id
->id
[0] ? p
->im_fanout
[id
->id
[0] - 1] : 0;
670 size_t hi
= p
->im_fanout
[id
->id
[0]];
673 size_t mid
= (lo
+ hi
) >> 1;
674 size_t pos
= 24 * mid
;
675 int cmp
= memcmp(id
->id
, data
+ pos
+ 4, 20);
679 *out
= decode32(data
+ pos
);
684 return GIT_ENOTFOUND
;
687 static int pack_openidx_v1(git_pack
*p
)
689 uint32_t *src_fanout
= p
->idx_map
.data
;
694 if ((im_fanout
= git__malloc(sizeof(*im_fanout
) * 256)) == NULL
)
697 im_fanout
[0] = decode32(&src_fanout
[0]);
698 for (j
= 1; j
< 256; j
++) {
699 im_fanout
[j
] = decode32(&src_fanout
[j
]);
700 if (im_fanout
[j
] < im_fanout
[j
- 1]) {
705 p
->obj_cnt
= im_fanout
[255];
707 expsz
= 4 * 256 + 24 * p
->obj_cnt
+ 2 * 20;
708 if (expsz
!= p
->idx_map
.len
) {
713 p
->idx_search
= idxv1_search
;
714 p
->im_fanout
= im_fanout
;
715 p
->im_oid
= (unsigned char*)(src_fanout
+ 256);
719 static int idxv2_search(off_t
*out
, git_pack
*p
, const git_oid
*id
)
721 unsigned char *data
= p
->im_oid
;
722 size_t lo
= id
->id
[0] ? p
->im_fanout
[id
->id
[0] - 1] : 0;
723 size_t hi
= p
->im_fanout
[id
->id
[0]];
726 size_t mid
= (lo
+ hi
) >> 1;
727 size_t pos
= 20 * mid
;
728 int cmp
= memcmp(id
->id
, data
+ pos
, 20);
732 uint32_t o32
= decode32(p
->im_offset32
+ mid
);
733 if (o32
& 0x80000000)
734 *out
= decode64(p
->im_offset64
+ 2*(o32
& ~0x80000000));
741 return GIT_ENOTFOUND
;
744 static int pack_openidx_v2(git_pack
*p
)
746 unsigned char *data
= p
->idx_map
.data
;
747 uint32_t *src_fanout
= (uint32_t*)(data
+ 8);
751 if ((im_fanout
= git__malloc(sizeof(*im_fanout
) * 256)) == NULL
)
754 im_fanout
[0] = decode32(&src_fanout
[0]);
755 for (j
= 1; j
< 256; j
++) {
756 im_fanout
[j
] = decode32(&src_fanout
[j
]);
757 if (im_fanout
[j
] < im_fanout
[j
- 1]) {
762 p
->obj_cnt
= im_fanout
[255];
764 p
->idx_search
= idxv2_search
;
765 p
->im_fanout
= im_fanout
;
766 p
->im_oid
= (unsigned char*)(src_fanout
+ 256);
767 p
->im_crc
= (uint32_t*)(p
->im_oid
+ 20 * p
->obj_cnt
);
768 p
->im_offset32
= p
->im_crc
+ p
->obj_cnt
;
769 p
->im_offset64
= p
->im_offset32
+ p
->obj_cnt
;
773 static int pack_openidx(git_pack
*p
)
775 gitlck_lock(&p
->lock
);
778 if (++p
->idxcnt
== 1 && !p
->idx_search
) {
781 if (pack_openidx_map(p
))
783 data
= p
->idx_map
.data
;
785 if (decode32(&data
[0]) == PACK_TOC
) {
786 switch (decode32(&data
[1])) {
788 if (pack_openidx_v2(p
))
794 } else if (pack_openidx_v1(p
))
797 gitlck_unlock(&p
->lock
);
801 gitfo_free_map(&p
->idx_map
);
808 gitlck_unlock(&p
->lock
);
812 static void pack_decidx(git_pack
*p
)
814 gitlck_lock(&p
->lock
);
816 gitlck_unlock(&p
->lock
);
819 static void pack_dec(git_pack
*p
)
823 gitlck_lock(&p
->lock
);
824 need_free
= !--p
->refcnt
;
825 gitlck_unlock(&p
->lock
);
829 gitfo_free_map(&p
->idx_map
);
830 gitfo_close(p
->idx_fd
);
834 gitlck_free(&p
->lock
);
839 static void packlist_dec(git_odb
*db
, git_packlist
*pl
)
843 gitlck_lock(&db
->lock
);
844 need_free
= !--pl
->refcnt
;
845 gitlck_unlock(&db
->lock
);
849 for (j
= 0; j
< pl
->n_packs
; j
++)
850 pack_dec(pl
->packs
[j
]);
855 static git_pack
*alloc_pack(const char *pack_name
)
857 git_pack
*p
= git__calloc(1, sizeof(*p
));
861 gitlck_init(&p
->lock
);
862 strcpy(p
->pack_name
, pack_name
);
867 struct scanned_pack
{
868 struct scanned_pack
*next
;
872 static int scan_one_pack(void *state
, char *name
)
874 struct scanned_pack
**ret
= state
, *r
;
875 char *s
= strrchr(name
, '/'), *d
;
877 if (git__prefixcmp(s
+ 1, "pack-")
878 || git__suffixcmp(s
, ".pack")
879 || strlen(s
+ 1) != GIT_PACK_NAME_MAX
+ 4)
882 d
= strrchr(s
+ 1, '.');
883 strcpy(d
+ 1, "idx"); /* "pack-abc.pack" -> "pack-abc.idx" */
884 if (gitfo_exists(name
))
887 if ((r
= git__malloc(sizeof(*r
))) == NULL
)
890 *d
= '\0'; /* "pack-abc.pack" -_> "pack-abc" */
891 if ((r
->pack
= alloc_pack(s
+ 1)) == NULL
) {
901 static git_packlist
* scan_packs(git_odb
*db
)
903 char pb
[GIT_PATH_MAX
];
904 struct scanned_pack
*state
= NULL
, *c
;
906 git_packlist
*new_list
;
908 if (git__fmt(pb
, sizeof(pb
), "%s/pack", db
->objects_dir
) < 0)
910 gitfo_dirent(pb
, sizeof(pb
), scan_one_pack
, &state
);
912 /* TODO - merge old entries into the new array */
913 for (cnt
= 0, c
= state
; c
; c
= c
->next
)
915 new_list
= git__malloc(sizeof(*new_list
)
916 + (sizeof(new_list
->packs
[0]) * cnt
));
920 for (cnt
= 0, c
= state
; c
; ) {
921 struct scanned_pack
*n
= c
->next
;
923 new_list
->packs
[cnt
++] = c
->pack
;
927 new_list
->n_packs
= cnt
;
928 new_list
->refcnt
= 2;
929 db
->packlist
= new_list
;
934 struct scanned_pack
*n
= state
->next
;
935 pack_dec(state
->pack
);
942 static git_packlist
*packlist_get(git_odb
*db
)
946 gitlck_lock(&db
->lock
);
947 if ((pl
= db
->packlist
) != NULL
)
951 gitlck_unlock(&db
->lock
);
955 static int search_packs(git_pack
**p
, off_t
*offset
, git_odb
*db
, const git_oid
*id
)
957 git_packlist
*pl
= packlist_get(db
);
961 return GIT_ENOTFOUND
;
963 for (j
= 0; j
< pl
->n_packs
; j
++) {
965 git_pack
*pack
= pl
->packs
[j
];
969 if (pack_openidx(pack
))
971 res
= pack
->idx_search(&pos
, pack
, id
);
986 return GIT_ENOTFOUND
;
989 static int exists_packed(git_odb
*db
, const git_oid
*id
)
991 return !search_packs(NULL
, NULL
, db
, id
);
994 static int exists_loose(git_odb
*db
, const git_oid
*id
)
996 char file
[GIT_PATH_MAX
];
998 if (object_file_name(file
, sizeof(file
), db
->objects_dir
, id
))
1001 if (gitfo_exists(file
) < 0)
1007 int git_odb_exists(git_odb
*db
, const git_oid
*id
)
1009 /* TODO: extend to search alternate db's */
1010 if (exists_packed(db
, id
))
1012 return exists_loose(db
, id
);
1015 int git_odb_open(git_odb
**out
, const char *objects_dir
)
1017 git_odb
*db
= git__calloc(1, sizeof(*db
));
1021 db
->objects_dir
= git__strdup(objects_dir
);
1022 if (!db
->objects_dir
) {
1027 gitlck_init(&db
->lock
);
1029 db
->object_zlib_level
= Z_BEST_SPEED
;
1030 db
->fsync_object_files
= 0;
1036 void git_odb_close(git_odb
*db
)
1043 gitlck_lock(&db
->lock
);
1046 db
->packlist
= NULL
;
1048 if (db
->alternates
) {
1050 for (alt
= db
->alternates
; *alt
; alt
++)
1051 git_odb_close(*alt
);
1052 free(db
->alternates
);
1055 free(db
->objects_dir
);
1057 gitlck_unlock(&db
->lock
);
1059 packlist_dec(db
, pl
);
1060 gitlck_free(&db
->lock
);
1070 if (!git_odb__read_packed(out
, db
, id
))
1072 if (!git_odb__read_loose(out
, db
, id
))
1074 if (!open_alternates(db
))
1078 return GIT_ENOTFOUND
;
1081 int git_odb__read_loose(git_obj
*out
, git_odb
*db
, const git_oid
*id
)
1083 char file
[GIT_PATH_MAX
];
1084 gitfo_buf obj
= GITFO_BUF_INIT
;
1086 assert(out
&& db
&& id
);
1090 out
->type
= GIT_OBJ_BAD
;
1092 if (object_file_name(file
, sizeof(file
), db
->objects_dir
, id
))
1093 return GIT_ENOTFOUND
; /* TODO: error handling */
1095 if (gitfo_read_file(&obj
, file
))
1096 return GIT_ENOTFOUND
; /* TODO: error handling */
1098 if (inflate_disk_obj(out
, &obj
)) {
1099 gitfo_free_buf(&obj
);
1100 return GIT_ENOTFOUND
; /* TODO: error handling */
1103 gitfo_free_buf(&obj
);
1108 static int read_packed(git_obj
*out
, git_pack
*p
, const git_oid
*id
)
1113 if (pack_openidx(p
))
1115 res
= p
->idx_search(&pos
, p
, id
);
1119 /* TODO unpack object at pos */
1126 int git_odb__read_packed(git_obj
*out
, git_odb
*db
, const git_oid
*id
)
1128 git_packlist
*pl
= packlist_get(db
);
1132 return GIT_ENOTFOUND
;
1134 for (j
= 0; j
< pl
->n_packs
; j
++) {
1135 if (!read_packed(out
, pl
->packs
[j
], id
)) {
1136 packlist_dec(db
, pl
);
1141 packlist_dec(db
, pl
);
1142 return GIT_ENOTFOUND
;
1145 int git_odb_write(git_oid
*id
, git_odb
*db
, git_obj
*obj
)
1149 gitfo_buf buf
= GITFO_BUF_INIT
;
1151 assert(id
&& db
&& obj
);
1153 if (hash_obj(id
, hdr
, sizeof(hdr
), &hdrlen
, obj
) < 0)
1156 if (git_odb_exists(db
, id
))
1159 if (deflate_obj(&buf
, hdr
, hdrlen
, obj
, db
->object_zlib_level
) < 0)
1162 if (write_obj(&buf
, id
, db
) < 0) {
1163 gitfo_free_buf(&buf
);
1167 gitfo_free_buf(&buf
);