diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/cmd_hash_object.c | 32 | ||||
-rw-r--r-- | src/libgit2/blob.c | 6 | ||||
-rw-r--r-- | src/libgit2/blob.h | 4 | ||||
-rw-r--r-- | src/libgit2/commit.c | 57 | ||||
-rw-r--r-- | src/libgit2/commit.h | 32 | ||||
-rw-r--r-- | src/libgit2/commit_list.c | 6 | ||||
-rw-r--r-- | src/libgit2/indexer.c | 79 | ||||
-rw-r--r-- | src/libgit2/object.c | 45 | ||||
-rw-r--r-- | src/libgit2/object.h | 3 | ||||
-rw-r--r-- | src/libgit2/odb_pack.c | 18 | ||||
-rw-r--r-- | src/libgit2/pack-objects.c | 13 | ||||
-rw-r--r-- | src/libgit2/repository.c | 5 | ||||
-rw-r--r-- | src/libgit2/tag.c | 25 | ||||
-rw-r--r-- | src/libgit2/tag.h | 4 | ||||
-rw-r--r-- | src/libgit2/tree.c | 38 | ||||
-rw-r--r-- | src/libgit2/tree.h | 4 |
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 |