diff options
Diffstat (limited to 'src/libgit2/odb_pack.c')
-rw-r--r-- | src/libgit2/odb_pack.c | 138 |
1 files changed, 95 insertions, 43 deletions
diff --git a/src/libgit2/odb_pack.c b/src/libgit2/odb_pack.c index 49a655b44..1b1d122b0 100644 --- a/src/libgit2/odb_pack.c +++ b/src/libgit2/odb_pack.c @@ -26,6 +26,7 @@ struct pack_backend { git_odb_backend parent; + git_odb_backend_pack_options opts; git_midx_file *midx; git_vector midx_packs; git_vector packs; @@ -95,24 +96,24 @@ struct pack_writepack { * -------------------------------------------------- * * # pack_backend__exists / pack_backend__exists_prefix - * | Check if the given SHA1 oid (or a SHA1 oid prefix) exists in any of the + * | Check if the given oid (or an oid prefix) exists in any of the * | packs that have been loaded for our ODB. * | * |-# pack_entry_find / pack_entry_find_prefix - * | If there is a multi-pack-index present, search the SHA1 oid in that + * | If there is a multi-pack-index present, search the oid in that * | index first. If it is not found there, iterate through all the unindexed * | packs that have been preloaded (starting by the pack where the latest * | object was found) to try to find the OID in one of them. * | * |-# git_midx_entry_find - * | Search for the SHA1 oid in the multi-pack-index. See + * | Search for the oid in the multi-pack-index. See * | <https://github.com/git/git/blob/master/Documentation/technical/pack-format.txt> * | for specifics on the multi-pack-index format and how do we find * | entries in it. * | * |-# git_pack_entry_find - * | Check the index of an individual unindexed pack to see if the SHA1 - * | OID can be found. If we can find the offset to that SHA1 inside of the + * | Check the index of an individual unindexed pack to see if the + * | OID can be found. If we can find the offset to that inside of the * | index, that means the object is contained inside of the packfile and * | we can stop searching. Before returning, we verify that the * | packfile behind the index we are searching still exists on disk. @@ -141,13 +142,13 @@ struct pack_writepack { * -------------------------------------------------- * * # pack_backend__read / pack_backend__read_prefix - * | Check if the given SHA1 oid (or a SHA1 oid prefix) exists in any of the + * | Check if the given oid (or an oid prefix) exists in any of the * | packs that have been loaded for our ODB. If it does, open the packfile and * | read from it. * | * |-# git_packfile_unpack * Armed with a packfile and the offset within it, we can finally unpack - * the object pointed at by the SHA1 oid. This involves mmapping part of + * the object pointed at by the oid. This involves mmapping part of * the `.pack` file, and uncompressing the object within it (if it is * stored in the undelfitied representation), or finding a base object and * applying some deltas to its uncompressed representation (if it is stored @@ -177,7 +178,7 @@ static int pack_entry_find(struct git_pack_entry *e, * a prefix of an identifier. * Sets GIT_EAMBIGUOUS if short oid is ambiguous. * This method assumes that len is between - * GIT_OID_MINPREFIXLEN and GIT_OID_SHA1_HEXSIZE. + * GIT_OID_MINPREFIXLEN and the hexsize for the hash type. */ static int pack_entry_find_prefix( struct git_pack_entry *e, @@ -251,7 +252,7 @@ static int packfile_load__cb(void *data, git_str *path) if (git_vector_search2(NULL, &backend->packs, packfile_byname_search_cmp, &index_prefix) == 0) return 0; - error = git_mwindow_get_pack(&pack, path->ptr); + error = git_mwindow_get_pack(&pack, path->ptr, backend->opts.oid_type); /* ignore missing .pack file as git does */ if (error == GIT_ENOTFOUND) { @@ -270,33 +271,34 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen { struct git_pack_file *last_found = backend->last_found, *p; git_midx_entry midx_entry; + size_t oid_hexsize = git_oid_hexsize(backend->opts.oid_type); size_t i; if (backend->midx && - git_midx_entry_find(&midx_entry, backend->midx, oid, GIT_OID_SHA1_HEXSIZE) == 0 && + git_midx_entry_find(&midx_entry, backend->midx, oid, oid_hexsize) == 0 && midx_entry.pack_index < git_vector_length(&backend->midx_packs)) { e->offset = midx_entry.offset; - git_oid_cpy(&e->sha1, &midx_entry.sha1); + git_oid_cpy(&e->id, &midx_entry.sha1); e->p = git_vector_get(&backend->midx_packs, midx_entry.pack_index); return 0; } if (last_found && - git_pack_entry_find(e, last_found, oid, GIT_OID_SHA1_HEXSIZE) == 0) + git_pack_entry_find(e, last_found, oid, oid_hexsize) == 0) return 0; git_vector_foreach(&backend->packs, i, p) { if (p == last_found) continue; - if (git_pack_entry_find(e, p, oid, GIT_OID_SHA1_HEXSIZE) == 0) { + if (git_pack_entry_find(e, p, oid, oid_hexsize) == 0) { backend->last_found = p; return 0; } } return git_odb__error_notfound( - "failed to find pack entry", oid, GIT_OID_SHA1_HEXSIZE); + "failed to find pack entry", oid, oid_hexsize); } static int pack_entry_find_prefix( @@ -318,9 +320,9 @@ static int pack_entry_find_prefix( return error; if (!error && midx_entry.pack_index < git_vector_length(&backend->midx_packs)) { e->offset = midx_entry.offset; - git_oid_cpy(&e->sha1, &midx_entry.sha1); + git_oid_cpy(&e->id, &midx_entry.sha1); e->p = git_vector_get(&backend->midx_packs, midx_entry.pack_index); - git_oid_cpy(&found_full_oid, &e->sha1); + git_oid_cpy(&found_full_oid, &e->id); found = true; } } @@ -330,9 +332,9 @@ static int pack_entry_find_prefix( if (error == GIT_EAMBIGUOUS) return error; if (!error) { - if (found && git_oid_cmp(&e->sha1, &found_full_oid)) + if (found && git_oid_cmp(&e->id, &found_full_oid)) return git_odb__error_ambiguous("found multiple pack entries"); - git_oid_cpy(&found_full_oid, &e->sha1); + git_oid_cpy(&found_full_oid, &e->id); found = true; } } @@ -345,9 +347,9 @@ static int pack_entry_find_prefix( if (error == GIT_EAMBIGUOUS) return error; if (!error) { - if (found && git_oid_cmp(&e->sha1, &found_full_oid)) + if (found && git_oid_cmp(&e->id, &found_full_oid)) return git_odb__error_ambiguous("found multiple pack entries"); - git_oid_cpy(&found_full_oid, &e->sha1); + git_oid_cpy(&found_full_oid, &e->id); found = true; backend->last_found = p; } @@ -425,7 +427,10 @@ static int process_multi_pack_index_pack( } /* Pack was not found. Allocate a new one. */ - error = git_mwindow_get_pack(&pack, git_str_cstr(&pack_path)); + error = git_mwindow_get_pack( + &pack, + git_str_cstr(&pack_path), + backend->opts.oid_type); git_str_dispose(&pack_path); if (error < 0) return error; @@ -596,32 +601,33 @@ static int pack_backend__read_prefix( void **buffer_p, size_t *len_p, git_object_t *type_p, - git_odb_backend *backend, + git_odb_backend *_backend, const git_oid *short_oid, size_t len) { + struct pack_backend *backend = (struct pack_backend *)_backend; int error = 0; if (len < GIT_OID_MINPREFIXLEN) error = git_odb__error_ambiguous("prefix length too short"); - else if (len >= GIT_OID_SHA1_HEXSIZE) { + else if (len >= git_oid_hexsize(backend->opts.oid_type)) { /* We can fall back to regular read method */ - error = pack_backend__read(buffer_p, len_p, type_p, backend, short_oid); + error = pack_backend__read(buffer_p, len_p, type_p, _backend, short_oid); if (!error) git_oid_cpy(out_oid, short_oid); } else { struct git_pack_entry e; git_rawobj raw = {NULL}; - if ((error = pack_entry_find_prefix( - &e, (struct pack_backend *)backend, short_oid, len)) == 0 && - (error = git_packfile_unpack(&raw, e.p, &e.offset)) == 0) + if ((error = pack_entry_find_prefix(&e, + backend, short_oid, len)) == 0 && + (error = git_packfile_unpack(&raw, e.p, &e.offset)) == 0) { *buffer_p = raw.data; *len_p = raw.len; *type_p = raw.type; - git_oid_cpy(out_oid, &e.sha1); + git_oid_cpy(out_oid, &e.id); } } @@ -642,7 +648,7 @@ static int pack_backend__exists_prefix( struct git_pack_entry e = {0}; error = pack_entry_find_prefix(&e, pb, short_id, len); - git_oid_cpy(out, &e.sha1); + git_oid_cpy(out, &e.id); return error; } @@ -712,6 +718,7 @@ static int pack_backend__writepack(struct git_odb_writepack **out, git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT; struct pack_backend *backend; struct pack_writepack *writepack; + int error; GIT_ASSERT_ARG(out); GIT_ASSERT_ARG(_backend); @@ -726,11 +733,20 @@ static int pack_backend__writepack(struct git_odb_writepack **out, writepack = git__calloc(1, sizeof(struct pack_writepack)); GIT_ERROR_CHECK_ALLOC(writepack); - if (git_indexer_new(&writepack->indexer, - backend->pack_folder, 0, odb, &opts) < 0) { - git__free(writepack); +#ifdef GIT_EXPERIMENTAL_SHA256 + opts.odb = odb; + + error = git_indexer_new(&writepack->indexer, + backend->pack_folder, + backend->opts.oid_type, + &opts); +#else + error = git_indexer_new(&writepack->indexer, + backend->pack_folder, 0, odb, &opts); +#endif + + if (error < 0) return -1; - } writepack->parent.backend = _backend; writepack->parent.append = pack_backend__writepack_append; @@ -840,7 +856,10 @@ static void pack_backend__free(git_odb_backend *_backend) git__free(backend); } -static int pack_backend__alloc(struct pack_backend **out, size_t initial_size) +static int pack_backend__alloc( + struct pack_backend **out, + size_t initial_size, + const git_odb_backend_pack_options *opts) { struct pack_backend *backend = git__calloc(1, sizeof(struct pack_backend)); GIT_ERROR_CHECK_ALLOC(backend); @@ -849,12 +868,19 @@ static int pack_backend__alloc(struct pack_backend **out, size_t initial_size) git__free(backend); return -1; } + if (git_vector_init(&backend->packs, initial_size, packfile_sort__cb) < 0) { git_vector_free(&backend->midx_packs); git__free(backend); return -1; } + if (opts) + memcpy(&backend->opts, opts, sizeof(git_odb_backend_pack_options)); + + if (!backend->opts.oid_type) + backend->opts.oid_type = GIT_OID_DEFAULT; + backend->parent.version = GIT_ODB_BACKEND_VERSION; backend->parent.read = &pack_backend__read; @@ -873,17 +899,31 @@ static int pack_backend__alloc(struct pack_backend **out, size_t initial_size) return 0; } -int git_odb_backend_one_pack(git_odb_backend **backend_out, const char *idx) +#ifdef GIT_EXPERIMENTAL_SHA256 +int git_odb_backend_one_pack( + git_odb_backend **backend_out, + const char *idx, + const git_odb_backend_pack_options *opts) +#else +int git_odb_backend_one_pack( + git_odb_backend **backend_out, + const char *idx) +#endif { struct pack_backend *backend = NULL; struct git_pack_file *packfile = NULL; - if (pack_backend__alloc(&backend, 1) < 0) +#ifndef GIT_EXPERIMENTAL_SHA256 + git_odb_backend_pack_options *opts = NULL; +#endif + + git_oid_t oid_type = opts ? opts->oid_type : 0; + + if (pack_backend__alloc(&backend, 1, opts) < 0) return -1; - if (git_mwindow_get_pack(&packfile, idx) < 0 || - git_vector_insert(&backend->packs, packfile) < 0) - { + if (git_mwindow_get_pack(&packfile, idx, oid_type) < 0 || + git_vector_insert(&backend->packs, packfile) < 0) { pack_backend__free((git_odb_backend *)backend); return -1; } @@ -892,18 +932,30 @@ int git_odb_backend_one_pack(git_odb_backend **backend_out, const char *idx) return 0; } -int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir) +#ifdef GIT_EXPERIMENTAL_SHA256 +int git_odb_backend_pack( + git_odb_backend **backend_out, + const char *objects_dir, + const git_odb_backend_pack_options *opts) +#else +int git_odb_backend_pack( + git_odb_backend **backend_out, + const char *objects_dir) +#endif { int error = 0; struct pack_backend *backend = NULL; git_str path = GIT_STR_INIT; - if (pack_backend__alloc(&backend, 8) < 0) +#ifndef GIT_EXPERIMENTAL_SHA256 + git_odb_backend_pack_options *opts = NULL; +#endif + + if (pack_backend__alloc(&backend, 8, opts) < 0) return -1; if (!(error = git_str_joinpath(&path, objects_dir, "pack")) && - git_fs_path_isdir(git_str_cstr(&path))) - { + git_fs_path_isdir(git_str_cstr(&path))) { backend->pack_folder = git_str_detach(&path); error = pack_backend__refresh((git_odb_backend *)backend); } |