summaryrefslogtreecommitdiff
path: root/src/libgit2/odb_pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libgit2/odb_pack.c')
-rw-r--r--src/libgit2/odb_pack.c138
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);
}