diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2022-09-19 10:39:58 -0400 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2023-02-12 21:26:10 +0000 |
commit | acb00e4eae66bfed84046bccb60bf59707fe9626 (patch) | |
tree | cb7136b9359e1ba600cc7f24571fcb8a69f6ce0e | |
parent | 4083e46f475cd3026a3c65a1e46c4b73d5c22513 (diff) | |
download | libgit2-acb00e4eae66bfed84046bccb60bf59707fe9626.tar.gz |
repo: understand the `objectformat` extension
Teach the repository about the `objectformat` extension, supporting
`sha1` always and `sha256` when the experimental sha256 support is
active.
-rw-r--r-- | include/git2/repository.h | 8 | ||||
-rw-r--r-- | src/libgit2/repository.c | 50 | ||||
-rw-r--r-- | src/libgit2/repository.h | 1 | ||||
-rw-r--r-- | tests/libgit2/core/opts.c | 15 | ||||
-rw-r--r-- | tests/libgit2/repo/objectformat.c | 69 |
5 files changed, 132 insertions, 11 deletions
diff --git a/include/git2/repository.h b/include/git2/repository.h index c87f3c962..9b56599d7 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -949,6 +949,14 @@ GIT_EXTERN(int) git_repository_ident(const char **name, const char **email, cons */ GIT_EXTERN(int) git_repository_set_ident(git_repository *repo, const char *name, const char *email); +/** + * Gets the object type used by this repository. + * + * @param repo the repository + * @return the object id type + */ +GIT_EXTERN(git_oid_t) git_repository_oid_type(git_repository *repo); + /** @} */ GIT_END_DECL #endif diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index df41f581c..5d51be6b7 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -67,6 +67,7 @@ static const struct { static int check_repositoryformatversion(int *version, git_config *config); static int check_extensions(git_config *config, int version); static int load_global_config(git_config **config); +static int load_objectformat(git_repository *repo, git_config *config); #define GIT_COMMONDIR_FILE "commondir" #define GIT_GITDIR_FILE "gitdir" @@ -240,7 +241,7 @@ GIT_INLINE(int) validate_repo_path(git_str *path) */ static size_t suffix_len = CONST_STRLEN("objects/pack/pack-.pack.lock") + - GIT_OID_SHA1_HEXSIZE; + GIT_OID_MAX_HEXSIZE; return git_fs_path_validate_str_length_with_suffix( path, suffix_len); @@ -1030,6 +1031,13 @@ int git_repository_open_ext( goto cleanup; } + if (version > 0) { + if ((error = load_objectformat(repo, config)) < 0) + goto cleanup; + } else { + repo->oid_type = GIT_OID_SHA1; + } + /* * Ensure that the git directory and worktree are * owned by the current user. @@ -1549,7 +1557,8 @@ static int check_repositoryformatversion(int *version, git_config *config) } static const char *builtin_extensions[] = { - "noop" + "noop", + "objectformat" }; static git_vector user_extensions = GIT_VECTOR_INIT; @@ -1613,6 +1622,32 @@ static int check_extensions(git_config *config, int version) return git_config_foreach_match(config, "^extensions\\.", check_valid_extension, NULL); } +static int load_objectformat(git_repository *repo, git_config *config) +{ + git_config_entry *entry = NULL; + int error; + + if ((error = git_config_get_entry(&entry, config, "extensions.objectformat")) < 0) { + if (error == GIT_ENOTFOUND) { + repo->oid_type = GIT_OID_SHA1; + git_error_clear(); + error = 0; + } + + goto done; + } + + if ((repo->oid_type = git_oid_type_fromstr(entry->value)) == 0) { + git_error_set(GIT_ERROR_REPOSITORY, + "unknown object format '%s'", entry->value); + error = GIT_EINVALID; + } + +done: + git_config_entry_free(entry); + return error; +} + int git_repository__extensions(char ***out, size_t *out_len) { git_vector extensions; @@ -2922,14 +2957,14 @@ int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head { git_filebuf file = GIT_FILEBUF_INIT; git_str file_path = GIT_STR_INIT; - char orig_head_str[GIT_OID_SHA1_HEXSIZE]; + char orig_head_str[GIT_OID_MAX_HEXSIZE]; int error = 0; git_oid_fmt(orig_head_str, orig_head); if ((error = git_str_joinpath(&file_path, repo->gitdir, GIT_ORIG_HEAD_FILE)) == 0 && (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_CREATE_LEADING_DIRS, GIT_MERGE_FILE_MODE)) == 0 && - (error = git_filebuf_printf(&file, "%.*s\n", GIT_OID_SHA1_HEXSIZE, orig_head_str)) == 0) + (error = git_filebuf_printf(&file, "%.*s\n", (int)git_oid_hexsize(repo->oid_type), orig_head_str)) == 0) error = git_filebuf_commit(&file); if (error < 0) @@ -3042,7 +3077,7 @@ int git_repository_hashfile( goto cleanup; } - error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, GIT_OID_SHA1, fl); + error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, repo->oid_type, fl); cleanup: if (fd >= 0) @@ -3389,3 +3424,8 @@ int git_repository_submodule_cache_clear(git_repository *repo) repo->submodule_cache = NULL; return error; } + +git_oid_t git_repository_oid_type(git_repository *repo) +{ + return repo ? repo->oid_type : 0; +} diff --git a/src/libgit2/repository.h b/src/libgit2/repository.h index a488f2bf2..b1e212a32 100644 --- a/src/libgit2/repository.h +++ b/src/libgit2/repository.h @@ -153,6 +153,7 @@ struct git_repository { unsigned is_bare:1; unsigned is_worktree:1; + git_oid_t oid_type; unsigned int lru_counter; diff --git a/tests/libgit2/core/opts.c b/tests/libgit2/core/opts.c index e8f65d510..486ff58c6 100644 --- a/tests/libgit2/core/opts.c +++ b/tests/libgit2/core/opts.c @@ -34,8 +34,9 @@ void test_core_opts__extensions_query(void) cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out)); - cl_assert_equal_sz(out.count, 1); + cl_assert_equal_sz(out.count, 2); cl_assert_equal_s("noop", out.strings[0]); + cl_assert_equal_s("objectformat", out.strings[1]); git_strarray_dispose(&out); } @@ -48,9 +49,10 @@ void test_core_opts__extensions_add(void) cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in))); cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out)); - cl_assert_equal_sz(out.count, 2); + cl_assert_equal_sz(out.count, 3); cl_assert_equal_s("noop", out.strings[0]); - cl_assert_equal_s("foo", out.strings[1]); + cl_assert_equal_s("objectformat", out.strings[1]); + cl_assert_equal_s("foo", out.strings[2]); git_strarray_dispose(&out); } @@ -63,9 +65,10 @@ void test_core_opts__extensions_remove(void) cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in))); cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out)); - cl_assert_equal_sz(out.count, 2); - cl_assert_equal_s("bar", out.strings[0]); - cl_assert_equal_s("baz", out.strings[1]); + cl_assert_equal_sz(out.count, 3); + cl_assert_equal_s("objectformat", out.strings[0]); + cl_assert_equal_s("bar", out.strings[1]); + cl_assert_equal_s("baz", out.strings[2]); git_strarray_dispose(&out); } diff --git a/tests/libgit2/repo/objectformat.c b/tests/libgit2/repo/objectformat.c new file mode 100644 index 000000000..3518115f4 --- /dev/null +++ b/tests/libgit2/repo/objectformat.c @@ -0,0 +1,69 @@ +#include "clar_libgit2.h" +#include "futils.h" +#include "sysdir.h" +#include "repository.h" +#include <ctype.h> + +git_repository *repo; +git_config *config; + +void test_repo_objectformat__initialize(void) +{ + repo = cl_git_sandbox_init("empty_bare.git"); + + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_set_int32(config, "core.repositoryformatversion", 1)); +} + +void test_repo_objectformat__cleanup(void) +{ + git_config_free(config); + cl_git_sandbox_cleanup(); +} + +void test_repo_objectformat__unspecified(void) +{ + git_repository *other; + + cl_git_pass(git_repository_open(&other, "empty_bare.git")); + cl_assert_equal_i(GIT_OID_SHA1, git_repository_oid_type(other)); + git_repository_free(other); +} + +void test_repo_objectformat__sha1(void) +{ + git_repository *other; + + cl_git_pass(git_config_set_string(config, "extensions.objectformat", "sha1")); + + cl_git_pass(git_repository_open(&other, "empty_bare.git")); + cl_assert_equal_i(GIT_OID_SHA1, git_repository_oid_type(other)); + git_repository_free(other); +} + +void test_repo_objectformat__sha256(void) +{ +#ifndef GIT_EXPERIMENTAL_SHA256 + cl_skip(); +#else + git_repository *other; + + cl_git_pass(git_config_set_string(config, "extensions.objectformat", "sha256")); + + cl_git_pass(git_repository_open(&other, "empty_bare.git")); + cl_assert_equal_i(GIT_OID_SHA256, git_repository_oid_type(other)); + git_repository_free(other); +#endif +} + +void test_repo_objectformat__invalid(void) +{ + git_repository *other; + + cl_git_pass(git_config_set_string(config, "extensions.objectformat", "bogus")); + + cl_git_fail_with(GIT_EINVALID, git_repository_open(&other, "empty_bare.git")); + cl_assert_equal_s("unknown object format 'bogus'", git_error_last()->message); + git_repository_free(other); +} + |