mirror of
https://github.com/git/git
synced 2024-08-24 18:26:02 +00:00
Merge branch 'xl/upgrade-repo-format'
Allow runtime upgrade of the repository format version, which needs to be done carefully. There is a rather unpleasant backward compatibility worry with the last step of this series, but it is the right thing to do in the longer term. * xl/upgrade-repo-format: check_repository_format_gently(): refuse extensions for old repositories sparse-checkout: upgrade repository to version 1 when enabling extension fetch: allow adding a filter after initial clone repository: add a helper function to perform repository format upgrade
This commit is contained in:
commit
1033b98291
|
@ -1795,9 +1795,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
|
||||||
if (depth || deepen_since || deepen_not.nr)
|
if (depth || deepen_since || deepen_not.nr)
|
||||||
deepen = 1;
|
deepen = 1;
|
||||||
|
|
||||||
if (filter_options.choice && !has_promisor_remote())
|
|
||||||
die("--filter can only be used when extensions.partialClone is set");
|
|
||||||
|
|
||||||
if (all) {
|
if (all) {
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
die(_("fetch --all does not take a repository argument"));
|
die(_("fetch --all does not take a repository argument"));
|
||||||
|
|
|
@ -253,6 +253,8 @@ static int set_config(enum sparse_checkout_mode mode)
|
||||||
{
|
{
|
||||||
const char *config_path;
|
const char *config_path;
|
||||||
|
|
||||||
|
if (upgrade_repository_format(1) < 0)
|
||||||
|
die(_("unable to upgrade repository format to enable worktreeConfig"));
|
||||||
if (git_config_set_gently("extensions.worktreeConfig", "true")) {
|
if (git_config_set_gently("extensions.worktreeConfig", "true")) {
|
||||||
error(_("failed to set extensions.worktreeConfig setting"));
|
error(_("failed to set extensions.worktreeConfig setting"));
|
||||||
return 1;
|
return 1;
|
||||||
|
|
1
cache.h
1
cache.h
|
@ -1042,6 +1042,7 @@ struct repository_format {
|
||||||
int worktree_config;
|
int worktree_config;
|
||||||
int is_bare;
|
int is_bare;
|
||||||
int hash_algo;
|
int hash_algo;
|
||||||
|
int has_extensions;
|
||||||
char *work_tree;
|
char *work_tree;
|
||||||
struct string_list unknown_extensions;
|
struct string_list unknown_extensions;
|
||||||
};
|
};
|
||||||
|
|
|
@ -326,7 +326,8 @@ void partial_clone_register(
|
||||||
|
|
||||||
/* Check if it is already registered */
|
/* Check if it is already registered */
|
||||||
if (!promisor_remote_find(remote)) {
|
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 */
|
/* Add promisor config for the remote */
|
||||||
cfg_name = xstrfmt("remote.%s.promisor", remote);
|
cfg_name = xstrfmt("remote.%s.promisor", remote);
|
||||||
|
|
|
@ -196,4 +196,10 @@ void repo_update_index_if_able(struct repository *, struct lock_file *);
|
||||||
|
|
||||||
void prepare_repo_settings(struct repository *r);
|
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 */
|
#endif /* REPOSITORY_H */
|
||||||
|
|
41
setup.c
41
setup.c
|
@ -455,6 +455,7 @@ static int check_repo_format(const char *var, const char *value, void *vdata)
|
||||||
if (strcmp(var, "core.repositoryformatversion") == 0)
|
if (strcmp(var, "core.repositoryformatversion") == 0)
|
||||||
data->version = git_config_int(var, value);
|
data->version = git_config_int(var, value);
|
||||||
else if (skip_prefix(var, "extensions.", &ext)) {
|
else if (skip_prefix(var, "extensions.", &ext)) {
|
||||||
|
data->has_extensions = 1;
|
||||||
/*
|
/*
|
||||||
* record any known extensions here; otherwise,
|
* record any known extensions here; otherwise,
|
||||||
* we fall through to recording it as unknown, and
|
* we fall through to recording it as unknown, and
|
||||||
|
@ -506,9 +507,15 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
|
||||||
die("%s", err.buf);
|
die("%s", err.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
repository_format_precious_objects = candidate->precious_objects;
|
if (candidate->version >= 1) {
|
||||||
set_repository_format_partial_clone(candidate->partial_clone);
|
repository_format_precious_objects = candidate->precious_objects;
|
||||||
repository_format_worktree_config = candidate->worktree_config;
|
set_repository_format_partial_clone(candidate->partial_clone);
|
||||||
|
repository_format_worktree_config = candidate->worktree_config;
|
||||||
|
} else {
|
||||||
|
repository_format_precious_objects = 0;
|
||||||
|
set_repository_format_partial_clone(NULL);
|
||||||
|
repository_format_worktree_config = 0;
|
||||||
|
}
|
||||||
string_list_clear(&candidate->unknown_extensions, 0);
|
string_list_clear(&candidate->unknown_extensions, 0);
|
||||||
|
|
||||||
if (repository_format_worktree_config) {
|
if (repository_format_worktree_config) {
|
||||||
|
@ -538,6 +545,34 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
|
||||||
return 0;
|
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)
|
static void init_repository_format(struct repository_format *format)
|
||||||
{
|
{
|
||||||
const struct repository_format fresh = REPOSITORY_FORMAT_INIT;
|
const struct repository_format fresh = REPOSITORY_FORMAT_INIT;
|
||||||
|
|
|
@ -30,6 +30,29 @@ test_expect_success 'extensions.partialclone without filter' '
|
||||||
git -C client fetch origin
|
git -C client fetch origin
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'convert shallow clone to partial clone' '
|
||||||
|
rm -fr server client &&
|
||||||
|
test_create_repo server &&
|
||||||
|
test_commit -C server my_commit 1 &&
|
||||||
|
test_commit -C server my_commit2 1 &&
|
||||||
|
git clone --depth=1 "file://$(pwd)/server" client &&
|
||||||
|
git -C client fetch --unshallow --filter="blob:none" &&
|
||||||
|
test_cmp_config -C client true remote.origin.promisor &&
|
||||||
|
test_cmp_config -C client blob:none remote.origin.partialclonefilter &&
|
||||||
|
test_cmp_config -C client 1 core.repositoryformatversion
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'convert shallow clone to partial clone must fail with any extension' '
|
||||||
|
rm -fr server client &&
|
||||||
|
test_create_repo server &&
|
||||||
|
test_commit -C server my_commit 1 &&
|
||||||
|
test_commit -C server my_commit2 1 &&
|
||||||
|
git clone --depth=1 "file://$(pwd)/server" client &&
|
||||||
|
test_cmp_config -C client 0 core.repositoryformatversion &&
|
||||||
|
git -C client config extensions.partialclone origin &&
|
||||||
|
test_must_fail git -C client fetch --unshallow --filter="blob:none"
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'missing reflog object, but promised by a commit, passes fsck' '
|
test_expect_success 'missing reflog object, but promised by a commit, passes fsck' '
|
||||||
rm -rf repo &&
|
rm -rf repo &&
|
||||||
test_create_repo repo &&
|
test_create_repo repo &&
|
||||||
|
|
|
@ -63,7 +63,6 @@ test_expect_success 'in partial clone, sparse checkout only fetches needed blobs
|
||||||
git -C server commit -m message &&
|
git -C server commit -m message &&
|
||||||
|
|
||||||
test_config -C client core.sparsecheckout 1 &&
|
test_config -C client core.sparsecheckout 1 &&
|
||||||
test_config -C client extensions.partialclone origin &&
|
|
||||||
echo "!/*" >client/.git/info/sparse-checkout &&
|
echo "!/*" >client/.git/info/sparse-checkout &&
|
||||||
echo "/a" >>client/.git/info/sparse-checkout &&
|
echo "/a" >>client/.git/info/sparse-checkout &&
|
||||||
git -C client fetch --filter=blob:none origin &&
|
git -C client fetch --filter=blob:none origin &&
|
||||||
|
|
|
@ -23,8 +23,10 @@ test_expect_success 'config --worktree without extension' '
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'enable worktreeConfig extension' '
|
test_expect_success 'enable worktreeConfig extension' '
|
||||||
|
git config core.repositoryformatversion 1 &&
|
||||||
git config extensions.worktreeConfig true &&
|
git config extensions.worktreeConfig true &&
|
||||||
test_cmp_config true extensions.worktreeConfig
|
test_cmp_config true extensions.worktreeConfig &&
|
||||||
|
test_cmp_config 1 core.repositoryformatversion
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'config is shared as before' '
|
test_expect_success 'config is shared as before' '
|
||||||
|
|
|
@ -999,7 +999,6 @@ fetch_filter_blob_limit_zero () {
|
||||||
test_config -C "$SERVER" uploadpack.allowfilter 1 &&
|
test_config -C "$SERVER" uploadpack.allowfilter 1 &&
|
||||||
|
|
||||||
git clone "$URL" client &&
|
git clone "$URL" client &&
|
||||||
test_config -C client extensions.partialclone origin &&
|
|
||||||
|
|
||||||
test_commit -C "$SERVER" two &&
|
test_commit -C "$SERVER" two &&
|
||||||
|
|
||||||
|
|
|
@ -348,7 +348,6 @@ test_expect_success 'partial fetch' '
|
||||||
rm -rf client "$(pwd)/trace" &&
|
rm -rf client "$(pwd)/trace" &&
|
||||||
git init client &&
|
git init client &&
|
||||||
SERVER="file://$(pwd)/server" &&
|
SERVER="file://$(pwd)/server" &&
|
||||||
test_config -C client extensions.partialClone "$SERVER" &&
|
|
||||||
|
|
||||||
GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \
|
GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \
|
||||||
fetch --filter=blob:none "$SERVER" master:refs/heads/other &&
|
fetch --filter=blob:none "$SERVER" master:refs/heads/other &&
|
||||||
|
|
Loading…
Reference in a new issue