repository: add a compatibility hash algorithm

We currently have support for using a full stage 4 SHA-256 implementation. However, we'd like to support interoperability with SHA-1 repositories as well. The transition plan anticipates a compatibility hash algorithm configuration option that we can use to implement support for this. Let's add an element to the repository structure that indicates the compatibility hash algorithm so we can use it when we need to consider interoperability between algorithms. Add a helper function repo_set_compat_hash_algo that takes a compatibility hash algorithm and sets "repo->compat_hash_algo". If GIT_HASH_UNKNOWN is passed as the compatibility hash algorithm "repo->compat_hash_algo" is set to NULL. For now, the code results in "repo->compat_hash_algo" always being set to NULL, but that will change once a configuration option is added. Inspired-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Eric W. Biederman committed Oct 1, 2023 at 21:40 UTC 15a1ca1abe8dafa9bf3bf924b4e3c6b851717ee2
3 files changed +15
repository.c
+8
@@ -104,6 +104,13 @@ void repo_set_hash_algo(struct repository *repo, int hash_algo)
104 repo->hash_algo = &hash_algos[hash_algo];
105 }
106
107 +void repo_set_compat_hash_algo(struct repository *repo, int algo)
108 +{
109 + if (hash_algo_by_ptr(repo->hash_algo) == algo)
110 + BUG("hash_algo and compat_hash_algo match");
111 + repo->compat_hash_algo = algo ? &hash_algos[algo] : NULL;
112 +}
113 +
114 /*
115 * Attempt to resolve and set the provided 'gitdir' for repository 'repo'.
116 * Return 0 upon success and a non-zero value upon failure.
@@ -184,6 +191,7 @@ int repo_init(struct repository *repo,
191 goto error;
192
193 repo_set_hash_algo(repo, format.hash_algo);
194 + repo_set_compat_hash_algo(repo, GIT_HASH_UNKNOWN);
195 repo->repository_format_worktree_config = format.worktree_config;
196
197 /* take ownership of format.partial_clone */
repository.h
+4
@@ -160,6 +160,9 @@ struct repository {
160 /* Repository's current hash algorithm, as serialized on disk. */
161 const struct git_hash_algo *hash_algo;
162
163 + /* Repository's compatibility hash algorithm. */
164 + const struct git_hash_algo *compat_hash_algo;
165 +
166 /* A unique-id for tracing purposes. */
167 int trace2_repo_id;
168
@@ -199,6 +202,7 @@ void repo_set_gitdir(struct repository *repo, const char *root,
202 const struct set_gitdir_args *extra_args);
203 void repo_set_worktree(struct repository *repo, const char *path);
204 void repo_set_hash_algo(struct repository *repo, int algo);
205 +void repo_set_compat_hash_algo(struct repository *repo, int compat_algo);
206 void initialize_the_repository(void);
207 RESULT_MUST_BE_USED
208 int repo_init(struct repository *r, const char *gitdir, const char *worktree);
setup.c
+3
@@ -1564,6 +1564,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
1564 }
1565 if (startup_info->have_repository) {
1566 repo_set_hash_algo(the_repository, repo_fmt.hash_algo);
1567 + repo_set_compat_hash_algo(the_repository,
1568 + GIT_HASH_UNKNOWN);
1569 the_repository->repository_format_worktree_config =
1570 repo_fmt.worktree_config;
1571 /* take ownership of repo_fmt.partial_clone */
@@ -1657,6 +1659,7 @@ void check_repository_format(struct repository_format *fmt)
1659 check_repository_format_gently(get_git_dir(), fmt, NULL);
1660 startup_info->have_repository = 1;
1661 repo_set_hash_algo(the_repository, fmt->hash_algo);
1662 + repo_set_compat_hash_algo(the_repository, GIT_HASH_UNKNOWN);
1663 the_repository->repository_format_worktree_config =
1664 fmt->worktree_config;
1665 the_repository->repository_format_partial_clone =