repository: add a helper function to perform repository format upgrade

In version 1 of repository format, "extensions" gained special meaning
and it is safer to avoid upgrading when there are pre-existing
extensions.

Make list-objects-filter to use the helper function instead of setting
repository version directly as a prerequisite of exposing the upgrade
capability.

Signed-off-by: Xin Li <delphij@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Xin Li 2020-06-05 02:10:01 -07:00 committed by Junio C Hamano
parent 2d5e9f31ac
commit 16af5f1abb
4 changed files with 38 additions and 1 deletions

View File

@ -1042,6 +1042,7 @@ struct repository_format {
int worktree_config;
int is_bare;
int hash_algo;
int has_extensions;
char *work_tree;
struct string_list unknown_extensions;
};

View File

@ -326,7 +326,8 @@ void partial_clone_register(
/* Check if it is already registered */
if (!promisor_remote_find(remote)) {
git_config_set("core.repositoryformatversion", "1");
if (upgrade_repository_format(1) < 0)
die(_("unable to upgrade repository format to support partial clone"));
/* Add promisor config for the remote */
cfg_name = xstrfmt("remote.%s.promisor", remote);

View File

@ -196,4 +196,10 @@ void repo_update_index_if_able(struct repository *, struct lock_file *);
void prepare_repo_settings(struct repository *r);
/*
* Return 1 if upgrade repository format to target_version succeeded,
* 0 if no upgrade is necessary, and -1 when upgrade is not possible.
*/
int upgrade_repository_format(int target_version);
#endif /* REPOSITORY_H */

29
setup.c
View File

@ -455,6 +455,7 @@ static int check_repo_format(const char *var, const char *value, void *vdata)
if (strcmp(var, "core.repositoryformatversion") == 0)
data->version = git_config_int(var, value);
else if (skip_prefix(var, "extensions.", &ext)) {
data->has_extensions = 1;
/*
* record any known extensions here; otherwise,
* we fall through to recording it as unknown, and
@ -538,6 +539,34 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
return 0;
}
int upgrade_repository_format(int target_version)
{
struct strbuf sb = STRBUF_INIT;
struct strbuf err = STRBUF_INIT;
struct strbuf repo_version = STRBUF_INIT;
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
strbuf_git_common_path(&sb, the_repository, "config");
read_repository_format(&repo_fmt, sb.buf);
strbuf_release(&sb);
if (repo_fmt.version >= target_version)
return 0;
if (verify_repository_format(&repo_fmt, &err) < 0 ||
(!repo_fmt.version && repo_fmt.has_extensions)) {
warning("unable to upgrade repository format from %d to %d: %s",
repo_fmt.version, target_version, err.buf);
strbuf_release(&err);
return -1;
}
strbuf_addf(&repo_version, "%d", target_version);
git_config_set("core.repositoryformatversion", repo_version.buf);
strbuf_release(&repo_version);
return 1;
}
static void init_repository_format(struct repository_format *format)
{
const struct repository_format fresh = REPOSITORY_FORMAT_INIT;