summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cli/cmd_hash_object.c32
-rw-r--r--src/libgit2/blob.c6
-rw-r--r--src/libgit2/blob.h4
-rw-r--r--src/libgit2/commit.c57
-rw-r--r--src/libgit2/commit.h32
-rw-r--r--src/libgit2/commit_list.c6
-rw-r--r--src/libgit2/indexer.c79
-rw-r--r--src/libgit2/object.c45
-rw-r--r--src/libgit2/object.h3
-rw-r--r--src/libgit2/odb_pack.c18
-rw-r--r--src/libgit2/pack-objects.c13
-rw-r--r--src/libgit2/repository.c5
-rw-r--r--src/libgit2/tag.c25
-rw-r--r--src/libgit2/tag.h4
-rw-r--r--src/libgit2/tree.c38
-rw-r--r--src/libgit2/tree.h4
16 files changed, 261 insertions, 110 deletions
diff --git a/src/cli/cmd_hash_object.c b/src/cli/cmd_hash_object.c
index a64db8823..93b980d66 100644
--- a/src/cli/cmd_hash_object.c
+++ b/src/cli/cmd_hash_object.c
@@ -49,26 +49,37 @@ static void print_help(void)
cli_opt_help_fprint(stdout, opts);
}
-static int hash_buf(git_odb *odb, git_str *buf, git_object_t type)
+static int hash_buf(
+ git_odb *odb,
+ git_str *buf,
+ git_object_t object_type,
+ git_oid_t oid_type)
{
git_oid oid;
if (!literally) {
int valid = 0;
- if (git_object_rawcontent_is_valid(&valid, buf->ptr, buf->size, type) < 0 || !valid)
+#ifdef GIT_EXPERIMENTAL_SHA256
+ if (git_object_rawcontent_is_valid(&valid, buf->ptr, buf->size, object_type, oid_type) < 0 || !valid)
+ return cli_error_git();
+#else
+ GIT_UNUSED(oid_type);
+
+ if (git_object_rawcontent_is_valid(&valid, buf->ptr, buf->size, object_type) < 0 || !valid)
return cli_error_git();
+#endif
}
if (write_object) {
- if (git_odb_write(&oid, odb, buf->ptr, buf->size, type) < 0)
+ if (git_odb_write(&oid, odb, buf->ptr, buf->size, object_type) < 0)
return cli_error_git();
} else {
#ifdef GIT_EXPERIMENTAL_SHA256
- if (git_odb_hash(&oid, buf->ptr, buf->size, type, GIT_OID_SHA1) < 0)
+ if (git_odb_hash(&oid, buf->ptr, buf->size, object_type, GIT_OID_SHA1) < 0)
return cli_error_git();
#else
- if (git_odb_hash(&oid, buf->ptr, buf->size, type) < 0)
+ if (git_odb_hash(&oid, buf->ptr, buf->size, object_type) < 0)
return cli_error_git();
#endif
}
@@ -83,9 +94,10 @@ int cmd_hash_object(int argc, char **argv)
{
git_repository *repo = NULL;
git_odb *odb = NULL;
+ git_oid_t oid_type;
git_str buf = GIT_STR_INIT;
cli_opt invalid_opt;
- git_object_t type = GIT_OBJECT_BLOB;
+ git_object_t object_type = GIT_OBJECT_BLOB;
char **filename;
int ret = 0;
@@ -97,7 +109,7 @@ int cmd_hash_object(int argc, char **argv)
return 0;
}
- if (type_name && (type = git_object_string2type(type_name)) == GIT_OBJECT_INVALID)
+ if (type_name && (object_type = git_object_string2type(type_name)) == GIT_OBJECT_INVALID)
return cli_error_usage("invalid object type '%s'", type_name);
if (write_object &&
@@ -107,6 +119,8 @@ int cmd_hash_object(int argc, char **argv)
goto done;
}
+ oid_type = git_repository_oid_type(repo);
+
/*
* TODO: we're reading blobs, we shouldn't pull them all into main
* memory, we should just stream them into the odb instead.
@@ -118,7 +132,7 @@ int cmd_hash_object(int argc, char **argv)
goto done;
}
- if ((ret = hash_buf(odb, &buf, type)) != 0)
+ if ((ret = hash_buf(odb, &buf, object_type, oid_type)) != 0)
goto done;
} else {
for (filename = filenames; *filename; filename++) {
@@ -127,7 +141,7 @@ int cmd_hash_object(int argc, char **argv)
goto done;
}
- if ((ret = hash_buf(odb, &buf, type)) != 0)
+ if ((ret = hash_buf(odb, &buf, object_type, oid_type)) != 0)
goto done;
}
}
diff --git a/src/libgit2/blob.c b/src/libgit2/blob.c
index b1680d3a8..5cfd7474b 100644
--- a/src/libgit2/blob.c
+++ b/src/libgit2/blob.c
@@ -52,11 +52,12 @@ void git_blob__free(void *_blob)
git__free(blob);
}
-int git_blob__parse_raw(void *_blob, const char *data, size_t size)
+int git_blob__parse_raw(void *_blob, const char *data, size_t size, git_oid_t oid_type)
{
git_blob *blob = (git_blob *) _blob;
GIT_ASSERT_ARG(blob);
+ GIT_UNUSED(oid_type);
blob->raw = 1;
blob->data.raw.data = data;
@@ -64,11 +65,12 @@ int git_blob__parse_raw(void *_blob, const char *data, size_t size)
return 0;
}
-int git_blob__parse(void *_blob, git_odb_object *odb_obj)
+int git_blob__parse(void *_blob, git_odb_object *odb_obj, git_oid_t oid_type)
{
git_blob *blob = (git_blob *) _blob;
GIT_ASSERT_ARG(blob);
+ GIT_UNUSED(oid_type);
git_cached_obj_incref((git_cached_obj *)odb_obj);
blob->raw = 0;
diff --git a/src/libgit2/blob.h b/src/libgit2/blob.h
index 9a5dda225..d6c9dd99b 100644
--- a/src/libgit2/blob.h
+++ b/src/libgit2/blob.h
@@ -36,8 +36,8 @@ struct git_blob {
} while(0)
void git_blob__free(void *blob);
-int git_blob__parse(void *blob, git_odb_object *obj);
-int git_blob__parse_raw(void *blob, const char *data, size_t size);
+int git_blob__parse(void *blob, git_odb_object *obj, git_oid_t oid_type);
+int git_blob__parse_raw(void *blob, const char *data, size_t size, git_oid_t oid_type);
int git_blob__getbuf(git_str *buffer, git_blob *blob);
extern int git_blob__create_from_paths(
diff --git a/src/libgit2/commit.c b/src/libgit2/commit.c
index 114ae6fc9..d85fefb3d 100644
--- a/src/libgit2/commit.c
+++ b/src/libgit2/commit.c
@@ -390,7 +390,11 @@ int git_commit_amend(
return error;
}
-static int commit_parse(git_commit *commit, const char *data, size_t size, unsigned int flags)
+static int commit_parse(
+ git_commit *commit,
+ const char *data,
+ size_t size,
+ git_commit__parse_options *opts)
{
const char *buffer_start = data, *buffer;
const char *buffer_end = buffer_start + size;
@@ -401,6 +405,7 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
GIT_ASSERT_ARG(commit);
GIT_ASSERT_ARG(data);
+ GIT_ASSERT_ARG(opts);
buffer = buffer_start;
@@ -409,13 +414,14 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
GIT_ERROR_CHECK_ARRAY(commit->parent_ids);
/* The tree is always the first field */
- if (!(flags & GIT_COMMIT_PARSE_QUICK)) {
+ if (!(opts->flags & GIT_COMMIT_PARSE_QUICK)) {
if (git_object__parse_oid_header(&commit->tree_id,
&buffer, buffer_end, "tree ",
- GIT_OID_SHA1) < 0)
+ opts->oid_type) < 0)
goto bad_buffer;
} else {
- size_t tree_len = strlen("tree ") + GIT_OID_SHA1_HEXSIZE + 1;
+ size_t tree_len = strlen("tree ") + git_oid_hexsize(opts->oid_type) + 1;
+
if (buffer + tree_len > buffer_end)
goto bad_buffer;
buffer += tree_len;
@@ -427,14 +433,14 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
while (git_object__parse_oid_header(&parent_id,
&buffer, buffer_end, "parent ",
- GIT_OID_SHA1) == 0) {
+ opts->oid_type) == 0) {
git_oid *new_id = git_array_alloc(commit->parent_ids);
GIT_ERROR_CHECK_ALLOC(new_id);
git_oid_cpy(new_id, &parent_id);
}
- if (!(flags & GIT_COMMIT_PARSE_QUICK)) {
+ if (!opts || !(opts->flags & GIT_COMMIT_PARSE_QUICK)) {
commit->author = git__malloc(sizeof(git_signature));
GIT_ERROR_CHECK_ALLOC(commit->author);
@@ -458,7 +464,7 @@ static int commit_parse(git_commit *commit, const char *data, size_t size, unsig
if ((error = git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n')) < 0)
return error;
- if (flags & GIT_COMMIT_PARSE_QUICK)
+ if (opts && opts->flags & GIT_COMMIT_PARSE_QUICK)
return 0;
/* Parse add'l header entries */
@@ -503,19 +509,39 @@ bad_buffer:
return GIT_EINVALID;
}
-int git_commit__parse_raw(void *commit, const char *data, size_t size)
+int git_commit__parse(
+ void *commit,
+ git_odb_object *odb_obj,
+ git_oid_t oid_type)
{
- return commit_parse(commit, data, size, 0);
+ git_commit__parse_options parse_options = {0};
+ parse_options.oid_type = oid_type;
+
+ return git_commit__parse_ext(commit, odb_obj, &parse_options);
}
-int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags)
+int git_commit__parse_raw(
+ void *commit,
+ const char *data,
+ size_t size,
+ git_oid_t oid_type)
{
- return commit_parse(commit, git_odb_object_data(odb_obj), git_odb_object_size(odb_obj), flags);
+ git_commit__parse_options parse_options = {0};
+ parse_options.oid_type = oid_type;
+
+ return commit_parse(commit, data, size, &parse_options);
}
-int git_commit__parse(void *_commit, git_odb_object *odb_obj)
+int git_commit__parse_ext(
+ git_commit *commit,
+ git_odb_object *odb_obj,
+ git_commit__parse_options *parse_opts)
{
- return git_commit__parse_ext(_commit, odb_obj, 0);
+ return commit_parse(
+ commit,
+ git_odb_object_data(odb_obj),
+ git_odb_object_size(odb_obj),
+ parse_opts);
}
#define GIT_COMMIT_GETTER(_rvalue, _name, _return, _invalid) \
@@ -985,11 +1011,14 @@ int git_commit_create_with_signature(
git_str commit = GIT_STR_INIT;
git_commit *parsed;
git_array_oid_t parents = GIT_ARRAY_INIT;
+ git_commit__parse_options parse_opts = {0};
+
+ parse_opts.oid_type = repo->oid_type;
/* The first step is to verify that all the tree and parents exist */
parsed = git__calloc(1, sizeof(git_commit));
GIT_ERROR_CHECK_ALLOC(parsed);
- if (commit_parse(parsed, commit_content, strlen(commit_content), 0) < 0) {
+ if (commit_parse(parsed, commit_content, strlen(commit_content), &parse_opts) < 0) {
error = -1;
goto cleanup;
}
diff --git a/src/libgit2/commit.h b/src/libgit2/commit.h
index 7a2454e61..c25fee327 100644
--- a/src/libgit2/commit.h
+++ b/src/libgit2/commit.h
@@ -33,6 +33,16 @@ struct git_commit {
char *body;
};
+typedef struct {
+ git_oid_t oid_type;
+ unsigned int flags;
+} git_commit__parse_options;
+
+typedef enum {
+ /** Only parse parents and committer info */
+ GIT_COMMIT_PARSE_QUICK = (1 << 0)
+} git_commit__parse_flags;
+
int git_commit__header_field(
git_str *out,
const git_commit *commit,
@@ -56,14 +66,22 @@ int git_commit__create_buffer(
size_t parent_count,
const git_commit *parents[]);
-void git_commit__free(void *commit);
-int git_commit__parse(void *commit, git_odb_object *obj);
-int git_commit__parse_raw(void *commit, const char *data, size_t size);
+int git_commit__parse(
+ void *commit,
+ git_odb_object *obj,
+ git_oid_t oid_type);
-typedef enum {
- GIT_COMMIT_PARSE_QUICK = (1 << 0) /**< Only parse parents and committer info */
-} git_commit__parse_flags;
+int git_commit__parse_raw(
+ void *commit,
+ const char *data,
+ size_t size,
+ git_oid_t oid_type);
-int git_commit__parse_ext(git_commit *commit, git_odb_object *odb_obj, unsigned int flags);
+int git_commit__parse_ext(
+ git_commit *commit,
+ git_odb_object *odb_obj,
+ git_commit__parse_options *parse_opts);
+
+void git_commit__free(void *commit);
#endif
diff --git a/src/libgit2/commit_list.c b/src/libgit2/commit_list.c
index 511d7291f..12b329b25 100644
--- a/src/libgit2/commit_list.c
+++ b/src/libgit2/commit_list.c
@@ -124,13 +124,17 @@ static int commit_quick_parse(
{
git_oid *parent_oid;
git_commit *commit;
+ git_commit__parse_options parse_opts = {
+ GIT_OID_SHA1,
+ GIT_COMMIT_PARSE_QUICK
+ };
size_t i;
commit = git__calloc(1, sizeof(*commit));
GIT_ERROR_CHECK_ALLOC(commit);
commit->object.repo = walk->repo;
- if (git_commit__parse_ext(commit, obj, GIT_COMMIT_PARSE_QUICK) < 0) {
+ if (git_commit__parse_ext(commit, obj, &parse_opts) < 0) {
git__free(commit);
return -1;
}
diff --git a/src/libgit2/indexer.c b/src/libgit2/indexer.c
index 98408646a..dfc326e02 100644
--- a/src/libgit2/indexer.c
+++ b/src/libgit2/indexer.c
@@ -42,6 +42,7 @@ struct git_indexer {
have_delta :1,
do_fsync :1,
do_verify :1;
+ git_oid_t oid_type;
struct git_pack_header hdr;
struct git_pack_file *pack;
unsigned int mode;
@@ -68,7 +69,7 @@ struct git_indexer {
git_odb *odb;
/* Fields for calculating the packfile trailer (hash of everything before it) */
- char inbuf[GIT_OID_SHA1_SIZE];
+ char inbuf[GIT_OID_MAX_SIZE];
size_t inbuf_len;
git_hash_ctx trailer;
};
@@ -136,12 +137,13 @@ int git_indexer_init_options(git_indexer_options *opts, unsigned int version)
}
#endif
-int git_indexer_new(
- git_indexer **out,
- const char *prefix,
- unsigned int mode,
- git_odb *odb,
- git_indexer_options *in_opts)
+static int indexer_new(
+ git_indexer **out,
+ const char *prefix,
+ git_oid_t oid_type,
+ unsigned int mode,
+ git_odb *odb,
+ git_indexer_options *in_opts)
{
git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT;
git_indexer *idx;
@@ -154,6 +156,7 @@ int git_indexer_new(
idx = git__calloc(1, sizeof(git_indexer));
GIT_ERROR_CHECK_ALLOC(idx);
+ idx->oid_type = oid_type;
idx->odb = odb;
idx->progress_cb = opts.progress_cb;
idx->progress_payload = opts.progress_cb_payload;
@@ -209,6 +212,33 @@ cleanup:
return -1;
}
+#ifdef GIT_EXPERIMENTAL_SHA256
+int git_indexer_new(
+ git_indexer **out,
+ const char *prefix,
+ git_oid_t oid_type,
+ git_indexer_options *opts)
+{
+ return indexer_new(
+ out,
+ prefix,
+ oid_type,
+ opts ? opts->mode : 0,
+ opts ? opts->odb : NULL,
+ opts);
+}
+#else
+int git_indexer_new(
+ git_indexer **out,
+ const char *prefix,
+ unsigned int mode,
+ git_odb *odb,
+ git_indexer_options *opts)
+{
+ return indexer_new(out, prefix, GIT_OID_SHA1, mode, odb, opts);
+}
+#endif
+
void git_indexer__set_fsync(git_indexer *idx, int do_fsync)
{
idx->do_fsync = !!do_fsync;
@@ -273,7 +303,7 @@ static int advance_delta_offset(git_indexer *idx, git_object_t type)
GIT_ASSERT_ARG(type == GIT_OBJECT_REF_DELTA || type == GIT_OBJECT_OFS_DELTA);
if (type == GIT_OBJECT_REF_DELTA) {
- idx->off += GIT_OID_SHA1_SIZE;
+ idx->off += git_oid_size(idx->oid_type);
} else {
off64_t base_off;
int error = get_delta_base(&base_off, idx->pack, &w, &idx->off, type, idx->entry_start);
@@ -357,7 +387,7 @@ static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj)
obj->type != GIT_OBJECT_TAG)
return 0;
- if (git_object__from_raw(&object, obj->data, obj->len, obj->type) < 0) {
+ if (git_object__from_raw(&object, obj->data, obj->len, obj->type, idx->oid_type) < 0) {
/*
* parse_raw returns EINVALID on invalid data; downgrade
* that to a normal -1 error code.
@@ -447,7 +477,7 @@ static int store_object(git_indexer *idx)
}
#ifdef GIT_EXPERIMENTAL_SHA256
- oid.type = GIT_OID_SHA1;
+ oid.type = idx->oid_type;
#endif
entry_size = idx->off - entry_start;
@@ -550,7 +580,7 @@ static int hash_and_save(git_indexer *idx, git_rawobj *obj, off64_t entry_start)
entry = git__calloc(1, sizeof(*entry));
GIT_ERROR_CHECK_ALLOC(entry);
- if (git_odb__hashobj(&oid, obj, GIT_OID_SHA1) < 0) {
+ if (git_odb__hashobj(&oid, obj, idx->oid_type) < 0) {
git_error_set(GIT_ERROR_INDEXER, "failed to hash object");
goto on_error;
}
@@ -588,30 +618,31 @@ static int do_progress_callback(git_indexer *idx, git_indexer_progress *stats)
static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size)
{
size_t to_expell, to_keep;
+ size_t oid_size = git_oid_size(idx->oid_type);
if (size == 0)
return;
/* Easy case, dump the buffer and the data minus the last 20 bytes */
- if (size >= GIT_OID_SHA1_SIZE) {
+ if (size >= oid_size) {
git_hash_update(&idx->trailer, idx->inbuf, idx->inbuf_len);
- git_hash_update(&idx->trailer, data, size - GIT_OID_SHA1_SIZE);
+ git_hash_update(&idx->trailer, data, size - oid_size);
- data += size - GIT_OID_SHA1_SIZE;
- memcpy(idx->inbuf, data, GIT_OID_SHA1_SIZE);
- idx->inbuf_len = GIT_OID_SHA1_SIZE;
+ data += size - oid_size;
+ memcpy(idx->inbuf, data, oid_size);
+ idx->inbuf_len = oid_size;
return;
}
/* We can just append */
- if (idx->inbuf_len + size <= GIT_OID_SHA1_SIZE) {
+ if (idx->inbuf_len + size <= oid_size) {
memcpy(idx->inbuf + idx->inbuf_len, data, size);
idx->inbuf_len += size;
return;
}
/* We need to partially drain the buffer and then append */
- to_keep = GIT_OID_SHA1_SIZE - size;
+ to_keep = oid_size - size;
to_expell = idx->inbuf_len - to_keep;
git_hash_update(&idx->trailer, idx->inbuf, to_expell);
@@ -906,7 +937,7 @@ static int index_path(git_str *path, git_indexer *idx, const char *suffix)
slash--;
if (git_str_grow(path, slash + 1 + strlen(prefix) +
- GIT_OID_SHA1_HEXSIZE + strlen(suffix) + 1) < 0)
+ git_oid_hexsize(idx->oid_type) + strlen(suffix) + 1) < 0)
return -1;
git_str_truncate(path, slash);
@@ -923,7 +954,7 @@ static int index_path(git_str *path, git_indexer *idx, const char *suffix)
*/
static int seek_back_trailer(git_indexer *idx)
{
- idx->pack->mwf.size -= GIT_OID_SHA1_SIZE;
+ idx->pack->mwf.size -= git_oid_size(idx->oid_type);
return git_mwindow_free_all(&idx->pack->mwf);
}
@@ -983,7 +1014,7 @@ static int inject_object(git_indexer *idx, git_oid *id)
if ((error = append_to_pack(idx, empty_checksum, checksum_size)) < 0)
goto cleanup;
- idx->pack->mwf.size += GIT_OID_SHA1_SIZE;
+ idx->pack->mwf.size += git_oid_size(idx->oid_type);
pentry = git__calloc(1, sizeof(struct git_pack_entry));
GIT_ERROR_CHECK_ALLOC(pentry);
@@ -1046,13 +1077,13 @@ static int fix_thin_pack(git_indexer *idx, git_indexer_progress *stats)
}
/* curpos now points to the base information, which is an OID */
- base_info = git_mwindow_open(&idx->pack->mwf, &w, curpos, GIT_OID_SHA1_SIZE, &left);
+ base_info = git_mwindow_open(&idx->pack->mwf, &w, curpos, git_oid_size(idx->oid_type), &left);
if (base_info == NULL) {
git_error_set(GIT_ERROR_INDEXER, "failed to map delta information");
return -1;
}
- git_oid__fromraw(&base, base_info, GIT_OID_SHA1);
+ git_oid__fromraw(&base, base_info, idx->oid_type);
git_mwindow_close(&w);
if (has_entry(idx, &base))
@@ -1275,7 +1306,7 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
/* Write out the object names (SHA-1 hashes) */
git_vector_foreach(&idx->objects, i, entry) {
- git_filebuf_write(&index_file, &entry->oid.id, GIT_OID_SHA1_SIZE);
+ git_filebuf_write(&index_file, &entry->oid.id, git_oid_size(idx->oid_type));
}
/* Write out the CRC32 values */
diff --git a/src/libgit2/object.c b/src/libgit2/object.c
index d45465678..d87d40cf1 100644
--- a/src/libgit2/object.c
+++ b/src/libgit2/object.c
@@ -27,8 +27,8 @@ typedef struct {
const char *str; /* type name string */
size_t size; /* size in bytes of the object structure */
- int (*parse)(void *self, git_odb_object *obj);
- int (*parse_raw)(void *self, const char *data, size_t size);
+ int (*parse)(void *self, git_odb_object *obj, git_oid_t oid_type);
+ int (*parse_raw)(void *self, const char *data, size_t size, git_oid_t oid_type);
void (*free)(void *self);
} git_object_def;
@@ -60,7 +60,8 @@ int git_object__from_raw(
git_object **object_out,
const char *data,
size_t size,
- git_object_t type)
+ git_object_t object_type,
+ git_oid_t oid_type)
{
git_object_def *def;
git_object *object;
@@ -71,12 +72,15 @@ int git_object__from_raw(
*object_out = NULL;
/* Validate type match */
- if (type != GIT_OBJECT_BLOB && type != GIT_OBJECT_TREE && type != GIT_OBJECT_COMMIT && type != GIT_OBJECT_TAG) {
+ if (object_type != GIT_OBJECT_BLOB &&
+ object_type != GIT_OBJECT_TREE &&
+ object_type != GIT_OBJECT_COMMIT &&
+ object_type != GIT_OBJECT_TAG) {
git_error_set(GIT_ERROR_INVALID, "the requested type is invalid");
return GIT_ENOTFOUND;
}
- if ((object_size = git_object__size(type)) == 0) {
+ if ((object_size = git_object__size(object_type)) == 0) {
git_error_set(GIT_ERROR_INVALID, "the requested type is invalid");
return GIT_ENOTFOUND;
}
@@ -85,15 +89,15 @@ int git_object__from_raw(
object = git__calloc(1, object_size);
GIT_ERROR_CHECK_ALLOC(object);
object->cached.flags = GIT_CACHE_STORE_PARSED;
- object->cached.type = type;
- if ((error = git_odb__hash(&object->cached.oid, data, size, type, GIT_OID_SHA1)) < 0)
+ object->cached.type = object_type;
+ if ((error = git_odb__hash(&object->cached.oid, data, size, object_type, oid_type)) < 0)
return error;
/* Parse raw object data */
- def = &git_objects_table[type];
+ def = &git_objects_table[object_type];
GIT_ASSERT(def->free && def->parse_raw);
- if ((error = def->parse_raw(object, data, size)) < 0) {
+ if ((error = def->parse_raw(object, data, size, oid_type)) < 0) {
def->free(object);
return error;
}
@@ -143,7 +147,7 @@ int git_object__from_odb_object(
def = &git_objects_table[odb_obj->cached.type];
GIT_ASSERT(def->free && def->parse);
- if ((error = def->parse(object, odb_obj)) < 0) {
+ if ((error = def->parse(object, odb_obj, repo->oid_type)) < 0) {
/*
* parse returns EINVALID on invalid data; downgrade
* that to a normal -1 error code.
@@ -357,12 +361,11 @@ static int dereference_object(git_object **dereferenced, git_object *obj)
static int peel_error(int error, const git_oid *oid, git_object_t type)
{
const char *type_name;
- char hex_oid[GIT_OID_SHA1_HEXSIZE + 1];
+ char hex_oid[GIT_OID_MAX_HEXSIZE + 1];
type_name = git_object_type2string(type);
- git_oid_fmt(hex_oid, oid);
- hex_oid[GIT_OID_SHA1_HEXSIZE] = '\0';
+ git_oid_nfmt(hex_oid, GIT_OID_MAX_HEXSIZE + 1, oid);
git_error_set(GIT_ERROR_OBJECT, "the git_object of id '%s' can not be "
"successfully peeled into a %s (git_object_t=%i).", hex_oid, type_name, type);
@@ -576,21 +579,29 @@ int git_object_rawcontent_is_valid(
int *valid,
const char *buf,
size_t len,
- git_object_t type)
+ git_object_t object_type
+#ifdef GIT_EXPERIMENTAL_SHA256
+ , git_oid_t oid_type
+#endif
+ )
{
git_object *obj = NULL;
int error;
+#ifndef GIT_EXPERIMENTAL_SHA256
+ git_oid_t oid_type = GIT_OID_SHA1;
+#endif
+
GIT_ASSERT_ARG(valid);
GIT_ASSERT_ARG(buf);
/* Blobs are always valid; don't bother parsing. */
- if (type == GIT_OBJECT_BLOB) {
+ if (object_type == GIT_OBJECT_BLOB) {
*valid = 1;
return 0;
}
- error = git_object__from_raw(&obj, buf, len, type);
+ error = git_object__from_raw(&obj, buf, len, object_type, oid_type);
git_object_free(obj);
if (error == 0) {
@@ -611,7 +622,7 @@ int git_object__parse_oid_header(
const char *header,
git_oid_t oid_type)
{
- const size_t sha_len = GIT_OID_SHA1_HEXSIZE;
+ const size_t sha_len = git_oid_hexsize(oid_type);
const size_t header_len = strlen(header);
const char *buffer = *buffer_out;
diff --git a/src/libgit2/object.h b/src/libgit2/object.h
index 980e8627e..a29fdfbf3 100644
--- a/src/libgit2/object.h
+++ b/src/libgit2/object.h
@@ -33,7 +33,8 @@ int git_object__from_raw(
git_object **object_out,
const char *data,
size_t size,
- git_object_t type);
+ git_object_t object_type,
+ git_oid_t oid_type);
int git_object__from_odb_object(
git_object **object_out,
diff --git a/src/libgit2/odb_pack.c b/src/libgit2/odb_pack.c
index 814c0bc75..1b1d122b0 100644
--- a/src/libgit2/odb_pack.c
+++ b/src/libgit2/odb_pack.c
@@ -718,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);
@@ -732,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;
diff --git a/src/libgit2/pack-objects.c b/src/libgit2/pack-objects.c
index 068231649..20a5dfcbd 100644
--- a/src/libgit2/pack-objects.c
+++ b/src/libgit2/pack-objects.c
@@ -1407,7 +1407,18 @@ int git_packbuilder_write(
opts.progress_cb = progress_cb;
opts.progress_cb_payload = progress_cb_payload;
- if ((error = git_indexer_new(&indexer, path, mode, pb->odb, &opts)) < 0)
+ /* TODO: SHA256 */
+
+#ifdef GIT_EXPERIMENTAL_SHA256
+ opts.mode = mode;
+ opts.odb = pb->odb;
+
+ error = git_indexer_new(&indexer, path, GIT_OID_SHA1, &opts);
+#else
+ error = git_indexer_new(&indexer, path, mode, pb->odb, &opts);
+#endif
+
+ if (error < 0)
goto cleanup;
if (!git_repository__configmap_lookup(&t, pb->repo, GIT_CONFIGMAP_FSYNCOBJECTFILES) && t)
diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c
index 043cfd1fd..2da6caf3a 100644
--- a/src/libgit2/repository.c
+++ b/src/libgit2/repository.c
@@ -1278,11 +1278,14 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
*out = git_atomic_load(repo->_odb);
if (*out == NULL) {
git_str odb_path = GIT_STR_INIT;
+ git_odb_options odb_opts = GIT_ODB_OPTIONS_INIT;
git_odb *odb;
+ odb_opts.oid_type = repo->oid_type;
+
if ((error = git_repository__item_path(&odb_path, repo,
GIT_REPOSITORY_ITEM_OBJECTS)) < 0 ||
- (error = git_odb__new(&odb, NULL)) < 0)
+ (error = git_odb__new(&odb, &odb_opts)) < 0)
return error;
GIT_REFCOUNT_OWN(odb, repo);
diff --git a/src/libgit2/tag.c b/src/libgit2/tag.c
index 0a90e393c..562ec13ea 100644
--- a/src/libgit2/tag.c
+++ b/src/libgit2/tag.c
@@ -65,7 +65,11 @@ static int tag_error(const char *str)
return GIT_EINVALID;
}
-static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
+static int tag_parse(
+ git_tag *tag,
+ const char *buffer,
+ const char *buffer_end,
+ git_oid_t oid_type)
{
static const char *tag_types[] = {
NULL, "commit\n", "tree\n", "blob\n", "tag\n"
@@ -76,7 +80,7 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
int error;
if (git_object__parse_oid_header(&tag->target,
- &buffer, buffer_end, "object ", GIT_OID_SHA1) < 0)
+ &buffer, buffer_end, "object ", oid_type) < 0)
return tag_error("object field invalid");
if (buffer + 5 >= buffer_end)
@@ -161,18 +165,25 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
return 0;
}
-int git_tag__parse_raw(void *_tag, const char *data, size_t size)
+int git_tag__parse_raw(
+ void *_tag,
+ const char *data,
+ size_t size,
+ git_oid_t oid_type)
{
- return tag_parse(_tag, data, data + size);
+ return tag_parse(_tag, data, data + size, oid_type);
}
-int git_tag__parse(void *_tag, git_odb_object *odb_obj)
+int git_tag__parse(
+ void *_tag,
+ git_odb_object *odb_obj,
+ git_oid_t oid_type)
{
git_tag *tag = _tag;
const char *buffer = git_odb_object_data(odb_obj);
const char *buffer_end = buffer + git_odb_object_size(odb_obj);
- return tag_parse(tag, buffer, buffer_end);
+ return tag_parse(tag, buffer, buffer_end, oid_type);
}
static int retrieve_tag_reference(
@@ -374,7 +385,7 @@ int git_tag_create_from_buffer(git_oid *oid, git_repository *repo, const char *b
return -1;
/* validate the buffer */
- if (tag_parse(&tag, buffer, buffer + strlen(buffer)) < 0)
+ if (tag_parse(&tag, buffer, buffer + strlen(buffer), repo->oid_type) < 0)
return -1;
/* validate the target */
diff --git a/src/libgit2/tag.h b/src/libgit2/tag.h
index 76ae1508e..fdaaa463c 100644
--- a/src/libgit2/tag.h
+++ b/src/libgit2/tag.h
@@ -25,7 +25,7 @@ struct git_tag {
};
void git_tag__free(void *tag);
-int git_tag__parse(void *tag, git_odb_object *obj);
-int git_tag__parse_raw(void *tag, const char *data, size_t size);
+int git_tag__parse(void *tag, git_odb_object *obj, git_oid_t oid_type);
+int git_tag__parse_raw(void *tag, const char *data, size_t size, git_oid_t oid_type);
#endif
diff --git a/src/libgit2/tree.c b/src/libgit2/tree.c
index 9a43d585c..9293d9422 100644
--- a/src/libgit2/tree.c
+++ b/src/libgit2/tree.c
@@ -85,11 +85,17 @@ static git_tree_entry *alloc_entry(const char *filename, size_t filename_len, co
char *filename_ptr;
size_t tree_len;
+#ifdef GIT_EXPERIMENTAL_SHA256
+ size_t oid_size = git_oid_size(id->type);
+#else
+ size_t oid_size = GIT_OID_SHA1_SIZE;
+#endif
+
TREE_ENTRY_CHECK_NAMELEN(filename_len);
if (GIT_ADD_SIZET_OVERFLOW(&tree_len, sizeof(git_tree_entry), filename_len) ||
GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, 1) ||
- GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, GIT_OID_SHA1_SIZE))
+ GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, oid_size))
return NULL;
entry = git__calloc(1, tree_len);
@@ -383,11 +389,12 @@ static int parse_mode(uint16_t *mode_out, const char *buffer, size_t buffer_len,
return 0;
}
-int git_tree__parse_raw(void *_tree, const char *data, size_t size)
+int git_tree__parse_raw(void *_tree, const char *data, size_t size, git_oid_t oid_type)
{
git_tree *tree = _tree;
const char *buffer;
const char *buffer_end;
+ const long oid_size = (long)git_oid_size(oid_type);
buffer = data;
buffer_end = buffer + size;
@@ -414,35 +421,33 @@ int git_tree__parse_raw(void *_tree, const char *data, size_t size)
if ((filename_len = nul - buffer) == 0 || filename_len > UINT16_MAX)
return tree_parse_error("failed to parse tree: can't parse filename", NULL);
- if ((buffer_end - (nul + 1)) < GIT_OID_SHA1_SIZE)
+ if ((buffer_end - (nul + 1)) < (long)oid_size)
return tree_parse_error("failed to parse tree: can't parse OID", NULL);
/* Allocate the entry */
- {
- entry = git_array_alloc(tree->entries);
- GIT_ERROR_CHECK_ALLOC(entry);
-
- entry->attr = attr;
- entry->filename_len = (uint16_t)filename_len;
- entry->filename = buffer;
- git_oid__fromraw(&entry->oid, ((unsigned char *) buffer + filename_len + 1), GIT_OID_SHA1);
- }
+ entry = git_array_alloc(tree->entries);
+ GIT_ERROR_CHECK_ALLOC(entry);
+ entry->attr = attr;
+ entry->filename_len = (uint16_t)filename_len;
+ entry->filename = buffer;
buffer += filename_len + 1;
- buffer += GIT_OID_SHA1_SIZE;
+
+ git_oid__fromraw(&entry->oid, (unsigned char *)buffer, oid_type);
+ buffer += oid_size;
}
return 0;
}
-int git_tree__parse(void *_tree, git_odb_object *odb_obj)
+int git_tree__parse(void *_tree, git_odb_object *odb_obj, git_oid_t oid_type)
{
git_tree *tree = _tree;
const char *data = git_odb_object_data(odb_obj);
size_t size = git_odb_object_size(odb_obj);
int error;
- if ((error = git_tree__parse_raw(tree, data, size)) < 0 ||
+ if ((error = git_tree__parse_raw(tree, data, size, oid_type)) < 0 ||
(error = git_odb_object_dup(&tree->odb_obj, odb_obj)) < 0)
return error;
@@ -506,6 +511,7 @@ static int git_treebuilder__write_with_buffer(
git_odb *odb;
git_tree_entry *entry;
git_vector entries = GIT_VECTOR_INIT;
+ size_t oid_size = git_oid_size(bld->repo->oid_type);
git_str_clear(buf);
@@ -529,7 +535,7 @@ static int git_treebuilder__write_with_buffer(
git_str_printf(buf, "%o ", entry->attr);
git_str_put(buf, entry->filename, entry->filename_len + 1);
- git_str_put(buf, (char *)entry->oid.id, GIT_OID_SHA1_SIZE);
+ git_str_put(buf, (char *)entry->oid.id, oid_size);
if (git_str_oom(buf)) {
error = -1;
diff --git a/src/libgit2/tree.h b/src/libgit2/tree.h
index 0dd963ff2..5088450ab 100644
--- a/src/libgit2/tree.h
+++ b/src/libgit2/tree.h
@@ -41,8 +41,8 @@ GIT_INLINE(bool) git_tree_entry__is_tree(const struct git_tree_entry *e)
}
void git_tree__free(void *tree);
-int git_tree__parse(void *tree, git_odb_object *obj);
-int git_tree__parse_raw(void *_tree, const char *data, size_t size);
+int git_tree__parse(void *tree, git_odb_object *obj, git_oid_t oid_type);
+int git_tree__parse_raw(void *_tree, const char *data, size_t size, git_oid_t oid_type);
/**
* Write a tree to the given repository