From 1e5dd57214dbec1b166c881c1c44c8930923da17 Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Fri, 12 Feb 2010 16:50:33 +0000 Subject: [PATCH 1/8] Fix some coding style issues Signed-off-by: Ramsay Jones --- src/commit.h | 2 +- src/fileops.h | 2 +- src/git/commit.h | 4 +- src/git/common.h | 10 ++--- src/git/oid.h | 3 +- src/git/revwalk.h | 4 +- src/odb.c | 20 ++++----- src/util.h | 2 +- tests/t0020-dirent.c | 36 ++++++++-------- tests/t0101-oid.c | 2 +- tests/t0102-objtype.c | 24 +++++------ tests/t0201-existsloose.c | 4 +- tests/t0301-write.c | 69 +++++++++++++++--------------- tests/test_helpers.c | 88 +++++++++++++++++++-------------------- tests/test_lib.c | 9 ++-- tests/test_lib.h | 2 +- 16 files changed, 139 insertions(+), 142 deletions(-) diff --git a/src/commit.h b/src/commit.h index 0b19f4634..05504cd34 100644 --- a/src/commit.h +++ b/src/commit.h @@ -9,7 +9,7 @@ struct git_commit { git_oid id; time_t commit_time; unsigned parsed:1, - flags:26; + flags:26; }; #endif diff --git a/src/fileops.h b/src/fileops.h index 53495ca95..dc5b2ce5d 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -34,7 +34,7 @@ extern int git__fsync(int fd); # ifndef GIT__WIN32_NO_HIDE_FILEOPS # define unlink(p) git__unlink(p) # define mkstemp(t) git__mkstemp(t) -# define mkdir(p,m) git__mkdir(p,m) +# define mkdir(p,m) git__mkdir(p, m) # define fsync(fd) git__fsync(fd) # endif #endif /* GIT_WIN32 */ diff --git a/src/git/commit.h b/src/git/commit.h index 979709bdb..010f258ae 100644 --- a/src/git/commit.h +++ b/src/git/commit.h @@ -25,14 +25,14 @@ typedef struct git_commit git_commit; * pool's git_odb, or if the commit is present but is * too malformed to be parsed successfully. */ -GIT_EXTERN(git_commit*) git_commit_parse(git_revpool *pool, const git_oid *id); +GIT_EXTERN(git_commit *) git_commit_parse(git_revpool *pool, const git_oid *id); /** * Get the id of a commit. * @param commit a previously parsed commit. * @return object identity for the commit. */ -GIT_EXTERN(const git_oid*) git_commit_id(git_commit *commit); +GIT_EXTERN(const git_oid *) git_commit_id(git_commit *commit); /** @} */ GIT_END_DECL diff --git a/src/git/common.h b/src/git/common.h index 375649f87..19c6a202c 100644 --- a/src/git/common.h +++ b/src/git/common.h @@ -16,8 +16,8 @@ /** Declare a public function exported for application use. */ #ifdef __GNUC__ # define GIT_EXTERN(type) extern \ - __attribute__((visibility("default"))) \ - type + __attribute__((visibility("default"))) \ + type #else # define GIT_EXTERN(type) extern type #endif @@ -25,9 +25,9 @@ /** Declare a public TLS symbol exported for application use. */ #ifdef __GNUC__ # define GIT_EXTERN_TLS(type) extern \ - __attribute__((visibility("default"))) \ - GIT_TLS \ - type + __attribute__((visibility("default"))) \ + GIT_TLS \ + type #else # define GIT_EXTERN_TLS(type) extern GIT_TLS type #endif diff --git a/src/git/oid.h b/src/git/oid.h index f3d6802e9..fe3c74b75 100644 --- a/src/git/oid.h +++ b/src/git/oid.h @@ -20,8 +20,7 @@ GIT_BEGIN_DECL #define GIT_OID_HEXSZ (GIT_OID_RAWSZ * 2) /** Unique identity of any object (commit, tree, blob, tag). */ -typedef struct -{ +typedef struct { /** raw binary formatted id */ unsigned char id[GIT_OID_RAWSZ]; } git_oid; diff --git a/src/git/revwalk.h b/src/git/revwalk.h index efaa4277c..5fac2a68a 100644 --- a/src/git/revwalk.h +++ b/src/git/revwalk.h @@ -25,7 +25,7 @@ GIT_BEGIN_DECL * @param db the database objects are read from. * @return the new traversal handle; NULL if memory is exhausted. */ -GIT_EXTERN(git_revpool*) gitrp_alloc(git_odb *db); +GIT_EXTERN(git_revpool *) gitrp_alloc(git_odb *db); /** * Reset the traversal machinary for reuse. @@ -52,7 +52,7 @@ GIT_EXTERN(void) gitrp_hide(git_revpool *pool, git_commit *commit); * @param pool the pool to pop the commit from. * @return next commit; NULL if there is no more output. */ -GIT_EXTERN(git_commit*) gitrp_next(git_revpool *pool); +GIT_EXTERN(git_commit *) gitrp_next(git_revpool *pool); /** * Free a revwalk previously allocated. diff --git a/src/odb.c b/src/odb.c index 982cc52d0..0985c00bc 100644 --- a/src/odb.c +++ b/src/odb.c @@ -100,7 +100,7 @@ typedef struct { /* object header data */ static struct { const char *str; /* type name string */ int loose; /* valid loose object type flag */ -} obj_type_table [] = { +} obj_type_table[] = { { "", 0 }, /* 0 = GIT_OBJ__EXT1 */ { "commit", 1 }, /* 1 = GIT_OBJ_COMMIT */ { "tree", 1 }, /* 2 = GIT_OBJ_TREE */ @@ -113,7 +113,7 @@ static struct { GIT_INLINE(uint32_t) decode32(void *b) { - return ntohl(*((uint32_t*)b)); + return ntohl(*((uint32_t *)b)); } GIT_INLINE(uint64_t) decode64(void *b) @@ -226,7 +226,7 @@ static int is_zlib_compressed_data(unsigned char *data) unsigned int w; w = ((unsigned int)(data[0]) << 8) + data[1]; - return data[0] == 0x78 && !(w %31); + return data[0] == 0x78 && !(w % 31); } static size_t get_binary_object_header(obj_hdr *hdr, gitfo_buf *obj) @@ -712,7 +712,7 @@ static int pack_openidx_v1(git_pack *p) p->idx_search = idxv1_search; p->im_fanout = im_fanout; - p->im_oid = (unsigned char*)(src_fanout + 256); + p->im_oid = (unsigned char *)(src_fanout + 256); return GIT_SUCCESS; } @@ -744,7 +744,7 @@ static int idxv2_search(off_t *out, git_pack *p, const git_oid *id) static int pack_openidx_v2(git_pack *p) { unsigned char *data = p->idx_map.data; - uint32_t *src_fanout = (uint32_t*)(data + 8); + uint32_t *src_fanout = (uint32_t *)(data + 8); uint32_t *im_fanout; int j; @@ -763,8 +763,8 @@ static int pack_openidx_v2(git_pack *p) p->idx_search = idxv2_search; p->im_fanout = im_fanout; - p->im_oid = (unsigned char*)(src_fanout + 256); - p->im_crc = (uint32_t*)(p->im_oid + 20 * p->obj_cnt); + p->im_oid = (unsigned char *)(src_fanout + 256); + p->im_crc = (uint32_t *)(p->im_oid + 20 * p->obj_cnt); p->im_offset32 = p->im_crc + p->obj_cnt; p->im_offset64 = p->im_offset32 + p->obj_cnt; return GIT_SUCCESS; @@ -900,7 +900,7 @@ static int scan_one_pack(void *state, char *name) return 0; } -static git_packlist* scan_packs(git_odb *db) +static git_packlist *scan_packs(git_odb *db) { char pb[GIT_PATH_MAX]; struct scanned_pack *state = NULL, *c; @@ -974,7 +974,7 @@ static int search_packs(git_pack **p, off_t *offset, git_odb *db, const git_oid pack_decidx(pack); if (!res) { - packlist_dec(db,pl); + packlist_dec(db, pl); if (p) *p = pack; if (offset) @@ -984,7 +984,7 @@ static int search_packs(git_pack **p, off_t *offset, git_odb *db, const git_oid } - packlist_dec(db,pl); + packlist_dec(db, pl); return GIT_ENOTFOUND; } diff --git a/src/util.h b/src/util.h index 3f541ffa6..4195117c1 100644 --- a/src/util.h +++ b/src/util.h @@ -58,6 +58,6 @@ GIT_INLINE(int) git__is_sizet(off_t p) alloc = alloc_nr(alloc); \ x = xrealloc((x), alloc * sizeof(*(x))); \ } \ - } while(0) + } while (0) #endif /* INCLUDE_util_h__ */ diff --git a/tests/t0020-dirent.c b/tests/t0020-dirent.c index 399b7d5ee..2e6776cae 100644 --- a/tests/t0020-dirent.c +++ b/tests/t0020-dirent.c @@ -123,9 +123,9 @@ BEGIN_TEST(dot) must_pass(setup(&dot)); must_pass(gitfo_dirent(path_buffer, - sizeof(path_buffer), - one_entry, - &dot)); + sizeof(path_buffer), + one_entry, + &dot)); must_pass(check_counts(&dot)); @@ -148,9 +148,9 @@ BEGIN_TEST(sub) must_pass(setup(&sub)); must_pass(gitfo_dirent(path_buffer, - sizeof(path_buffer), - one_entry, - &sub)); + sizeof(path_buffer), + one_entry, + &sub)); must_pass(check_counts(&sub)); @@ -167,9 +167,9 @@ BEGIN_TEST(sub_slash) must_pass(setup(&sub_slash)); must_pass(gitfo_dirent(path_buffer, - sizeof(path_buffer), - one_entry, - &sub_slash)); + sizeof(path_buffer), + one_entry, + &sub_slash)); must_pass(check_counts(&sub_slash)); @@ -196,17 +196,17 @@ BEGIN_TEST(empty) must_pass(setup(&empty)); must_pass(gitfo_dirent(path_buffer, - sizeof(path_buffer), - one_entry, - &empty)); + sizeof(path_buffer), + one_entry, + &empty)); must_pass(check_counts(&empty)); /* make sure callback not called */ must_pass(gitfo_dirent(path_buffer, - sizeof(path_buffer), - dont_call_me, - &empty)); + sizeof(path_buffer), + dont_call_me, + &empty)); must_pass(knockdown(&empty)); END_TEST @@ -229,9 +229,9 @@ BEGIN_TEST(odd) must_pass(setup(&odd)); must_pass(gitfo_dirent(path_buffer, - sizeof(path_buffer), - one_entry, - &odd)); + sizeof(path_buffer), + one_entry, + &odd)); must_pass(check_counts(&odd)); diff --git a/tests/t0101-oid.c b/tests/t0101-oid.c index 16ba02bda..c867e4ff4 100644 --- a/tests/t0101-oid.c +++ b/tests/t0101-oid.c @@ -50,7 +50,7 @@ BEGIN_TEST(invalid_string_all_chars) test_die("line %d: must accept '%s'", __LINE__, in); if (memcmp(out.id, exp, sizeof(out.id))) test_die("line %d: bad parse of '%s', %x != %x", - __LINE__, in, exp[19], out.id[19]); + __LINE__, in, exp[19], out.id[19]); } else if (!git_oid_mkstr(&out, in)) test_die("line %d: must not accept '%s'", __LINE__, in); } diff --git a/tests/t0102-objtype.c b/tests/t0102-objtype.c index 425b3cd58..b42f3f731 100644 --- a/tests/t0102-objtype.c +++ b/tests/t0102-objtype.c @@ -3,19 +3,19 @@ #include BEGIN_TEST(type_to_string) - must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_BAD),"")); - must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ__EXT1),"")); - must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_COMMIT),"commit")); - must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_TREE),"tree")); - must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_BLOB),"blob")); - must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_TAG),"tag")); - must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ__EXT2),"")); - must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_OFS_DELTA),"OFS_DELTA")); - must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_REF_DELTA),"REF_DELTA")); + must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_BAD), "")); + must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ__EXT1), "")); + must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_COMMIT), "commit")); + must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_TREE), "tree")); + must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_BLOB), "blob")); + must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_TAG), "tag")); + must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ__EXT2), "")); + must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_OFS_DELTA), "OFS_DELTA")); + must_be_true(!strcmp(git_obj_type_to_string(GIT_OBJ_REF_DELTA), "REF_DELTA")); - must_be_true(!strcmp(git_obj_type_to_string(-2),"")); - must_be_true(!strcmp(git_obj_type_to_string(8),"")); - must_be_true(!strcmp(git_obj_type_to_string(1234),"")); + must_be_true(!strcmp(git_obj_type_to_string(-2), "")); + must_be_true(!strcmp(git_obj_type_to_string(8), "")); + must_be_true(!strcmp(git_obj_type_to_string(1234), "")); END_TEST BEGIN_TEST(string_to_type) diff --git a/tests/t0201-existsloose.c b/tests/t0201-existsloose.c index 76f293894..0c7fda8e4 100644 --- a/tests/t0201-existsloose.c +++ b/tests/t0201-existsloose.c @@ -37,8 +37,8 @@ BEGIN_TEST(exists_loose_one) must_be_true(git_odb_exists(db, &id)); /* Test for a non-existant object */ - must_pass(git_oid_mkstr(&id2,"8b137891791fe96927ad78e64b0aad7bded08baa")); - must_be_true(0 == git_odb_exists(db, &id2)); + must_pass(git_oid_mkstr(&id2, "8b137891791fe96927ad78e64b0aad7bded08baa")); + must_be_true(0 == git_odb_exists(db, &id2)); git_odb_close(db); must_pass(remove_object_files(odb_dir, &one)); diff --git a/tests/t0301-write.c b/tests/t0301-write.c index f161ce12c..b4440c0be 100644 --- a/tests/t0301-write.c +++ b/tests/t0301-write.c @@ -351,55 +351,54 @@ static git_obj some_obj = { static int make_odb_dir(void) { - if (gitfo_mkdir(odb_dir, 0755) < 0) { - if (errno == EEXIST) { - fprintf(stderr, "odb directory \"%s\" already exists!\n", odb_dir); - return -1; - } - fprintf(stderr, "can't make odb directory \"%s\"\n", odb_dir); - return -1; - } - - return 0; + if (gitfo_mkdir(odb_dir, 0755) < 0) { + int err = errno; + fprintf(stderr, "can't make directory \"%s\"", odb_dir); + if (err == EEXIST) + fprintf(stderr, " (already exists)"); + fprintf(stderr, "\n"); + return -1; + } + return 0; } static int remove_object_files(object_data *d) { - if (gitfo_unlink(d->file) < 0) { - fprintf(stderr, "can't delete object file \"%s\"\n", d->file); - return -1; - } - if ((gitfo_rmdir(d->dir) < 0) && (errno != ENOTEMPTY)) { - fprintf(stderr, "can't remove object directory \"%s\"\n", d->dir); - return -1; - } + if (gitfo_unlink(d->file) < 0) { + fprintf(stderr, "can't delete object file \"%s\"\n", d->file); + return -1; + } + if ((gitfo_rmdir(d->dir) < 0) && (errno != ENOTEMPTY)) { + fprintf(stderr, "can't remove directory \"%s\"\n", d->dir); + return -1; + } - if (gitfo_rmdir(odb_dir) < 0) { - fprintf(stderr, "can't remove odb directory \"%s\"\n", odb_dir); - return -1; - } + if (gitfo_rmdir(odb_dir) < 0) { + fprintf(stderr, "can't remove directory \"%s\"\n", odb_dir); + return -1; + } - return 0; + return 0; } static int check_object_files(object_data *d) { - if (gitfo_exists(d->dir) < 0) - return -1; - if (gitfo_exists(d->file) < 0) - return -1; - return 0; + if (gitfo_exists(d->dir) < 0) + return -1; + if (gitfo_exists(d->file) < 0) + return -1; + return 0; } static int cmp_objects(git_obj *o1, git_obj *o2) { - if (o1->type != o2->type) - return -1; - if (o1->len != o2->len) - return -1; - if ((o1->len > 0) && (memcmp(o1->data, o2->data, o1->len) != 0)) - return -1; - return 0; + if (o1->type != o2->type) + return -1; + if (o1->len != o2->len) + return -1; + if ((o1->len > 0) && (memcmp(o1->data, o2->data, o1->len) != 0)) + return -1; + return 0; } BEGIN_TEST(write_commit) diff --git a/tests/test_helpers.c b/tests/test_helpers.c index 6829e2c49..46a29b40d 100644 --- a/tests/test_helpers.c +++ b/tests/test_helpers.c @@ -29,66 +29,66 @@ int write_object_data(char *file, void *data, size_t len) { - git_file fd; - int ret; + git_file fd; + int ret; - if ((fd = gitfo_creat(file, S_IREAD | S_IWRITE)) < 0) - return -1; - ret = gitfo_write(fd, data, len); - gitfo_close(fd); + if ((fd = gitfo_creat(file, S_IREAD | S_IWRITE)) < 0) + return -1; + ret = gitfo_write(fd, data, len); + gitfo_close(fd); - return ret; + return ret; } int write_object_files(const char *odb_dir, object_data *d) { - if (gitfo_mkdir(odb_dir, 0755) < 0) { - if (errno == EEXIST) { - fprintf(stderr, "odb directory \"%s\" already exists!\n", odb_dir); - return -1; - } - fprintf(stderr, "can't make odb directory \"%s\"\n", odb_dir); - return -1; - } + if (gitfo_mkdir(odb_dir, 0755) < 0) { + int err = errno; + fprintf(stderr, "can't make directory \"%s\"", odb_dir); + if (err == EEXIST) + fprintf(stderr, " (already exists)"); + fprintf(stderr, "\n"); + return -1; + } - if ((gitfo_mkdir(d->dir, 0755) < 0) && (errno != EEXIST)) { - fprintf(stderr, "can't make object directory \"%s\"\n", d->dir); - return -1; - } - if (write_object_data(d->file, d->bytes, d->blen) < 0) { - fprintf(stderr, "can't write object file \"%s\"\n", d->file); - return -1; - } + if ((gitfo_mkdir(d->dir, 0755) < 0) && (errno != EEXIST)) { + fprintf(stderr, "can't make object directory \"%s\"\n", d->dir); + return -1; + } + if (write_object_data(d->file, d->bytes, d->blen) < 0) { + fprintf(stderr, "can't write object file \"%s\"\n", d->file); + return -1; + } - return 0; + return 0; } int remove_object_files(const char *odb_dir, object_data *d) { - if (gitfo_unlink(d->file) < 0) { - fprintf(stderr, "can't delete object file \"%s\"\n", d->file); - return -1; - } - if ((gitfo_rmdir(d->dir) < 0) && (errno != ENOTEMPTY)) { - fprintf(stderr, "can't remove object directory \"%s\"\n", d->dir); - return -1; - } + if (gitfo_unlink(d->file) < 0) { + fprintf(stderr, "can't delete object file \"%s\"\n", d->file); + return -1; + } + if ((gitfo_rmdir(d->dir) < 0) && (errno != ENOTEMPTY)) { + fprintf(stderr, "can't remove object directory \"%s\"\n", d->dir); + return -1; + } - if (gitfo_rmdir(odb_dir) < 0) { - fprintf(stderr, "can't remove odb directory \"%s\"\n", odb_dir); - return -1; - } + if (gitfo_rmdir(odb_dir) < 0) { + fprintf(stderr, "can't remove directory \"%s\"\n", odb_dir); + return -1; + } - return 0; + return 0; } int cmp_objects(git_obj *o, object_data *d) { - if (o->type != git_obj_string_to_type(d->type)) - return -1; - if (o->len != d->dlen) - return -1; - if ((o->len > 0) && (memcmp(o->data, d->data, o->len) != 0)) - return -1; - return 0; + if (o->type != git_obj_string_to_type(d->type)) + return -1; + if (o->len != d->dlen) + return -1; + if ((o->len > 0) && (memcmp(o->data, d->data, o->len) != 0)) + return -1; + return 0; } diff --git a/tests/test_lib.c b/tests/test_lib.c index 9475785cf..1ce3f92bf 100644 --- a/tests/test_lib.c +++ b/tests/test_lib.c @@ -26,8 +26,7 @@ #define GIT__NO_HIDE_MALLOC #include "test_lib.h" -struct test_info -{ +struct test_info { struct test_info *next; const char *test_name; const char *file_name; @@ -40,9 +39,9 @@ static struct test_info *current_test; static void show_test_result(const char *status) { fprintf(stderr, "* %-6s %5d: %s\n", - status, - current_test->line_no, - current_test->test_name); + status, + current_test->line_no, + current_test->test_name); } void test_die(const char *fmt, ...) diff --git a/tests/test_lib.h b/tests/test_lib.h index f863bba4d..78f992332 100644 --- a/tests/test_lib.h +++ b/tests/test_lib.h @@ -45,7 +45,7 @@ * @param name C symbol to assign to this test's function. */ #define BEGIN_TEST(name) \ - void testfunc__##name (void) \ + void testfunc__##name(void) \ { \ test_begin(#name, __FILE__, __LINE__); \ { From 56931d1ab4de660b27c56ce488245e78f8c713c3 Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Fri, 19 Feb 2010 20:07:03 +0000 Subject: [PATCH 2/8] Makefile: Add support for custom build options in config.mak file Signed-off-by: Ramsay Jones --- .gitignore | 1 + Makefile | 2 ++ tests/Makefile | 2 ++ 3 files changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 5c7507cc2..0c3aa3474 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /apidocs /trash-*.exe /libgit2.pc +/config.mak *.o *.a *.exe diff --git a/Makefile b/Makefile index a5ab36d1d..ad7cf03cc 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,8 @@ ifneq (,$(findstring MINGW,$(uname_S))) SPARSE_FLAGS=-Wno-one-bit-signed-bitfield endif +-include config.mak + SRC_C = $(wildcard src/*.c) OS_SRC = $(wildcard src/$(OS)/*.c) SRC_C += $(OS_SRC) diff --git a/tests/Makefile b/tests/Makefile index 487addc85..beaa5abd5 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -41,6 +41,8 @@ ifneq (,$(findstring MINGW,$(uname_S))) EXTRA_LIBS += -lwsock32 -lpthread endif +-include ../config.mak + GIT_LIB = ../libgit2.a HDRS = $(wildcard ../src/*.h) From e8cc449fe9c99f9ca35088e3247ab9c0088081fe Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Fri, 19 Feb 2010 21:49:22 +0000 Subject: [PATCH 3/8] win32: Add separate MinGW and MSVC compatability header files Signed-off-by: Ramsay Jones --- src/common.h | 43 ++----------------------------------------- src/mingw-compat.h | 14 ++++++++++++++ src/msvc-compat.h | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 41 deletions(-) create mode 100644 src/mingw-compat.h create mode 100644 src/msvc-compat.h diff --git a/src/common.h b/src/common.h index 29a61a7f8..18c321ca3 100644 --- a/src/common.h +++ b/src/common.h @@ -32,43 +32,13 @@ # include # include # include +# include "msvc-compat.h" +# include "mingw-compat.h" # define snprintf _snprintf -# if defined(__DMC__) -# if defined(_M_AMD64) -# define SSIZE_T long long -# else -# define SSIZE_T int -# endif -# endif - typedef SSIZE_T ssize_t; -# if defined(_MSC_VER) -/* access() mode parameter #defines */ -# define F_OK 0 /* existence check */ -# define W_OK 2 /* write mode check */ -# define R_OK 4 /* read mode check */ -# endif - -#if defined(__MINGW32__) - -# define off_t off64_t -# define lseek _lseeki64 -# define stat _stati64 -# define fstat _fstati64 - -#elif defined(_MSC_VER) - -typedef __int64 off64_t; -# define off_t off64_t -# define lseek _lseeki64 -# define stat _stat64 -# define fstat _fstat64 - -#endif - #else # include @@ -83,13 +53,4 @@ typedef __int64 off64_t; #define GIT_PATH_MAX 4096 -#ifndef GIT_HAVE_INTTYPES_H -/* add some missing typedef's */ -typedef long int32_t; -typedef unsigned long uint32_t; - -typedef long long int64_t; -typedef unsigned long long uint64_t; -#endif - #endif /* INCLUDE_common_h__ */ diff --git a/src/mingw-compat.h b/src/mingw-compat.h new file mode 100644 index 000000000..e3805dff2 --- /dev/null +++ b/src/mingw-compat.h @@ -0,0 +1,14 @@ +#ifndef INCLUDE_mingw_compat__ +#define INCLUDE_mingw_compat__ + +#if defined(__MINGW32__) + +/* use a 64-bit file offset type */ +# define off_t off64_t +# define lseek _lseeki64 +# define stat _stati64 +# define fstat _fstati64 + +#endif + +#endif /* INCLUDE_mingw_compat__ */ diff --git a/src/msvc-compat.h b/src/msvc-compat.h new file mode 100644 index 000000000..62ab0af99 --- /dev/null +++ b/src/msvc-compat.h @@ -0,0 +1,41 @@ +#ifndef INCLUDE_msvc_compat__ +#define INCLUDE_msvc_compat__ + +#if defined(_MSC_VER) + +/* access() mode parameter #defines */ +# define F_OK 0 /* existence check */ +# define W_OK 2 /* write mode check */ +# define R_OK 4 /* read mode check */ + +/* use a 64-bit file offset type */ +typedef __int64 off64_t; +# define off_t off64_t +# define lseek _lseeki64 +# define stat _stat64 +# define fstat _fstat64 + +/* stat: file mode type testing macros */ +# define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) +# define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) +# define S_ISFIFO(m) (((m) & _S_IFMT) == _S_IFIFO) + +/* add some missing typedef's */ +typedef signed char int8_t; +typedef unsigned char uint8_t; + +typedef short int16_t; +typedef unsigned short uint16_t; + +typedef long int32_t; +typedef unsigned long uint32_t; + +typedef long long int64_t; +typedef unsigned long long uint64_t; + +typedef long long intmax_t; +typedef unsigned long long uintmax_t; + +#endif + +#endif /* INCLUDE_msvc_compat__ */ From 255a0dabb28beb56096af18dc20187deca4a545c Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Fri, 19 Feb 2010 22:36:31 +0000 Subject: [PATCH 4/8] Add a minimum size check when opening an v2 pack index file Signed-off-by: Ramsay Jones --- src/odb.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/odb.c b/src/odb.c index 0985c00bc..5e95e5342 100644 --- a/src/odb.c +++ b/src/odb.c @@ -746,6 +746,7 @@ static int pack_openidx_v2(git_pack *p) unsigned char *data = p->idx_map.data; uint32_t *src_fanout = (uint32_t *)(data + 8); uint32_t *im_fanout; + size_t sz; int j; if ((im_fanout = git__malloc(sizeof(*im_fanout) * 256)) == NULL) @@ -761,6 +762,13 @@ static int pack_openidx_v2(git_pack *p) } p->obj_cnt = im_fanout[255]; + /* minimum size of .idx file (with empty 64-bit offsets table): */ + sz = 4 + 4 + 256 * 4 + p->obj_cnt * (20 + 4 + 4) + 2 * 20; + if (p->idx_map.len < sz) { + free(im_fanout); + return GIT_ERROR; + } + p->idx_search = idxv2_search; p->im_fanout = im_fanout; p->im_oid = (unsigned char *)(src_fanout + 256); From 238e54bcfff45d477a17cc5a0f51f8ee4bc68bad Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Sun, 21 Feb 2010 15:34:53 +0000 Subject: [PATCH 5/8] Add an 64-bit offset table index bounds check for v2 pack index Signed-off-by: Ramsay Jones --- src/odb.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/odb.c b/src/odb.c index 5e95e5342..47015c6bb 100644 --- a/src/odb.c +++ b/src/odb.c @@ -746,8 +746,8 @@ static int pack_openidx_v2(git_pack *p) unsigned char *data = p->idx_map.data; uint32_t *src_fanout = (uint32_t *)(data + 8); uint32_t *im_fanout; - size_t sz; - int j; + size_t sz, o64_sz, o64_len; + uint32_t j; if ((im_fanout = git__malloc(sizeof(*im_fanout) * 256)) == NULL) return GIT_ERROR; @@ -775,6 +775,21 @@ static int pack_openidx_v2(git_pack *p) p->im_crc = (uint32_t *)(p->im_oid + 20 * p->obj_cnt); p->im_offset32 = p->im_crc + p->obj_cnt; p->im_offset64 = p->im_offset32 + p->obj_cnt; + + /* check 64-bit offset table index values are within bounds */ + o64_sz = p->idx_map.len - sz; + o64_len = o64_sz / 8; + for (j = 0; j < p->obj_cnt; j++) { + uint32_t o32 = decode32(p->im_offset32 + j); + if (o32 & 0x80000000) { + uint32_t o64_idx = (o32 & ~0x80000000); + if (o64_idx >= o64_len) { + free(im_fanout); + return GIT_ERROR; + } + } + } + return GIT_SUCCESS; } From abf5681c033e83f92198fdce8d30c799a6e42af4 Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Fri, 26 Feb 2010 19:29:54 +0000 Subject: [PATCH 6/8] Change the interface of the pack index search function In particular, on a successful search, we now return the index entry number of the object rather than the '.pack' file offset. Signed-off-by: Ramsay Jones --- src/odb.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/odb.c b/src/odb.c index 47015c6bb..87a63e99a 100644 --- a/src/odb.c +++ b/src/odb.c @@ -37,7 +37,7 @@ struct git_pack { /** Functions to access idx_map. */ int (*idx_search)( - off_t *, + uint32_t *, struct git_pack *, const git_oid *); @@ -663,20 +663,20 @@ static int pack_openidx_map(git_pack *p) return GIT_SUCCESS; } -static int idxv1_search(off_t *out, git_pack *p, const git_oid *id) +static int idxv1_search(uint32_t *out, git_pack *p, const git_oid *id) { unsigned char *data = p->im_oid; - size_t lo = id->id[0] ? p->im_fanout[id->id[0] - 1] : 0; - size_t hi = p->im_fanout[id->id[0]]; + uint32_t lo = id->id[0] ? p->im_fanout[id->id[0] - 1] : 0; + uint32_t hi = p->im_fanout[id->id[0]]; do { - size_t mid = (lo + hi) >> 1; - size_t pos = 24 * mid; + uint32_t mid = (lo + hi) >> 1; + uint32_t pos = 24 * mid; int cmp = memcmp(id->id, data + pos + 4, 20); if (cmp < 0) hi = mid; else if (!cmp) { - *out = decode32(data + pos); + *out = mid; return GIT_SUCCESS; } else lo = mid + 1; @@ -716,24 +716,20 @@ static int pack_openidx_v1(git_pack *p) return GIT_SUCCESS; } -static int idxv2_search(off_t *out, git_pack *p, const git_oid *id) +static int idxv2_search(uint32_t *out, git_pack *p, const git_oid *id) { unsigned char *data = p->im_oid; - size_t lo = id->id[0] ? p->im_fanout[id->id[0] - 1] : 0; - size_t hi = p->im_fanout[id->id[0]]; + uint32_t lo = id->id[0] ? p->im_fanout[id->id[0] - 1] : 0; + uint32_t hi = p->im_fanout[id->id[0]]; do { - size_t mid = (lo + hi) >> 1; - size_t pos = 20 * mid; + uint32_t mid = (lo + hi) >> 1; + uint32_t pos = 20 * mid; int cmp = memcmp(id->id, data + pos, 20); if (cmp < 0) hi = mid; else if (!cmp) { - uint32_t o32 = decode32(p->im_offset32 + mid); - if (o32 & 0x80000000) - *out = decode64(p->im_offset64 + 2*(o32 & ~0x80000000)); - else - *out = o32; + *out = mid; return GIT_SUCCESS; } else lo = mid + 1; @@ -977,7 +973,7 @@ static git_packlist *packlist_get(git_odb *db) return pl; } -static int search_packs(git_pack **p, off_t *offset, git_odb *db, const git_oid *id) +static int search_packs(git_pack **p, uint32_t *n, git_odb *db, const git_oid *id) { git_packlist *pl = packlist_get(db); size_t j; @@ -988,7 +984,7 @@ static int search_packs(git_pack **p, off_t *offset, git_odb *db, const git_oid for (j = 0; j < pl->n_packs; j++) { git_pack *pack = pl->packs[j]; - off_t pos; + uint32_t pos; int res; if (pack_openidx(pack)) @@ -1000,8 +996,8 @@ static int search_packs(git_pack **p, off_t *offset, git_odb *db, const git_oid packlist_dec(db, pl); if (p) *p = pack; - if (offset) - *offset = pos; + if (n) + *n = pos; return GIT_SUCCESS; } @@ -1132,18 +1128,18 @@ int git_odb__read_loose(git_obj *out, git_odb *db, const git_oid *id) static int read_packed(git_obj *out, git_pack *p, const git_oid *id) { - off_t pos; + uint32_t n; int res; assert(out && p && id); if (pack_openidx(p)) return GIT_ERROR; - res = p->idx_search(&pos, p, id); + res = p->idx_search(&n, p, id); pack_decidx(p); if (!res) { - /* TODO unpack object at pos */ + /* TODO unpack object */ res = GIT_ERROR; } From 608d33fa676aab1ed350312cc07e02cd7f94847d Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Fri, 26 Feb 2010 19:59:06 +0000 Subject: [PATCH 7/8] Add a pack index 'virtual function' to search by file offset In addition to searching the index by oid, we need to search by '.pack' file offset, particularly when processing OBJ_OFS_DELTA objects. Since the v1 and v2 file formats differ in the layout of the object records, we provide two implementations of the search function and initialise the (virtual) function pointer appropriately. Note that, as part of the creation of the 'offset index', we also add a check that the offset data in the index is within the bounds of the '.pack' file. Having sorted the file offsets, while creating the index, we only need to check the smallest and largest values. The offset index consists of the im_off_idx array, which contains the index entry numbers sorted into file offset order, and the im_off_next mapping array. The im_off_next array maps an index entry number to the 'next' index entry in file offset order. Signed-off-by: Ramsay Jones --- src/odb.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 213 insertions(+), 27 deletions(-) diff --git a/src/odb.c b/src/odb.c index 87a63e99a..803022317 100644 --- a/src/odb.c +++ b/src/odb.c @@ -40,6 +40,10 @@ struct git_pack { uint32_t *, struct git_pack *, const git_oid *); + int (*idx_search_offset)( + uint32_t *, + struct git_pack *, + off_t); /** The .idx file, mapped into memory. */ git_file idx_fd; @@ -49,10 +53,18 @@ struct git_pack { uint32_t *im_crc; uint32_t *im_offset32; uint32_t *im_offset64; + uint32_t *im_off_idx; + uint32_t *im_off_next; /** Number of objects in this pack. */ uint32_t obj_cnt; + /** The size of the .pack file. */ + off_t pack_size; + + /** The mtime of the .pack file. */ + time_t pack_mtime; + /** Number of git_packlist we appear in. */ unsigned int refcnt; @@ -663,6 +675,51 @@ static int pack_openidx_map(git_pack *p) return GIT_SUCCESS; } +typedef struct { + off_t offset; + uint32_t n; +} offset_idx_info; + +static int cmp_offset_idx_info(const void *lhs, const void *rhs) +{ + const offset_idx_info *a = lhs; + const offset_idx_info *b = rhs; + return (a->offset < b->offset) ? -1 : (a->offset > b->offset) ? 1 : 0; +} + +static int make_offset_index(git_pack *p, offset_idx_info *data) +{ + off_t min_off = 3 * 4, max_off = p->pack_size - GIT_OID_RAWSZ; + uint32_t *idx, *next; + uint32_t j; + + qsort(data, p->obj_cnt, sizeof(*data), cmp_offset_idx_info); + + if (data[0].offset < min_off || data[p->obj_cnt].offset > max_off) + return GIT_ERROR; + + if ((idx = git__malloc(sizeof(*idx) * (p->obj_cnt+1))) == NULL) + return GIT_ERROR; + if ((next = git__malloc(sizeof(*next) * p->obj_cnt)) == NULL) { + free(idx); + return GIT_ERROR; + } + + for (j = 0; j < p->obj_cnt+1; j++) + idx[j] = data[j].n; + + for (j = 0; j < p->obj_cnt; j++) { + assert(idx[j] < p->obj_cnt); + assert(idx[j+1] < p->obj_cnt+1); + + next[idx[j]] = idx[j+1]; + } + + p->im_off_idx = idx; + p->im_off_next = next; + return GIT_SUCCESS; +} + static int idxv1_search(uint32_t *out, git_pack *p, const git_oid *id) { unsigned char *data = p->im_oid; @@ -684,12 +741,37 @@ static int idxv1_search(uint32_t *out, git_pack *p, const git_oid *id) return GIT_ENOTFOUND; } +static int idxv1_search_offset(uint32_t *out, git_pack *p, off_t offset) +{ + if (offset > 0 && offset < (p->pack_size - GIT_OID_RAWSZ)) { + uint32_t lo = 0, hi = p->obj_cnt+1; + unsigned char *data = p->im_oid; + uint32_t *idx = p->im_off_idx; + do { + uint32_t mid = (lo + hi) >> 1; + uint32_t n = idx[mid]; + uint32_t pos = n * (GIT_OID_RAWSZ + 4); + off_t here = decode32(data + pos); + if (offset < here) + hi = mid; + else if (offset == here) { + *out = n; + return GIT_SUCCESS; + } else + lo = mid + 1; + } while (lo < hi); + } + return GIT_ENOTFOUND; +} + static int pack_openidx_v1(git_pack *p) { uint32_t *src_fanout = p->idx_map.data; uint32_t *im_fanout; + offset_idx_info *info; size_t expsz; - int j; + uint32_t j; + if ((im_fanout = git__malloc(sizeof(*im_fanout) * 256)) == NULL) return GIT_ERROR; @@ -711,8 +793,30 @@ static int pack_openidx_v1(git_pack *p) } p->idx_search = idxv1_search; + p->idx_search_offset = idxv1_search_offset; p->im_fanout = im_fanout; p->im_oid = (unsigned char *)(src_fanout + 256); + + if ((info = git__malloc(sizeof(*info) * (p->obj_cnt+1))) == NULL) { + free(im_fanout); + return GIT_ERROR; + } + + for (j = 0; j < p->obj_cnt; j++) { + uint32_t pos = j * (GIT_OID_RAWSZ + 4); + info[j].offset = decode32(p->im_oid + pos); + info[j].n = j; + } + info[p->obj_cnt].offset = p->pack_size - GIT_OID_RAWSZ; + info[p->obj_cnt].n = p->obj_cnt; + + if (make_offset_index(p, info)) { + free(im_fanout); + free(info); + return GIT_ERROR; + } + free(info); + return GIT_SUCCESS; } @@ -737,11 +841,40 @@ static int idxv2_search(uint32_t *out, git_pack *p, const git_oid *id) return GIT_ENOTFOUND; } +static int idxv2_search_offset(uint32_t *out, git_pack *p, off_t offset) +{ + if (offset > 0 && offset < (p->pack_size - GIT_OID_RAWSZ)) { + uint32_t lo = 0, hi = p->obj_cnt+1; + uint32_t *idx = p->im_off_idx; + do { + uint32_t mid = (lo + hi) >> 1; + uint32_t n = idx[mid]; + uint32_t o32 = decode32(p->im_offset32 + n); + off_t here = o32; + + if (o32 & 0x80000000) { + uint32_t o64_idx = (o32 & ~0x80000000); + here = decode64(p->im_offset64 + 2*o64_idx); + } + + if (offset < here) + hi = mid; + else if (offset == here) { + *out = n; + return GIT_SUCCESS; + } else + lo = mid + 1; + } while (lo < hi); + } + return GIT_ENOTFOUND; +} + static int pack_openidx_v2(git_pack *p) { unsigned char *data = p->idx_map.data; uint32_t *src_fanout = (uint32_t *)(data + 8); uint32_t *im_fanout; + offset_idx_info *info; size_t sz, o64_sz, o64_len; uint32_t j; @@ -766,25 +899,67 @@ static int pack_openidx_v2(git_pack *p) } p->idx_search = idxv2_search; + p->idx_search_offset = idxv2_search_offset; p->im_fanout = im_fanout; p->im_oid = (unsigned char *)(src_fanout + 256); p->im_crc = (uint32_t *)(p->im_oid + 20 * p->obj_cnt); p->im_offset32 = p->im_crc + p->obj_cnt; p->im_offset64 = p->im_offset32 + p->obj_cnt; + if ((info = git__malloc(sizeof(*info) * (p->obj_cnt+1))) == NULL) { + free(im_fanout); + return GIT_ERROR; + } + /* check 64-bit offset table index values are within bounds */ o64_sz = p->idx_map.len - sz; o64_len = o64_sz / 8; for (j = 0; j < p->obj_cnt; j++) { uint32_t o32 = decode32(p->im_offset32 + j); + off_t offset = o32; if (o32 & 0x80000000) { uint32_t o64_idx = (o32 & ~0x80000000); if (o64_idx >= o64_len) { free(im_fanout); + free(info); return GIT_ERROR; } + offset = decode64(p->im_offset64 + 2*o64_idx); } + info[j].offset = offset; + info[j].n = j; } + info[p->obj_cnt].offset = p->pack_size - GIT_OID_RAWSZ; + info[p->obj_cnt].n = p->obj_cnt; + + if (make_offset_index(p, info)) { + free(im_fanout); + free(info); + return GIT_ERROR; + } + free(info); + + return GIT_SUCCESS; +} + +static int pack_stat(git_pack *p) +{ + char pb[GIT_PATH_MAX]; + struct stat sb; + + if (git__fmt(pb, sizeof(pb), "%s/pack/%s.pack", + p->db->objects_dir, + p->pack_name) < 0) + return GIT_ERROR; + + if (stat(pb, &sb) || !S_ISREG(sb.st_mode)) + return GIT_ERROR; + + if (sb.st_size < (3 * 4 + GIT_OID_RAWSZ)) + return GIT_ERROR; + + p->pack_size = sb.st_size; + p->pack_mtime = sb.st_mtime; return GIT_SUCCESS; } @@ -792,40 +967,51 @@ static int pack_openidx_v2(git_pack *p) static int pack_openidx(git_pack *p) { gitlck_lock(&p->lock); - if (p->invalid) - goto unlock_fail; + + if (p->invalid) { + gitlck_unlock(&p->lock); + return GIT_ERROR; + } + if (++p->idxcnt == 1 && !p->idx_search) { + int status, version; uint32_t *data; - if (pack_openidx_map(p)) - goto invalid_fail; + if (pack_stat(p) || pack_openidx_map(p)) { + p->invalid = 1; + p->idxcnt--; + gitlck_unlock(&p->lock); + return GIT_ERROR; + } data = p->idx_map.data; + status = GIT_SUCCESS; + version = 1; - if (decode32(&data[0]) == PACK_TOC) { - switch (decode32(&data[1])) { - case 2: - if (pack_openidx_v2(p)) - goto unmap_fail; - break; - default: - goto unmap_fail; - } - } else if (pack_openidx_v1(p)) - goto unmap_fail; + if (decode32(&data[0]) == PACK_TOC) + version = decode32(&data[1]); + + switch (version) { + case 1: + status = pack_openidx_v1(p); + break; + case 2: + status = pack_openidx_v2(p); + break; + default: + status = GIT_ERROR; + } + + if (status != GIT_SUCCESS) { + gitfo_free_map(&p->idx_map); + p->invalid = 1; + p->idxcnt--; + gitlck_unlock(&p->lock); + return status; + } } + gitlck_unlock(&p->lock); return GIT_SUCCESS; - -unmap_fail: - gitfo_free_map(&p->idx_map); - -invalid_fail: - p->invalid = 1; - p->idxcnt--; - -unlock_fail: - gitlck_unlock(&p->lock); - return GIT_ERROR; } static void pack_decidx(git_pack *p) From 2cdc4544233b503a5aff7dd1baa4ba8743fef7ab Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Fri, 26 Feb 2010 22:53:10 +0000 Subject: [PATCH 8/8] Add a pack index 'virtual function' to fetch an index entry Given an index entry number, the idx_get() function returns an (version agnostic) index_entry structure containing all of the information required to unpack the corresponding object from the '.pack' file. Since the v1 and v2 file formats differ in the layout of the object records, we provide two implementations of the get function and initialise the function pointer appropriately. Signed-off-by: Ramsay Jones --- src/odb.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/odb.c b/src/odb.c index 803022317..85a843cc1 100644 --- a/src/odb.c +++ b/src/odb.c @@ -31,6 +31,14 @@ #include "odb.h" #define GIT_PACK_NAME_MAX (5 + 40 + 1) + +typedef struct { + uint32_t n; + unsigned char *oid; + off_t offset; + off_t size; +} index_entry; + struct git_pack { git_odb *db; git_lck lock; @@ -44,6 +52,10 @@ struct git_pack { uint32_t *, struct git_pack *, off_t); + int (*idx_get)( + index_entry *, + struct git_pack *, + uint32_t n); /** The .idx file, mapped into memory. */ git_file idx_fd; @@ -764,6 +776,27 @@ static int idxv1_search_offset(uint32_t *out, git_pack *p, off_t offset) return GIT_ENOTFOUND; } +static int idxv1_get(index_entry *e, git_pack *p, uint32_t n) +{ + unsigned char *data = p->im_oid; + uint32_t *next = p->im_off_next; + + if (n < p->obj_cnt) { + uint32_t pos = n * (GIT_OID_RAWSZ + 4); + off_t next_off = p->pack_size - GIT_OID_RAWSZ; + e->n = n; + e->oid = data + pos + 4; + e->offset = decode32(data + pos); + if (next[n] < p->obj_cnt) { + pos = next[n] * (GIT_OID_RAWSZ + 4); + next_off = decode32(data + pos); + } + e->size = next_off - e->offset; + return GIT_SUCCESS; + } + return GIT_ENOTFOUND; +} + static int pack_openidx_v1(git_pack *p) { uint32_t *src_fanout = p->idx_map.data; @@ -794,6 +827,7 @@ static int pack_openidx_v1(git_pack *p) p->idx_search = idxv1_search; p->idx_search_offset = idxv1_search_offset; + p->idx_get = idxv1_get; p->im_fanout = im_fanout; p->im_oid = (unsigned char *)(src_fanout + 256); @@ -869,6 +903,35 @@ static int idxv2_search_offset(uint32_t *out, git_pack *p, off_t offset) return GIT_ENOTFOUND; } +static int idxv2_get(index_entry *e, git_pack *p, uint32_t n) +{ + unsigned char *data = p->im_oid; + uint32_t *next = p->im_off_next; + + if (n < p->obj_cnt) { + uint32_t o32 = decode32(p->im_offset32 + n); + off_t next_off = p->pack_size - GIT_OID_RAWSZ; + e->n = n; + e->oid = data + n * GIT_OID_RAWSZ; + e->offset = o32; + if (o32 & 0x80000000) { + uint32_t o64_idx = (o32 & ~0x80000000); + e->offset = decode64(p->im_offset64 + 2*o64_idx); + } + if (next[n] < p->obj_cnt) { + o32 = decode32(p->im_offset32 + next[n]); + next_off = o32; + if (o32 & 0x80000000) { + uint32_t o64_idx = (o32 & ~0x80000000); + next_off = decode64(p->im_offset64 + 2*o64_idx); + } + } + e->size = next_off - e->offset; + return GIT_SUCCESS; + } + return GIT_ENOTFOUND; +} + static int pack_openidx_v2(git_pack *p) { unsigned char *data = p->idx_map.data; @@ -900,6 +963,7 @@ static int pack_openidx_v2(git_pack *p) p->idx_search = idxv2_search; p->idx_search_offset = idxv2_search_offset; + p->idx_get = idxv2_get; p->im_fanout = im_fanout; p->im_oid = (unsigned char *)(src_fanout + 256); p->im_crc = (uint32_t *)(p->im_oid + 20 * p->obj_cnt);