diff --git a/fuzzers/packfile_fuzzer.c b/fuzzers/packfile_fuzzer.c index cc4c33ad5..f9479b25b 100644 --- a/fuzzers/packfile_fuzzer.c +++ b/fuzzers/packfile_fuzzer.c @@ -99,17 +99,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) if (git_indexer_append(indexer, data, size, &stats) < 0) goto cleanup; if (append_hash) { -#ifdef GIT_EXPERIMENTAL_SHA256 - if (git_odb_hash(&oid, data, size, GIT_OBJECT_BLOB, GIT_OID_SHA1) < 0) { + if (git_object_id_from_buffer(&oid, data, size, NULL) < 0) { fprintf(stderr, "Failed to compute the SHA1 hash\n"); abort(); } -#else - if (git_odb_hash(&oid, data, size, GIT_OBJECT_BLOB) < 0) { - fprintf(stderr, "Failed to compute the SHA1 hash\n"); - abort(); - } -#endif if (git_indexer_append(indexer, &oid.id, GIT_OID_SHA1_SIZE, &stats) < 0) { goto cleanup; diff --git a/include/git2/deprecated.h b/include/git2/deprecated.h index 930d4f7d6..b070dc5d7 100644 --- a/include/git2/deprecated.h +++ b/include/git2/deprecated.h @@ -677,6 +677,56 @@ GIT_EXTERN(int) git_object_typeisloose(git_object_t type); /**@}*/ +/** @name Deprecated Object Database Functions + * + * These functions are retained for backward compatibility. The newer + * versions of these functions should be preferred in all new code. + * + * There is no plan to remove these backward compatibility functions at + * this time. + */ +/**@{*/ + +/** + * Generate the SHA1 object ID for a given data buffer. + * + * @deprecated use `git_object_id_from_buffer` + * + * @param[out] oid the resulting object ID. + * @param data data to hash + * @param len size of the data + * @param object_type of the data to hash + * @return 0 or an error code + */ +GIT_EXTERN(int) git_odb_hash( + git_oid *oid, + const void *data, + size_t len, + git_object_t object_type); + +/** + * Read a file from disk and fill a git_oid with the object id + * that the file would have if it were written to the Object + * Database as an object of the given type (w/o applying filters). + * Similar functionality to git.git's `git hash-object` without + * the `-w` flag, however, with the --no-filters flag. + * If you need filters, see `git_repository_hashfile` or + * `git_object_id_from_file. + * + * @deprecated use `git_object_id_from_file` + * + * @param[out] oid oid structure the result is written into. + * @param path file to read and determine object id for + * @param object_type of the data to hash + * @return 0 or an error code + */ +GIT_EXTERN(int) git_odb_hashfile( + git_oid *oid, + const char *path, + git_object_t object_type); + +/**@}*/ + /** @name Deprecated Remote Functions * * These functions are retained for backward compatibility. The newer diff --git a/include/git2/object.h b/include/git2/object.h index f923f81ed..afaf37c43 100644 --- a/include/git2/object.h +++ b/include/git2/object.h @@ -11,6 +11,7 @@ #include "types.h" #include "oid.h" #include "buffer.h" +#include "filter.h" /** * @file git2/object.h @@ -225,6 +226,91 @@ GIT_EXTERN(int) git_object_peel( */ GIT_EXTERN(int) git_object_dup(git_object **dest, git_object *source); +/** + * Options for calculating object IDs from raw content. + * + * Initialize with `GIT_OBJECT_ID_OPTIONS_INIT`. Alternatively, you can + * use `git_object_id_options_init`. + */ +typedef struct { + unsigned int version; /**< version for the struct */ + + /** + * Object type of the raw content; if not specified, this + * defaults to `GIT_OBJECT_BLOB`. + */ + git_object_t object_type; + + /** + * Object ID type to generate; if not specified, this defaults + * to `GIT_OID_DEFAULT`. + */ + git_oid_t oid_type; + + /** + * Filters to mutate the raw data with; these are ignored + * unless the given raw object data is a blob. + */ + git_filter_list *filters; +} git_object_id_options; + +/** Current version for the `git_object_id_options` structure */ +#define GIT_OBJECT_ID_OPTIONS_VERSION 1 + +/** Static constructor for `object_id_options` */ +#define GIT_OBJECT_ID_OPTIONS_INIT {GIT_OBJECT_ID_OPTIONS_VERSION} + +/** + * Initialize `git_object_id_options` structure with default values. + * Equivalent to creating an instance with `GIT_WORKTREE_ADD_OPTIONS_INIT`. + * + * @param opts The `git_object_id_options` struct to initialize. + * @param version The struct version; pass `GIT_OBJECT_ID_OPTIONS_INIT`. + * @return 0 on success; -1 on failure. + */ +GIT_EXTERN(int) git_object_id_options_init(git_object_id_options *opts, + unsigned int version); + +/** + * Given the raw content of an object, determine the object ID. + * This prepends the object header to the given data, and hashes + * the results with the hash corresponding to the given oid_type. + * + * @param[out] oid_out the resulting object id + * @param buf the raw object content + * @param len the length of the given buffer + * @param opts the options for id calculation + * @return 0 on success, or an error code + */ +GIT_EXTERN(int) git_object_id_from_buffer( + git_oid *oid_out, + const void *buf, + size_t len, + const git_object_id_options *opts); + +/** + * Given an on-disk file that contains the raw content of an object, + * determine the object ID. This prepends the object header to the given + * data, and hashes the results with the hash corresponding to the given + * oid_type. + * + * Note that this does not look at attributes or do any on-disk filtering + * (like line ending translation), so when used with blobs, it may not + * match the results for adding to the repository. To compute the object + * ID for a blob with filters, use `git_repository_hashfile`. + * + * @see git_repository_hashfile + * + * @param[out] oid_out the resulting object id + * @param path the on-disk path to the raw object content + * @param opts the options for id calculation + * @return 0 on success, or an error code + */ +GIT_EXTERN(int) git_object_id_from_file( + git_oid *oid_out, + const char *path, + const git_object_id_options *opts); + #ifdef GIT_EXPERIMENTAL_SHA256 /** * Analyzes a buffer of raw object content and determines its validity. diff --git a/include/git2/odb.h b/include/git2/odb.h index e81e41c91..e01fac5d8 100644 --- a/include/git2/odb.h +++ b/include/git2/odb.h @@ -500,72 +500,6 @@ GIT_EXTERN(int) git_odb_write_pack( GIT_EXTERN(int) git_odb_write_multi_pack_index( git_odb *db); -#ifdef GIT_EXPERIMENTAL_SHA256 - -/** - * Generate the object ID (in SHA1 or SHA256 format) for a given data buffer. - * - * @param[out] oid the resulting object ID. - * @param data data to hash - * @param len size of the data - * @param object_type of the data to hash - * @param oid_type the oid type to hash to - * @return 0 or an error code - */ -GIT_EXTERN(int) git_odb_hash( - git_oid *oid, - const void *data, - size_t len, - git_object_t object_type, - git_oid_t oid_type); - -/** - * Determine the object ID of a file on disk. - * - * @param[out] oid oid structure the result is written into. - * @param path file to read and determine object id for - * @param object_type of the data to hash - * @param oid_type the oid type to hash to - * @return 0 or an error code - */ -GIT_EXTERN(int) git_odb_hashfile( - git_oid *oid, - const char *path, - git_object_t object_type, - git_oid_t oid_type); -#else - -/** - * Determine the object-ID (sha1 or sha256 hash) of a data buffer - * - * The resulting OID will be the identifier for the data buffer as if - * the data buffer it were to written to the ODB. - * - * @param[out] oid the resulting object-ID. - * @param data data to hash - * @param len size of the data - * @param object_type of the data to hash - * @return 0 or an error code - */ -GIT_EXTERN(int) git_odb_hash(git_oid *oid, const void *data, size_t len, git_object_t object_type); - -/** - * Read a file from disk and fill a git_oid with the object id - * that the file would have if it were written to the Object - * Database as an object of the given type (w/o applying filters). - * Similar functionality to git.git's `git hash-object` without - * the `-w` flag, however, with the --no-filters flag. - * If you need filters, see git_repository_hashfile. - * - * @param[out] oid oid structure the result is written into. - * @param path file to read and determine object id for - * @param object_type of the data to hash - * @return 0 or an error code - */ -GIT_EXTERN(int) git_odb_hashfile(git_oid *oid, const char *path, git_object_t object_type); - -#endif - /** * Create a copy of an odb_object * diff --git a/src/cli/cmd_hash_object.c b/src/cli/cmd_hash_object.c index 94e7eb91f..6b07416e3 100644 --- a/src/cli/cmd_hash_object.c +++ b/src/cli/cmd_hash_object.c @@ -52,6 +52,7 @@ static int hash_buf( git_object_t object_type, git_oid_t oid_type) { + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; git_oid oid; if (!literally) { @@ -72,13 +73,10 @@ static int hash_buf( 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, object_type, GIT_OID_SHA1) < 0) + id_opts.object_type = object_type; + + if (git_object_id_from_buffer(&oid, buf->ptr, buf->size, &id_opts) < 0) return cli_error_git(); -#else - if (git_odb_hash(&oid, buf->ptr, buf->size, object_type) < 0) - return cli_error_git(); -#endif } if (printf("%s\n", git_oid_tostr_s(&oid)) < 0) diff --git a/src/libgit2/diff_file.c b/src/libgit2/diff_file.c index a792834ca..d58e79460 100644 --- a/src/libgit2/diff_file.c +++ b/src/libgit2/diff_file.c @@ -138,10 +138,15 @@ int git_diff_file_content__init_from_src( const git_diff_file_content_src *src, git_diff_file *as_file) { + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; + memset(fc, 0, sizeof(*fc)); fc->repo = repo; fc->file = as_file; + id_opts.object_type = GIT_OBJECT_BLOB; + id_opts.oid_type = opts->oid_type; + if (!src->blob && !src->buf) { fc->flags |= GIT_DIFF_FLAG__NO_DATA; git_oid_clear(&fc->file->id, opts->oid_type); @@ -162,7 +167,11 @@ int git_diff_file_content__init_from_src( fc->flags |= GIT_DIFF_FLAG__FREE_BLOB; } else { int error; - if ((error = git_odb__hash(&fc->file->id, src->buf, src->buflen, GIT_OBJECT_BLOB, opts->oid_type)) < 0) + + if ((error = git_object_id_from_buffer( + &fc->file->id, + src->buf, src->buflen, + &id_opts)) < 0) return error; fc->file->size = src->buflen; fc->file->id_abbrev = (uint16_t)git_oid_hexsize(opts->oid_type); @@ -399,9 +408,13 @@ static int diff_file_content_load_workdir( git_diff_file_content *fc, git_diff_options *diff_opts) { + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; int error = 0; git_str path = GIT_STR_INIT; + id_opts.object_type = GIT_OBJECT_BLOB; + id_opts.oid_type = diff_opts->oid_type; + if (fc->file->mode == GIT_FILEMODE_COMMIT) return diff_file_content_commit_to_str(fc, true); @@ -418,9 +431,8 @@ static int diff_file_content_load_workdir( /* once data is loaded, update OID if we didn't have it previously */ if (!error && (fc->file->flags & GIT_DIFF_FLAG_VALID_ID) == 0) { - error = git_odb__hash( - &fc->file->id, fc->map.data, fc->map.len, - GIT_OBJECT_BLOB, diff_opts->oid_type); + error = git_object_id_from_buffer(&fc->file->id, + fc->map.data, fc->map.len, &id_opts); fc->file->flags |= GIT_DIFF_FLAG_VALID_ID; } diff --git a/src/libgit2/diff_generate.c b/src/libgit2/diff_generate.c index 654145e34..0236c5dc8 100644 --- a/src/libgit2/diff_generate.c +++ b/src/libgit2/diff_generate.c @@ -632,6 +632,7 @@ int git_diff__oid_for_entry( uint16_t mode, const git_oid *update_match) { + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; git_diff_generated *diff; git_str full_path = GIT_STR_INIT; git_index_entry entry = *src; @@ -643,6 +644,9 @@ int git_diff__oid_for_entry( git_oid_clear(out, diff->base.opts.oid_type); + id_opts.object_type = GIT_OBJECT_BLOB; + id_opts.oid_type = diff->base.opts.oid_type; + if (git_repository_workdir_path(&full_path, diff->base.repo, entry.path) < 0) return -1; @@ -677,8 +681,8 @@ int git_diff__oid_for_entry( git_error_clear(); } } else if (S_ISLNK(mode)) { - error = git_odb__hashlink(out, full_path.ptr, - diff->base.opts.oid_type); + error = git_object_id_from_symlink(out, full_path.ptr, + &id_opts); diff->base.perf.oid_calculations++; } else if (!git__is_sizet(entry.file_size)) { git_error_set(GIT_ERROR_NOMEMORY, "file size overflow (for 32-bits) on '%s'", @@ -689,13 +693,14 @@ int git_diff__oid_for_entry( GIT_FILTER_TO_ODB, GIT_FILTER_ALLOW_UNSAFE))) { int fd = git_futils_open_ro(full_path.ptr); - if (fd < 0) + + id_opts.filters = fl; + + if (fd < 0) { error = fd; - else { - error = git_odb__hashfd_filtered( - out, fd, (size_t)entry.file_size, - GIT_OBJECT_BLOB, diff->base.opts.oid_type, - fl); + } else { + error = git_object_id_from_fd(out, + fd, (size_t)entry.file_size, &id_opts); p_close(fd); diff->base.perf.oid_calculations++; } diff --git a/src/libgit2/indexer.c b/src/libgit2/indexer.c index ab2b3241b..b3e2509d2 100644 --- a/src/libgit2/indexer.c +++ b/src/libgit2/indexer.c @@ -597,6 +597,7 @@ static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_ent static int hash_and_save(git_indexer *idx, git_rawobj *obj, off64_t entry_start) { + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; git_oid oid; size_t entry_size; struct entry *entry; @@ -605,7 +606,10 @@ 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, idx->oid_type) < 0) { + id_opts.object_type = obj->type; + id_opts.oid_type = idx->oid_type; + + if (git_object_id_from_buffer(&oid, obj->data, obj->len, &id_opts) < 0) { git_error_set(GIT_ERROR_INDEXER, "failed to hash object"); goto on_error; } diff --git a/src/libgit2/iterator.c b/src/libgit2/iterator.c index 4eca11f7c..9fd211f25 100644 --- a/src/libgit2/iterator.c +++ b/src/libgit2/iterator.c @@ -1275,9 +1275,13 @@ static int filesystem_iterator_entry_hash( filesystem_iterator *iter, filesystem_iterator_entry *entry) { + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; git_str fullpath = GIT_STR_INIT; int error; + id_opts.object_type = GIT_OBJECT_BLOB; + id_opts.oid_type = iter->oid_type; + if (S_ISDIR(entry->st.st_mode)) { memset(&entry->id, 0, git_oid_size(iter->oid_type)); return 0; @@ -1289,7 +1293,8 @@ static int filesystem_iterator_entry_hash( if (!(error = git_str_joinpath(&fullpath, iter->root, entry->path)) && !(error = git_path_validate_str_length(iter->base.repo, &fullpath))) - error = git_odb__hashfile(&entry->id, fullpath.ptr, GIT_OBJECT_BLOB, iter->oid_type); + error = git_object_id_from_file(&entry->id, + fullpath.ptr, &id_opts); git_str_dispose(&fullpath); return error; diff --git a/src/libgit2/object.c b/src/libgit2/object.c index f20dbb6cf..75a22d0ac 100644 --- a/src/libgit2/object.c +++ b/src/libgit2/object.c @@ -56,6 +56,7 @@ int git_object__from_raw( git_object_t object_type, git_oid_t oid_type) { + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; git_object_def *def; git_object *object; size_t object_size; @@ -64,6 +65,9 @@ int git_object__from_raw( GIT_ASSERT_ARG(object_out); *object_out = NULL; + id_opts.object_type = object_type; + id_opts.oid_type = oid_type; + /* Validate type match */ if (object_type != GIT_OBJECT_BLOB && object_type != GIT_OBJECT_TREE && @@ -83,7 +87,9 @@ int git_object__from_raw( GIT_ERROR_CHECK_ALLOC(object); object->cached.flags = GIT_CACHE_STORE_PARSED; object->cached.type = object_type; - if ((error = git_odb__hash(&object->cached.oid, data, size, object_type, oid_type)) < 0) + + if ((error = git_object_id_from_buffer(&object->cached.oid, + data, size, &id_opts)) < 0) return error; /* Parse raw object data */ @@ -601,6 +607,302 @@ bool git_object__is_valid( return true; } +int git_object_id_options_init( + git_object_id_options *opts, + unsigned int version) +{ + GIT_INIT_STRUCTURE_FROM_TEMPLATE(opts, version, + git_object_id_options, GIT_OBJECT_ID_OPTIONS_INIT); + return 0; +} + +GIT_INLINE(bool) needs_filter(git_object_id_options *opts) +{ + return (opts && opts->filters && + git_filter_list_length(opts->filters) > 0 && + (!opts->object_type || opts->object_type == GIT_OBJECT_BLOB)); +} + +GIT_INLINE(int) normalize_options( + git_object_id_options *normalized, + const git_object_id_options *given_opts) +{ + normalized->object_type = (given_opts && given_opts->object_type) ? + given_opts->object_type : GIT_OBJECT_BLOB; + + normalized->oid_type = (given_opts && given_opts->oid_type) ? + given_opts->oid_type : GIT_OID_DEFAULT; + + if (!git_object_type_is_valid(normalized->object_type)) { + git_error_set(GIT_ERROR_INVALID, "invalid object type"); + return -1; + } + + if (!git_oid_type_is_valid(normalized->oid_type)) { + git_error_set(GIT_ERROR_INVALID, "unknown oid type"); + return -1; + } + + if (given_opts) + normalized->filters = given_opts->filters; + + return 0; +} + +/* Raw object ID computation (no filters applied) from a descriptor */ +static int id_from_fd( + git_oid *out, + git_file fd, + size_t size, + git_object_id_options *opts) +{ + size_t hdr_len; + char hdr[64], buffer[GIT_BUFSIZE_FILEIO]; + git_hash_ctx ctx; + git_hash_algorithm_t algorithm; + ssize_t read_len = 0; + int error = 0; + + algorithm = git_oid_algorithm(opts->oid_type); + + if ((error = git_hash_ctx_init(&ctx, algorithm)) < 0) + return error; + + if ((error = git_odb__format_object_header(&hdr_len, hdr, + sizeof(hdr), size, opts->object_type)) < 0) + goto done; + + if ((error = git_hash_update(&ctx, hdr, hdr_len)) < 0) + goto done; + + while (size > 0 && + (read_len = p_read(fd, buffer, sizeof(buffer))) > 0) { + + if ((size_t)read_len > size) { + git_error_set(GIT_ERROR_OS, "error reading file for hashing"); + error = -1; + goto done; + } + + if ((error = git_hash_update(&ctx, buffer, read_len)) < 0) + goto done; + + size -= read_len; + } + + /* If p_read returned an error code, the read obviously failed. + * If size is not zero, the file was truncated after we originally + * stat'd it, so we consider this a read failure too */ + if (read_len < 0 || size > 0) { + git_error_set(GIT_ERROR_OS, "error reading file for hashing"); + error = -1; + + goto done; + } + + error = git_hash_final(out->id, &ctx); + +#ifdef GIT_EXPERIMENTAL_SHA256 + out->type = opts->oid_type; +#endif + +done: + git_hash_ctx_cleanup(&ctx); + return error; +} + +int git_object_id_from_fd( + git_oid *id, + git_file fd, + size_t size, + git_object_id_options *given_opts) +{ + git_object_id_options opts = GIT_OBJECT_ID_OPTIONS_INIT; + git_str raw = GIT_STR_INIT; + int error; + + GIT_ASSERT_ARG(id); + + if (normalize_options(&opts, given_opts) < 0) + return -1; + + if (!needs_filter(&opts)) + return id_from_fd(id, fd, size, &opts); + + /* + * size of data is used in header, so we have to read the + * whole file into memory to apply filters before beginning + * to calculate the hash + */ + + if ((error = git_futils_readbuffer_fd(&raw, fd, size)) < 0) + goto done; + + error = git_object_id_from_buffer(id, raw.ptr, raw.size, &opts); + +done: + git_str_dispose(&raw); + return error; +} + +int git_object_id_from_symlink( + git_oid *id, + const char *path, + const git_object_id_options *given_opts) +{ + git_object_id_options opts = GIT_OBJECT_ID_OPTIONS_INIT; + struct stat st; + char *link_data; + size_t link_len; + int read_len; + int error; + + GIT_ASSERT_ARG(id); + GIT_ASSERT_ARG(path); + + if (normalize_options(&opts, given_opts) < 0) + return -1; + + opts.filters = NULL; + if (opts.object_type != GIT_OBJECT_BLOB) { + git_error_set(GIT_ERROR_INVALID, "symbolic links must be blob types"); + return -1; + } + + if (git_fs_path_lstat(path, &st) < 0) + return -1; + + /* Non-symlink fallback, primarily for non-Unix systems. */ + if (!S_ISLNK(st.st_mode)) + return git_object_id_from_file(id, path, &opts); + + if (!git__is_int(st.st_size) || (int)st.st_size < 0) { + git_error_set(GIT_ERROR_FILESYSTEM, "file size overflow for 32-bit systems"); + return -1; + } + + link_len = (size_t)st.st_size; + link_data = git__malloc(link_len + 1); + GIT_ERROR_CHECK_ALLOC(link_data); + + if ((read_len = p_readlink(path, link_data, link_len)) < 0) { + git_error_set(GIT_ERROR_OS, "failed to read symlink data for '%s'", path); + error = -1; + goto done; + } + + GIT_ASSERT(read_len <= st.st_size); + link_data[read_len] = '\0'; + + error = git_object_id_from_buffer(id, + link_data, (size_t)read_len, &opts); + +done: + git__free(link_data); + return error; +} + +int git_object_id_from_file( + git_oid *id, + const char *path, + const git_object_id_options *given_opts) +{ + git_object_id_options opts = GIT_OBJECT_ID_OPTIONS_INIT; + uint64_t size; + int fd, error = 0; + + GIT_ASSERT_ARG(id); + GIT_ASSERT_ARG(path); + + if (normalize_options(&opts, given_opts) < 0) + return -1; + + if ((fd = git_futils_open_ro(path)) < 0) + return fd; + + if ((error = git_futils_filesize(&size, fd)) < 0) + goto done; + + if (!git__is_sizet(size)) { + git_error_set(GIT_ERROR_OS, "file size overflow for 32-bit systems"); + error = -1; + goto done; + } + + error = git_object_id_from_fd(id, fd, (size_t)size, &opts); + +done: + p_close(fd); + return error; +} + +/* Raw object ID computation (no filters applied) from a buffer */ +static int id_from_buffer( + git_oid *id, + const void *data, + size_t len, + const git_object_id_options *opts) +{ + git_str_vec vec[2]; + char header[64]; + size_t hdrlen; + git_hash_algorithm_t algorithm; + int error; + + algorithm = git_oid_algorithm(opts->oid_type); + + if (!data && len != 0) { + git_error_set(GIT_ERROR_INVALID, "invalid object"); + return -1; + } + + if ((error = git_odb__format_object_header(&hdrlen, + header, sizeof(header), len, opts->object_type)) < 0) + return error; + + vec[0].data = header; + vec[0].len = hdrlen; + vec[1].data = (void *)data; + vec[1].len = len; + +#ifdef GIT_EXPERIMENTAL_SHA256 + id->type = opts->oid_type; +#endif + + return git_hash_vec(id->id, vec, 2, algorithm); +} + +int git_object_id_from_buffer( + git_oid *id, + const void *data, + size_t len, + const git_object_id_options *given_opts) +{ + git_str filtered = GIT_STR_INIT; + git_object_id_options opts = GIT_OBJECT_ID_OPTIONS_INIT; + int error = -1; + + GIT_ASSERT_ARG(id); + + if (normalize_options(&opts, given_opts) < 0) + return -1; + + if (needs_filter(&opts)) { + if (git_filter_list__apply_to_buffer(&filtered, + opts.filters, (char *)data, len) < 0) + goto done; + + data = filtered.ptr; + len = filtered.size; + } + + error = id_from_buffer(id, data, len, &opts); + +done: + git_str_dispose(&filtered); + return error; +} + int git_object_rawcontent_is_valid( int *valid, const char *buf, diff --git a/src/libgit2/object.h b/src/libgit2/object.h index b6c604c81..2a4a2154f 100644 --- a/src/libgit2/object.h +++ b/src/libgit2/object.h @@ -83,4 +83,24 @@ GIT_INLINE(git_object_t) git_object__type_from_filemode(git_filemode_t mode) } } +/** + * Calculate the object ID for an already open file descriptor. + * This is a performance call when the contents of a fd need to be hashed, + * but the fd is already open and we have the size of the contents. + * This can reduce the number of `swtat` calls. +*/ +int git_object_id_from_fd( + git_oid *id, + git_file fd, + size_t size, + git_object_id_options *opts); + +/** + * Calculate the object ID for a file that is a symbolic link. +-*/ +int git_object_id_from_symlink( + git_oid *id, + const char *path, + const git_object_id_options *opts); + #endif diff --git a/src/libgit2/odb.c b/src/libgit2/odb.c index e58f3c942..4d740cf47 100644 --- a/src/libgit2/odb.c +++ b/src/libgit2/odb.c @@ -105,49 +105,6 @@ int git_odb__format_object_header( return 0; } -int git_odb__hashobj(git_oid *id, git_rawobj *obj, git_oid_t oid_type) -{ - git_str_vec vec[2]; - char header[64]; - size_t hdrlen; - git_hash_algorithm_t algorithm; - int error; - - GIT_ASSERT_ARG(id); - GIT_ASSERT_ARG(obj); - - if (!git_object_type_is_valid(obj->type)) { - git_error_set(GIT_ERROR_INVALID, "invalid object type"); - return -1; - } - - if (!(algorithm = git_oid_algorithm(oid_type))) { - git_error_set(GIT_ERROR_INVALID, "unknown oid type"); - return -1; - } - - if (!obj->data && obj->len != 0) { - git_error_set(GIT_ERROR_INVALID, "invalid object"); - return -1; - } - - if ((error = git_odb__format_object_header(&hdrlen, - header, sizeof(header), obj->len, obj->type)) < 0) - return error; - - vec[0].data = header; - vec[0].len = hdrlen; - vec[1].data = obj->data; - vec[1].len = obj->len; - -#ifdef GIT_EXPERIMENTAL_SHA256 - id->type = oid_type; -#endif - - return git_hash_vec(id->id, vec, 2, algorithm); -} - - static git_odb_object *odb_object__alloc(const git_oid *oid, git_rawobj *source) { git_odb_object *object = git__calloc(1, sizeof(git_odb_object)); @@ -205,231 +162,37 @@ void git_odb_object_free(git_odb_object *object) git_cached_obj_decref(object); } -int git_odb__hashfd( - git_oid *out, - git_file fd, - size_t size, - git_object_t object_type, - git_oid_t oid_type) -{ - size_t hdr_len; - char hdr[64], buffer[GIT_BUFSIZE_FILEIO]; - git_hash_ctx ctx; - git_hash_algorithm_t algorithm; - ssize_t read_len = 0; - int error = 0; +#ifndef GIT_DEPRECATE_HARD - if (!git_object_type_is_valid(object_type)) { - git_error_set(GIT_ERROR_INVALID, "invalid object type for hash"); - return -1; - } - - if (!(algorithm = git_oid_algorithm(oid_type))) { - git_error_set(GIT_ERROR_INVALID, "unknown oid type"); - return -1; - } - - if ((error = git_hash_ctx_init(&ctx, algorithm)) < 0) - return error; - - if ((error = git_odb__format_object_header(&hdr_len, hdr, - sizeof(hdr), size, object_type)) < 0) - goto done; - - if ((error = git_hash_update(&ctx, hdr, hdr_len)) < 0) - goto done; - - while (size > 0 && (read_len = p_read(fd, buffer, sizeof(buffer))) > 0) { - if ((error = git_hash_update(&ctx, buffer, read_len)) < 0) - goto done; - - size -= read_len; - } - - /* If p_read returned an error code, the read obviously failed. - * If size is not zero, the file was truncated after we originally - * stat'd it, so we consider this a read failure too */ - if (read_len < 0 || size > 0) { - git_error_set(GIT_ERROR_OS, "error reading file for hashing"); - error = -1; - - goto done; - } - - error = git_hash_final(out->id, &ctx); - -#ifdef GIT_EXPERIMENTAL_SHA256 - out->type = oid_type; -#endif - -done: - git_hash_ctx_cleanup(&ctx); - return error; -} - -int git_odb__hashfd_filtered( - git_oid *out, - git_file fd, - size_t size, - git_object_t object_type, - git_oid_t oid_type, - git_filter_list *fl) -{ - int error; - git_str raw = GIT_STR_INIT; - - if (!fl) - return git_odb__hashfd(out, fd, size, object_type, oid_type); - - /* size of data is used in header, so we have to read the whole file - * into memory to apply filters before beginning to calculate the hash - */ - - if (!(error = git_futils_readbuffer_fd(&raw, fd, size))) { - git_str post = GIT_STR_INIT; - - error = git_filter_list__convert_buf(&post, fl, &raw); - - if (!error) - error = git_odb__hash(out, post.ptr, post.size, object_type, oid_type); - - git_str_dispose(&post); - } - - return error; -} - -int git_odb__hashlink(git_oid *out, const char *path, git_oid_t oid_type) -{ - struct stat st; - int size; - int result; - - if (git_fs_path_lstat(path, &st) < 0) - return -1; - - if (!git__is_int(st.st_size) || (int)st.st_size < 0) { - git_error_set(GIT_ERROR_FILESYSTEM, "file size overflow for 32-bit systems"); - return -1; - } - - size = (int)st.st_size; - - if (S_ISLNK(st.st_mode)) { - char *link_data; - int read_len; - size_t alloc_size; - - GIT_ERROR_CHECK_ALLOC_ADD(&alloc_size, size, 1); - link_data = git__malloc(alloc_size); - GIT_ERROR_CHECK_ALLOC(link_data); - - read_len = p_readlink(path, link_data, size); - if (read_len == -1) { - git_error_set(GIT_ERROR_OS, "failed to read symlink data for '%s'", path); - git__free(link_data); - return -1; - } - GIT_ASSERT(read_len <= size); - link_data[read_len] = '\0'; - - result = git_odb__hash(out, link_data, read_len, GIT_OBJECT_BLOB, oid_type); - git__free(link_data); - } else { - int fd = git_futils_open_ro(path); - if (fd < 0) - return -1; - result = git_odb__hashfd(out, fd, size, GIT_OBJECT_BLOB, oid_type); - p_close(fd); - } - - return result; -} - -int git_odb__hashfile( - git_oid *out, - const char *path, - git_object_t object_type, - git_oid_t oid_type) -{ - uint64_t size; - int fd, error = 0; - - if ((fd = git_futils_open_ro(path)) < 0) - return fd; - - if ((error = git_futils_filesize(&size, fd)) < 0) - goto done; - - if (!git__is_sizet(size)) { - git_error_set(GIT_ERROR_OS, "file size overflow for 32-bit systems"); - error = -1; - goto done; - } - - error = git_odb__hashfd(out, fd, (size_t)size, object_type, oid_type); - -done: - p_close(fd); - return error; -} - -#ifdef GIT_EXPERIMENTAL_SHA256 -int git_odb_hashfile( - git_oid *out, - const char *path, - git_object_t object_type, - git_oid_t oid_type) -{ - return git_odb__hashfile(out, path, object_type, oid_type); -} -#else int git_odb_hashfile( git_oid *out, const char *path, git_object_t object_type) { - return git_odb__hashfile(out, path, object_type, GIT_OID_SHA1); -} -#endif + git_object_id_options opts = GIT_OBJECT_ID_OPTIONS_INIT; -int git_odb__hash( + GIT_ASSERT_ARG(object_type); + + opts.object_type = object_type; + + return git_object_id_from_file(out, path, &opts); +} + +int git_odb_hash( git_oid *id, const void *data, size_t len, - git_object_t object_type, - git_oid_t oid_type) + git_object_t object_type) { - git_rawobj raw; + git_object_id_options opts = GIT_OBJECT_ID_OPTIONS_INIT; - GIT_ASSERT_ARG(id); + GIT_ASSERT_ARG(object_type); - raw.data = (void *)data; - raw.len = len; - raw.type = object_type; + opts.object_type = object_type; - return git_odb__hashobj(id, &raw, oid_type); + return git_object_id_from_buffer(id, data, len, &opts); } -#ifdef GIT_EXPERIMENTAL_SHA256 -int git_odb_hash( - git_oid *out, - const void *data, - size_t len, - git_object_t object_type, - git_oid_t oid_type) -{ - return git_odb__hash(out, data, len, object_type, oid_type); -} -#else -int git_odb_hash( - git_oid *out, - const void *data, - size_t len, - git_object_t type) -{ - return git_odb__hash(out, data, len, type, GIT_OID_SHA1); -} #endif /** @@ -1358,7 +1121,13 @@ static int odb_read_1( return GIT_ENOTFOUND; if (git_odb__strict_hash_verification) { - if ((error = git_odb__hash(&hashed, raw.data, raw.len, raw.type, db->options.oid_type)) < 0) + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; + + id_opts.object_type = raw.type; + id_opts.oid_type = db->options.oid_type; + + if ((error = git_object_id_from_buffer(&hashed, + raw.data, raw.len, &id_opts)) < 0) goto out; if (!git_oid_equal(id, &hashed)) { @@ -1502,9 +1271,14 @@ static int read_prefix_1(git_odb_object **out, git_odb *db, return GIT_ENOTFOUND; if (git_odb__strict_hash_verification) { + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; git_oid hash; - if ((error = git_odb__hash(&hash, raw.data, raw.len, raw.type, db->options.oid_type)) < 0) + id_opts.object_type = raw.type; + id_opts.oid_type = db->options.oid_type; + + if ((error = git_object_id_from_buffer(&hash, + raw.data, raw.len, &id_opts)) < 0) goto out; if (!git_oid_equal(&found_full_oid, &hash)) { @@ -1598,14 +1372,18 @@ cleanup: int git_odb_write( git_oid *oid, git_odb *db, const void *data, size_t len, git_object_t type) { + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; + git_odb_stream *stream; size_t i; int error; - git_odb_stream *stream; + + id_opts.object_type = type; + id_opts.oid_type = db->options.oid_type; GIT_ASSERT_ARG(oid); GIT_ASSERT_ARG(db); - if ((error = git_odb__hash(oid, data, len, type, db->options.oid_type)) < 0) + if ((error = git_object_id_from_buffer(oid, data, len, &id_opts)) < 0) return error; if (git_oid_is_zero(oid)) diff --git a/src/libgit2/odb.h b/src/libgit2/odb.h index fa50b9849..bd58125f3 100644 --- a/src/libgit2/odb.h +++ b/src/libgit2/odb.h @@ -70,56 +70,11 @@ int git_odb__add_default_backends( git_odb *db, const char *objects_dir, bool as_alternates, int alternate_depth); -/* - * Hash a git_rawobj internally. - * The `git_rawobj` is supposed to be previously initialized - */ -int git_odb__hashobj(git_oid *id, git_rawobj *obj, git_oid_t oid_type); - /* * Format the object header such as it would appear in the on-disk object */ int git_odb__format_object_header(size_t *out_len, char *hdr, size_t hdr_size, git_object_size_t obj_len, git_object_t obj_type); -/* - * Hash an open file descriptor. - * This is a performance call when the contents of a fd need to be hashed, - * but the fd is already open and we have the size of the contents. - * - * Saves us some `stat` calls. - * - * The fd is never closed, not even on error. It must be opened and closed - * by the caller - */ -int git_odb__hashfd( - git_oid *out, - git_file fd, - size_t size, - git_object_t object_type, - git_oid_t oid_type); - -/* - * Hash an open file descriptor applying an array of filters - * Acts just like git_odb__hashfd with the addition of filters... - */ -int git_odb__hashfd_filtered( - git_oid *out, - git_file fd, - size_t len, - git_object_t object_type, - git_oid_t oid_type, - git_filter_list *fl); - -/* - * Hash a `path`, assuming it could be a POSIX symlink: if the path is a - * symlink, then the raw contents of the symlink will be hashed. Otherwise, - * this will fallback to `git_odb__hashfd`. - * - * The hash type for this call is always `GIT_OBJECT_BLOB` because - * symlinks may only point to blobs. - */ -int git_odb__hashlink(git_oid *out, const char *path, git_oid_t oid_type); - /** * Generate a GIT_EMISMATCH error for the ODB. */ @@ -160,19 +115,6 @@ void git_odb_object__free(void *object); /* SHA256 support */ -int git_odb__hash( - git_oid *out, - const void *data, - size_t len, - git_object_t object_type, - git_oid_t oid_type); - -int git_odb__hashfile( - git_oid *out, - const char *path, - git_object_t object_type, - git_oid_t oid_type); - int git_odb__backend_loose( git_odb_backend **out, const char *objects_dir, diff --git a/src/libgit2/reader.c b/src/libgit2/reader.c index df2b2807f..b08505f7b 100644 --- a/src/libgit2/reader.c +++ b/src/libgit2/reader.c @@ -125,7 +125,13 @@ static int workdir_reader_read( goto done; if (out_id || reader->index) { - if ((error = git_odb__hash(&id, out->ptr, out->size, GIT_OBJECT_BLOB, reader->repo->oid_type)) < 0) + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; + + id_opts.object_type = GIT_OBJECT_BLOB; + id_opts.oid_type = reader->repo->oid_type; + + if ((error = git_object_id_from_buffer(&id, + out->ptr, out->size, &id_opts)) < 0) goto done; } diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 53f56d5ca..19dab3b57 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -3558,6 +3558,7 @@ int git_repository_hashfile( git_object_t type, const char *as_path) { + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; int error; git_filter_list *fl = NULL; git_file fd = -1; @@ -3612,7 +3613,11 @@ int git_repository_hashfile( goto cleanup; } - error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, repo->oid_type, fl); + id_opts.object_type = type; + id_opts.oid_type = repo->oid_type; + id_opts.filters = fl; + + error = git_object_id_from_fd(out, fd, (size_t)len, &id_opts); cleanup: if (fd >= 0) diff --git a/tests/libgit2/checkout/binaryunicode.c b/tests/libgit2/checkout/binaryunicode.c index 5cefa77e2..d308ef2af 100644 --- a/tests/libgit2/checkout/binaryunicode.c +++ b/tests/libgit2/checkout/binaryunicode.c @@ -35,12 +35,12 @@ static void execute_test(void) /* Verify that the lenna.jpg file was checked out correctly */ cl_git_pass(git_oid_from_string(&check, "8ab005d890fe53f65eda14b23672f60d9f4ec5a1", GIT_OID_SHA1)); - cl_git_pass(git_odb__hashfile(&oid, "binaryunicode/lenna.jpg", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&oid, "binaryunicode/lenna.jpg", NULL)); cl_assert_equal_oid(&oid, &check); /* Verify that the text file was checked out correctly */ cl_git_pass(git_oid_from_string(&check, "965b223880dd4249e2c66a0cc0b4cffe1dc40f5a", GIT_OID_SHA1)); - cl_git_pass(git_odb__hashfile(&oid, "binaryunicode/utf16_withbom_noeol_crlf.txt", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&oid, "binaryunicode/utf16_withbom_noeol_crlf.txt", NULL)); cl_assert_equal_oid(&oid, &check); } diff --git a/tests/libgit2/object/raw/hash.c b/tests/libgit2/object/raw/hash.c index 914096f6a..208c9cfff 100644 --- a/tests/libgit2/object/raw/hash.c +++ b/tests/libgit2/object/raw/hash.c @@ -8,11 +8,19 @@ static void hash_object_pass(git_oid *oid, git_rawobj *obj) { - cl_git_pass(git_odb__hash(oid, obj->data, obj->len, obj->type, GIT_OID_SHA1)); + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; + + id_opts.object_type = obj->type; + + cl_git_pass(git_object_id_from_buffer(oid, obj->data, obj->len, &id_opts)); } static void hash_object_fail(git_oid *oid, git_rawobj *obj) { - cl_git_fail(git_odb__hash(oid, obj->data, obj->len, obj->type, GIT_OID_SHA1)); + git_object_id_options id_opts = GIT_OBJECT_ID_OPTIONS_INIT; + + id_opts.object_type = obj->type; + + cl_git_fail(git_object_id_from_buffer(oid, obj->data, obj->len, &id_opts)); } static char *hello_id = "22596363b3de40b06f981fb85d82312e8c0ed511"; @@ -87,9 +95,6 @@ void test_object_raw_hash__hash_junk_data(void) junk_obj.data = some_data; hash_object_fail(&id, &junk_obj); - junk_obj.type = 0; /* unused */ - hash_object_fail(&id, &junk_obj); - junk_obj.type = 5; /* unused */ hash_object_fail(&id, &junk_obj); diff --git a/tests/libgit2/repo/hashfile.c b/tests/libgit2/repo/hashfile.c index 64b8dfa46..8f470879d 100644 --- a/tests/libgit2/repo/hashfile.c +++ b/tests/libgit2/repo/hashfile.c @@ -21,19 +21,18 @@ void test_repo_hashfile__simple(void) git_str full = GIT_STR_INIT; /* hash with repo relative path */ - cl_git_pass(git_odb__hashfile(&a, "status/current_file", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/current_file", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, "current_file", GIT_OBJECT_BLOB, NULL)); cl_assert_equal_oid(&a, &b); cl_git_pass(git_str_joinpath(&full, git_repository_workdir(_repo), "current_file")); /* hash with full path */ - cl_git_pass(git_odb__hashfile(&a, full.ptr, GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, full.ptr, NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, full.ptr, GIT_OBJECT_BLOB, NULL)); cl_assert_equal_oid(&a, &b); /* hash with invalid type */ - cl_git_fail(git_odb__hashfile(&a, full.ptr, GIT_OBJECT_ANY, GIT_OID_SHA1)); cl_git_fail(git_repository_hashfile(&b, _repo, full.ptr, 6, NULL)); git_str_dispose(&full); @@ -60,64 +59,63 @@ void test_repo_hashfile__filtered_in_workdir(void) cl_git_mkfile("status/testfile.bin", "other\r\nstuff\r\n"); /* not equal hashes because of filtering */ - cl_git_pass(git_odb__hashfile(&a, "status/testfile.txt", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.txt", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJECT_BLOB, NULL)); cl_assert(git_oid_cmp(&a, &b)); /* not equal hashes because of filtering when specified by absolute path */ - cl_git_pass(git_odb__hashfile(&a, "status/testfile.txt", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.txt", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, txt.ptr, GIT_OBJECT_BLOB, NULL)); cl_assert(git_oid_cmp(&a, &b)); /* equal hashes because filter is binary */ - cl_git_pass(git_odb__hashfile(&a, "status/testfile.bin", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.bin", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJECT_BLOB, NULL)); cl_assert_equal_oid(&a, &b); /* equal hashes because filter is binary when specified by absolute path */ - cl_git_pass(git_odb__hashfile(&a, "status/testfile.bin", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.bin", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, bin.ptr, GIT_OBJECT_BLOB, NULL)); cl_assert_equal_oid(&a, &b); /* equal hashes when 'as_file' points to binary filtering */ - cl_git_pass(git_odb__hashfile(&a, "status/testfile.txt", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.txt", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJECT_BLOB, "foo.bin")); cl_assert_equal_oid(&a, &b); /* equal hashes when 'as_file' points to binary filtering (absolute path) */ - cl_git_pass(git_odb__hashfile(&a, "status/testfile.txt", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.txt", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, txt.ptr, GIT_OBJECT_BLOB, "foo.bin")); cl_assert_equal_oid(&a, &b); /* not equal hashes when 'as_file' points to text filtering */ - cl_git_pass(git_odb__hashfile(&a, "status/testfile.bin", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.bin", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJECT_BLOB, "foo.txt")); cl_assert(git_oid_cmp(&a, &b)); /* not equal hashes when 'as_file' points to text filtering */ - cl_git_pass(git_odb__hashfile(&a, "status/testfile.bin", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.bin", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, bin.ptr, GIT_OBJECT_BLOB, "foo.txt")); cl_assert(git_oid_cmp(&a, &b)); /* equal hashes when 'as_file' is empty and turns off filtering */ - cl_git_pass(git_odb__hashfile(&a, "status/testfile.txt", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.txt", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJECT_BLOB, "")); cl_assert_equal_oid(&a, &b); - cl_git_pass(git_odb__hashfile(&a, "status/testfile.bin", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.bin", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJECT_BLOB, "")); cl_assert_equal_oid(&a, &b); - cl_git_pass(git_odb__hashfile(&a, "status/testfile.txt", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.txt", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, txt.ptr, GIT_OBJECT_BLOB, "")); cl_assert_equal_oid(&a, &b); - cl_git_pass(git_odb__hashfile(&a, "status/testfile.bin", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "status/testfile.bin", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, bin.ptr, GIT_OBJECT_BLOB, "")); cl_assert_equal_oid(&a, &b); /* some hash type failures */ - cl_git_fail(git_odb__hashfile(&a, "status/testfile.txt", 0, GIT_OID_SHA1)); cl_git_fail(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJECT_ANY, NULL)); git_str_dispose(&txt); @@ -145,12 +143,12 @@ void test_repo_hashfile__filtered_outside_workdir(void) cl_git_mkfile("absolute/testfile.bin", "other\r\nstuff\r\n"); /* not equal hashes because of filtering */ - cl_git_pass(git_odb__hashfile(&a, "absolute/testfile.txt", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "absolute/testfile.txt", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, txt.ptr, GIT_OBJECT_BLOB, "testfile.txt")); cl_assert(git_oid_cmp(&a, &b)); /* equal hashes because filter is binary */ - cl_git_pass(git_odb__hashfile(&a, "absolute/testfile.bin", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "absolute/testfile.bin", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, bin.ptr, GIT_OBJECT_BLOB, "testfile.bin")); cl_assert_equal_oid(&a, &b); @@ -158,11 +156,11 @@ void test_repo_hashfile__filtered_outside_workdir(void) * equal hashes because no filtering occurs for absolute paths outside the working * directory unless as_path is specified */ - cl_git_pass(git_odb__hashfile(&a, "absolute/testfile.txt", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "absolute/testfile.txt", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, txt.ptr, GIT_OBJECT_BLOB, NULL)); cl_assert_equal_oid(&a, &b); - cl_git_pass(git_odb__hashfile(&a, "absolute/testfile.bin", GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&a, "absolute/testfile.bin", NULL)); cl_git_pass(git_repository_hashfile(&b, _repo, bin.ptr, GIT_OBJECT_BLOB, NULL)); cl_assert_equal_oid(&a, &b); diff --git a/tests/libgit2/status/single.c b/tests/libgit2/status/single.c index d217064b5..b2b144245 100644 --- a/tests/libgit2/status/single.c +++ b/tests/libgit2/status/single.c @@ -22,7 +22,7 @@ void test_status_single__hash_single_file(void) cl_git_mkfile(file_name, file_contents); cl_set_cleanup(&cleanup__remove_file, (void *)file_name); - cl_git_pass(git_odb__hashfile(&actual_id, file_name, GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&actual_id, file_name, NULL)); cl_assert_equal_oid(&expected_id, &actual_id); } @@ -40,7 +40,7 @@ void test_status_single__hash_single_empty_file(void) cl_git_mkfile(file_name, file_contents); cl_set_cleanup(&cleanup__remove_file, (void *)file_name); - cl_git_pass(git_odb__hashfile(&actual_id, file_name, GIT_OBJECT_BLOB, GIT_OID_SHA1)); + cl_git_pass(git_object_id_from_file(&actual_id, file_name, NULL)); cl_assert_equal_oid(&expected_id, &actual_id); }