Commit be484d35 by Edward Thomson

midx: support sha256

parent 87727409
...@@ -29,7 +29,11 @@ GIT_BEGIN_DECL ...@@ -29,7 +29,11 @@ GIT_BEGIN_DECL
*/ */
GIT_EXTERN(int) git_midx_writer_new( GIT_EXTERN(int) git_midx_writer_new(
git_midx_writer **out, git_midx_writer **out,
const char *pack_dir); const char *pack_dir
#ifdef GIT_EXPERIMENTAL_SHA256
, git_oid_t oid_type
#endif
);
/** /**
* Free the multi-pack-index writer and its resources. * Free the multi-pack-index writer and its resources.
......
...@@ -115,19 +115,20 @@ static int midx_parse_oid_lookup( ...@@ -115,19 +115,20 @@ static int midx_parse_oid_lookup(
struct git_midx_chunk *chunk_oid_lookup) struct git_midx_chunk *chunk_oid_lookup)
{ {
uint32_t i; uint32_t i;
unsigned char *oid, *prev_oid, zero_oid[GIT_OID_SHA1_SIZE] = {0}; unsigned char *oid, *prev_oid, zero_oid[GIT_OID_MAX_SIZE] = {0};
size_t oid_size = git_oid_size(idx->oid_type);
if (chunk_oid_lookup->offset == 0) if (chunk_oid_lookup->offset == 0)
return midx_error("missing OID Lookup chunk"); return midx_error("missing OID Lookup chunk");
if (chunk_oid_lookup->length == 0) if (chunk_oid_lookup->length == 0)
return midx_error("empty OID Lookup chunk"); return midx_error("empty OID Lookup chunk");
if (chunk_oid_lookup->length != idx->num_objects * GIT_OID_SHA1_SIZE) if (chunk_oid_lookup->length != idx->num_objects * oid_size)
return midx_error("OID Lookup chunk has wrong length"); return midx_error("OID Lookup chunk has wrong length");
idx->oid_lookup = oid = (unsigned char *)(data + chunk_oid_lookup->offset); idx->oid_lookup = oid = (unsigned char *)(data + chunk_oid_lookup->offset);
prev_oid = zero_oid; prev_oid = zero_oid;
for (i = 0; i < idx->num_objects; ++i, oid += GIT_OID_SHA1_SIZE) { for (i = 0; i < idx->num_objects; ++i, oid += oid_size) {
if (git_oid_raw_cmp(prev_oid, oid, GIT_OID_SHA1_SIZE) >= 0) if (git_oid_raw_cmp(prev_oid, oid, oid_size) >= 0)
return midx_error("OID Lookup index is non-monotonic"); return midx_error("OID Lookup index is non-monotonic");
prev_oid = oid; prev_oid = oid;
} }
...@@ -178,7 +179,7 @@ int git_midx_parse( ...@@ -178,7 +179,7 @@ int git_midx_parse(
struct git_midx_chunk *last_chunk; struct git_midx_chunk *last_chunk;
uint32_t i; uint32_t i;
off64_t last_chunk_offset, chunk_offset, trailer_offset; off64_t last_chunk_offset, chunk_offset, trailer_offset;
size_t checksum_size; size_t checksum_size, oid_size;
int error; int error;
struct git_midx_chunk chunk_packfile_names = {0}, struct git_midx_chunk chunk_packfile_names = {0},
chunk_oid_fanout = {0}, chunk_oid_fanout = {0},
...@@ -188,7 +189,9 @@ int git_midx_parse( ...@@ -188,7 +189,9 @@ int git_midx_parse(
GIT_ASSERT_ARG(idx); GIT_ASSERT_ARG(idx);
if (size < sizeof(struct git_midx_header) + GIT_OID_SHA1_SIZE) oid_size = git_oid_size(idx->oid_type);
if (size < sizeof(struct git_midx_header) + oid_size)
return midx_error("multi-pack index is too short"); return midx_error("multi-pack index is too short");
hdr = ((struct git_midx_header *)data); hdr = ((struct git_midx_header *)data);
...@@ -209,7 +212,7 @@ int git_midx_parse( ...@@ -209,7 +212,7 @@ int git_midx_parse(
sizeof(struct git_midx_header) + sizeof(struct git_midx_header) +
(1 + hdr->chunks) * 12; (1 + hdr->chunks) * 12;
checksum_size = GIT_HASH_SHA1_SIZE; checksum_size = oid_size;
trailer_offset = size - checksum_size; trailer_offset = size - checksum_size;
if (trailer_offset < last_chunk_offset) if (trailer_offset < last_chunk_offset)
...@@ -287,8 +290,9 @@ int git_midx_parse( ...@@ -287,8 +290,9 @@ int git_midx_parse(
} }
int git_midx_open( int git_midx_open(
git_midx_file **idx_out, git_midx_file **idx_out,
const char *path) const char *path,
git_oid_t oid_type)
{ {
git_midx_file *idx; git_midx_file *idx;
git_file fd = -1; git_file fd = -1;
...@@ -296,6 +300,8 @@ int git_midx_open( ...@@ -296,6 +300,8 @@ int git_midx_open(
struct stat st; struct stat st;
int error; int error;
GIT_ASSERT_ARG(idx_out && path && oid_type);
/* TODO: properly open the file without access time using O_NOATIME */ /* TODO: properly open the file without access time using O_NOATIME */
fd = git_futils_open_ro(path); fd = git_futils_open_ro(path);
if (fd < 0) if (fd < 0)
...@@ -317,6 +323,8 @@ int git_midx_open( ...@@ -317,6 +323,8 @@ int git_midx_open(
idx = git__calloc(1, sizeof(git_midx_file)); idx = git__calloc(1, sizeof(git_midx_file));
GIT_ERROR_CHECK_ALLOC(idx); GIT_ERROR_CHECK_ALLOC(idx);
idx->oid_type = oid_type;
error = git_str_sets(&idx->filename, path); error = git_str_sets(&idx->filename, path);
if (error < 0) if (error < 0)
return error; return error;
...@@ -344,7 +352,7 @@ bool git_midx_needs_refresh( ...@@ -344,7 +352,7 @@ bool git_midx_needs_refresh(
git_file fd = -1; git_file fd = -1;
struct stat st; struct stat st;
ssize_t bytes_read; ssize_t bytes_read;
unsigned char checksum[GIT_HASH_SHA1_SIZE]; unsigned char checksum[GIT_HASH_MAX_SIZE];
size_t checksum_size; size_t checksum_size;
/* TODO: properly open the file without access time using O_NOATIME */ /* TODO: properly open the file without access time using O_NOATIME */
...@@ -364,8 +372,8 @@ bool git_midx_needs_refresh( ...@@ -364,8 +372,8 @@ bool git_midx_needs_refresh(
return true; return true;
} }
checksum_size = GIT_HASH_SHA1_SIZE; checksum_size = git_oid_size(idx->oid_type);
bytes_read = p_pread(fd, checksum, checksum_size, st.st_size - GIT_OID_SHA1_SIZE); bytes_read = p_pread(fd, checksum, checksum_size, st.st_size - checksum_size);
p_close(fd); p_close(fd);
if (bytes_read != (ssize_t)checksum_size) if (bytes_read != (ssize_t)checksum_size)
...@@ -381,7 +389,7 @@ int git_midx_entry_find( ...@@ -381,7 +389,7 @@ int git_midx_entry_find(
size_t len) size_t len)
{ {
int pos, found = 0; int pos, found = 0;
size_t pack_index; size_t pack_index, oid_size, oid_hexsize;
uint32_t hi, lo; uint32_t hi, lo;
unsigned char *current = NULL; unsigned char *current = NULL;
const unsigned char *object_offset; const unsigned char *object_offset;
...@@ -389,30 +397,33 @@ int git_midx_entry_find( ...@@ -389,30 +397,33 @@ int git_midx_entry_find(
GIT_ASSERT_ARG(idx); GIT_ASSERT_ARG(idx);
oid_size = git_oid_size(idx->oid_type);
oid_hexsize = git_oid_hexsize(idx->oid_type);
hi = ntohl(idx->oid_fanout[(int)short_oid->id[0]]); hi = ntohl(idx->oid_fanout[(int)short_oid->id[0]]);
lo = ((short_oid->id[0] == 0x0) ? 0 : ntohl(idx->oid_fanout[(int)short_oid->id[0] - 1])); lo = ((short_oid->id[0] == 0x0) ? 0 : ntohl(idx->oid_fanout[(int)short_oid->id[0] - 1]));
pos = git_pack__lookup_id(idx->oid_lookup, GIT_OID_SHA1_SIZE, lo, hi, short_oid->id, GIT_OID_SHA1); pos = git_pack__lookup_id(idx->oid_lookup, oid_size, lo, hi, short_oid->id, idx->oid_type);
if (pos >= 0) { if (pos >= 0) {
/* An object matching exactly the oid was found */ /* An object matching exactly the oid was found */
found = 1; found = 1;
current = idx->oid_lookup + (pos * GIT_OID_SHA1_SIZE); current = idx->oid_lookup + (pos * oid_size);
} else { } else {
/* No object was found */ /* No object was found */
/* pos refers to the object with the "closest" oid to short_oid */ /* pos refers to the object with the "closest" oid to short_oid */
pos = -1 - pos; pos = -1 - pos;
if (pos < (int)idx->num_objects) { if (pos < (int)idx->num_objects) {
current = idx->oid_lookup + (pos * GIT_OID_SHA1_SIZE); current = idx->oid_lookup + (pos * oid_size);
if (!git_oid_raw_ncmp(short_oid->id, current, len)) if (!git_oid_raw_ncmp(short_oid->id, current, len))
found = 1; found = 1;
} }
} }
if (found && len != GIT_OID_SHA1_HEXSIZE && pos + 1 < (int)idx->num_objects) { if (found && len != oid_hexsize && pos + 1 < (int)idx->num_objects) {
/* Check for ambiguousity */ /* Check for ambiguousity */
const unsigned char *next = current + GIT_OID_SHA1_SIZE; const unsigned char *next = current + oid_size;
if (!git_oid_raw_ncmp(short_oid->id, next, len)) if (!git_oid_raw_ncmp(short_oid->id, next, len))
found = 2; found = 2;
...@@ -443,7 +454,7 @@ int git_midx_entry_find( ...@@ -443,7 +454,7 @@ int git_midx_entry_find(
return midx_error("invalid index into the packfile names table"); return midx_error("invalid index into the packfile names table");
e->pack_index = pack_index; e->pack_index = pack_index;
e->offset = offset; e->offset = offset;
git_oid__fromraw(&e->sha1, current, GIT_OID_SHA1); git_oid__fromraw(&e->sha1, current, idx->oid_type);
return 0; return 0;
} }
...@@ -453,13 +464,15 @@ int git_midx_foreach_entry( ...@@ -453,13 +464,15 @@ int git_midx_foreach_entry(
void *data) void *data)
{ {
git_oid oid; git_oid oid;
size_t i; size_t oid_size, i;
int error; int error;
GIT_ASSERT_ARG(idx); GIT_ASSERT_ARG(idx);
oid_size = git_oid_size(idx->oid_type);
for (i = 0; i < idx->num_objects; ++i) { for (i = 0; i < idx->num_objects; ++i) {
if ((error = git_oid__fromraw(&oid, &idx->oid_lookup[i * GIT_OID_SHA1_SIZE], GIT_OID_SHA1)) < 0) if ((error = git_oid__fromraw(&oid, &idx->oid_lookup[i * oid_size], idx->oid_type)) < 0)
return error; return error;
if ((error = cb(&oid, data)) != 0) if ((error = cb(&oid, data)) != 0)
...@@ -501,9 +514,21 @@ static int packfile__cmp(const void *a_, const void *b_) ...@@ -501,9 +514,21 @@ static int packfile__cmp(const void *a_, const void *b_)
int git_midx_writer_new( int git_midx_writer_new(
git_midx_writer **out, git_midx_writer **out,
const char *pack_dir) const char *pack_dir
#ifdef GIT_EXPERIMENTAL_SHA256
, git_oid_t oid_type
#endif
)
{ {
git_midx_writer *w = git__calloc(1, sizeof(git_midx_writer)); git_midx_writer *w;
#ifndef GIT_EXPERIMENTAL_SHA256
git_oid_t oid_type = GIT_OID_SHA1;
#endif
GIT_ASSERT_ARG(out && pack_dir && oid_type);
w = git__calloc(1, sizeof(git_midx_writer));
GIT_ERROR_CHECK_ALLOC(w); GIT_ERROR_CHECK_ALLOC(w);
if (git_str_sets(&w->pack_dir, pack_dir) < 0) { if (git_str_sets(&w->pack_dir, pack_dir) < 0) {
...@@ -518,6 +543,8 @@ int git_midx_writer_new( ...@@ -518,6 +543,8 @@ int git_midx_writer_new(
return -1; return -1;
} }
w->oid_type = oid_type;
*out = w; *out = w;
return 0; return 0;
} }
...@@ -662,12 +689,13 @@ static int midx_write( ...@@ -662,12 +689,13 @@ static int midx_write(
oid_lookup = GIT_STR_INIT, oid_lookup = GIT_STR_INIT,
object_offsets = GIT_STR_INIT, object_offsets = GIT_STR_INIT,
object_large_offsets = GIT_STR_INIT; object_large_offsets = GIT_STR_INIT;
unsigned char checksum[GIT_HASH_SHA1_SIZE]; unsigned char checksum[GIT_HASH_MAX_SIZE];
size_t checksum_size; size_t checksum_size, oid_size;
git_midx_entry *entry; git_midx_entry *entry;
object_entry_array_t object_entries_array = GIT_ARRAY_INIT; object_entry_array_t object_entries_array = GIT_ARRAY_INIT;
git_vector object_entries = GIT_VECTOR_INIT; git_vector object_entries = GIT_VECTOR_INIT;
git_hash_ctx ctx; git_hash_ctx ctx;
git_hash_algorithm_t checksum_type;
struct midx_write_hash_context hash_cb_data = {0}; struct midx_write_hash_context hash_cb_data = {0};
hdr.signature = htonl(MIDX_SIGNATURE); hdr.signature = htonl(MIDX_SIGNATURE);
...@@ -679,10 +707,14 @@ static int midx_write( ...@@ -679,10 +707,14 @@ static int midx_write(
hash_cb_data.cb_data = cb_data; hash_cb_data.cb_data = cb_data;
hash_cb_data.ctx = &ctx; hash_cb_data.ctx = &ctx;
checksum_size = GIT_HASH_SHA1_SIZE; oid_size = git_oid_size(w->oid_type);
error = git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1);
if (error < 0) GIT_ASSERT((checksum_type = git_oid_algorithm(w->oid_type)));
checksum_size = git_hash_size(checksum_type);
if ((error = git_hash_ctx_init(&ctx, checksum_type)) < 0)
return error; return error;
cb_data = &hash_cb_data; cb_data = &hash_cb_data;
write_cb = midx_write_hash; write_cb = midx_write_hash;
...@@ -749,7 +781,9 @@ static int midx_write( ...@@ -749,7 +781,9 @@ static int midx_write(
/* Fill the OID Lookup table. */ /* Fill the OID Lookup table. */
git_vector_foreach (&object_entries, i, entry) { git_vector_foreach (&object_entries, i, entry) {
error = git_str_put(&oid_lookup, (char *)&entry->sha1.id, GIT_OID_SHA1_SIZE); error = git_str_put(&oid_lookup,
(char *)&entry->sha1.id, oid_size);
if (error < 0) if (error < 0)
goto cleanup; goto cleanup;
} }
......
...@@ -51,8 +51,14 @@ typedef struct git_midx_file { ...@@ -51,8 +51,14 @@ typedef struct git_midx_file {
/* The number of entries in the Object Large Offsets table. Each entry has an 8-byte with an offset */ /* The number of entries in the Object Large Offsets table. Each entry has an 8-byte with an offset */
size_t num_object_large_offsets; size_t num_object_large_offsets;
/* The trailer of the file. Contains the SHA1-checksum of the whole file. */ /*
unsigned char checksum[GIT_HASH_SHA1_SIZE]; * The trailer of the file. Contains the checksum of the whole
* file, in the repository's object format hash.
*/
unsigned char checksum[GIT_HASH_MAX_SIZE];
/* The type of object IDs in the midx. */
git_oid_t oid_type;
/* something like ".git/objects/pack/multi-pack-index". */ /* something like ".git/objects/pack/multi-pack-index". */
git_str filename; git_str filename;
...@@ -82,11 +88,15 @@ struct git_midx_writer { ...@@ -82,11 +88,15 @@ struct git_midx_writer {
/* The list of `git_pack_file`s. */ /* The list of `git_pack_file`s. */
git_vector packs; git_vector packs;
/* The object ID type of the writer. */
git_oid_t oid_type;
}; };
int git_midx_open( int git_midx_open(
git_midx_file **idx_out, git_midx_file **idx_out,
const char *path); const char *path,
git_oid_t oid_type);
bool git_midx_needs_refresh( bool git_midx_needs_refresh(
const git_midx_file *idx, const git_midx_file *idx,
const char *path); const char *path);
......
...@@ -479,7 +479,9 @@ static int refresh_multi_pack_index(struct pack_backend *backend) ...@@ -479,7 +479,9 @@ static int refresh_multi_pack_index(struct pack_backend *backend)
} }
} }
error = git_midx_open(&backend->midx, git_str_cstr(&midx_path)); error = git_midx_open(&backend->midx, git_str_cstr(&midx_path),
backend->opts.oid_type);
git_str_dispose(&midx_path); git_str_dispose(&midx_path);
if (error < 0) if (error < 0)
return error; return error;
...@@ -798,7 +800,12 @@ static int pack_backend__writemidx(git_odb_backend *_backend) ...@@ -798,7 +800,12 @@ static int pack_backend__writemidx(git_odb_backend *_backend)
backend = (struct pack_backend *)_backend; backend = (struct pack_backend *)_backend;
error = git_midx_writer_new(&w, backend->pack_folder); error = git_midx_writer_new(&w, backend->pack_folder
#ifdef GIT_EXPERIMENTAL_SHA256
, backend->opts.oid_type
#endif
);
if (error < 0) if (error < 0)
return error; return error;
......
...@@ -16,7 +16,7 @@ void test_pack_midx__parse(void) ...@@ -16,7 +16,7 @@ void test_pack_midx__parse(void)
cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
cl_git_pass(git_str_joinpath(&midx_path, git_repository_path(repo), "objects/pack/multi-pack-index")); cl_git_pass(git_str_joinpath(&midx_path, git_repository_path(repo), "objects/pack/multi-pack-index"));
cl_git_pass(git_midx_open(&idx, git_str_cstr(&midx_path))); cl_git_pass(git_midx_open(&idx, git_str_cstr(&midx_path), GIT_OID_SHA1));
cl_assert_equal_i(git_midx_needs_refresh(idx, git_str_cstr(&midx_path)), 0); cl_assert_equal_i(git_midx_needs_refresh(idx, git_str_cstr(&midx_path)), 0);
cl_git_pass(git_oid__fromstr(&id, "5001298e0c09ad9c34e4249bc5801c75e9754fa5", GIT_OID_SHA1)); cl_git_pass(git_oid__fromstr(&id, "5001298e0c09ad9c34e4249bc5801c75e9754fa5", GIT_OID_SHA1));
...@@ -57,7 +57,12 @@ void test_pack_midx__writer(void) ...@@ -57,7 +57,12 @@ void test_pack_midx__writer(void)
cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
cl_git_pass(git_str_joinpath(&path, git_repository_path(repo), "objects/pack")); cl_git_pass(git_str_joinpath(&path, git_repository_path(repo), "objects/pack"));
#ifdef GIT_EXPERIMENTAL_SHA256
cl_git_pass(git_midx_writer_new(&w, git_str_cstr(&path), GIT_OID_SHA1));
#else
cl_git_pass(git_midx_writer_new(&w, git_str_cstr(&path))); cl_git_pass(git_midx_writer_new(&w, git_str_cstr(&path)));
#endif
cl_git_pass(git_midx_writer_add(w, "pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx")); cl_git_pass(git_midx_writer_add(w, "pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx"));
cl_git_pass(git_midx_writer_add(w, "pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx")); cl_git_pass(git_midx_writer_add(w, "pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx"));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment