Skip to content

Commit ea0cb5c

Browse files
committed
Merge branch 'xl/upgrade-repo-format' into pu
Allow runtime upgrade of the repository format version, which needs to be done carefully. Almost there. * 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
2 parents 3f946f0 + 14c7fa2 commit ea0cb5c

11 files changed

+75
-11
lines changed

builtin/fetch.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,9 +1795,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
17951795
if (depth || deepen_since || deepen_not.nr)
17961796
deepen = 1;
17971797

1798-
if (filter_options.choice && !has_promisor_remote())
1799-
die("--filter can only be used when extensions.partialClone is set");
1800-
18011798
if (all) {
18021799
if (argc == 1)
18031800
die(_("fetch --all does not take a repository argument"));

builtin/sparse-checkout.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ static int set_config(enum sparse_checkout_mode mode)
253253
{
254254
const char *config_path;
255255

256+
if (upgrade_repository_format(1) < 0)
257+
die(_("unable to upgrade repository format to enable worktreeConfig"));
256258
if (git_config_set_gently("extensions.worktreeConfig", "true")) {
257259
error(_("failed to set extensions.worktreeConfig setting"));
258260
return 1;

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,7 @@ struct repository_format {
10421042
int worktree_config;
10431043
int is_bare;
10441044
int hash_algo;
1045+
int has_extensions;
10451046
char *work_tree;
10461047
struct string_list unknown_extensions;
10471048
};

list-objects-filter-options.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ void partial_clone_register(
326326

327327
/* Check if it is already registered */
328328
if (!promisor_remote_find(remote)) {
329-
git_config_set("core.repositoryformatversion", "1");
329+
if (upgrade_repository_format(1) < 0)
330+
die(_("unable to upgrade repository format to support partial clone"));
330331

331332
/* Add promisor config for the remote */
332333
cfg_name = xstrfmt("remote.%s.promisor", remote);

repository.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,10 @@ void repo_update_index_if_able(struct repository *, struct lock_file *);
196196

197197
void prepare_repo_settings(struct repository *r);
198198

199+
/*
200+
* Return 1 if upgrade repository format to target_version succeeded,
201+
* 0 if no upgrade is necessary, and -1 when upgrade is not possible.
202+
*/
203+
int upgrade_repository_format(int target_version);
204+
199205
#endif /* REPOSITORY_H */

setup.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ static int check_repo_format(const char *var, const char *value, void *vdata)
455455
if (strcmp(var, "core.repositoryformatversion") == 0)
456456
data->version = git_config_int(var, value);
457457
else if (skip_prefix(var, "extensions.", &ext)) {
458+
data->has_extensions = 1;
458459
/*
459460
* record any known extensions here; otherwise,
460461
* we fall through to recording it as unknown, and
@@ -506,9 +507,15 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
506507
die("%s", err.buf);
507508
}
508509

509-
repository_format_precious_objects = candidate->precious_objects;
510-
set_repository_format_partial_clone(candidate->partial_clone);
511-
repository_format_worktree_config = candidate->worktree_config;
510+
if (candidate->version >= 1) {
511+
repository_format_precious_objects = candidate->precious_objects;
512+
set_repository_format_partial_clone(candidate->partial_clone);
513+
repository_format_worktree_config = candidate->worktree_config;
514+
} else {
515+
repository_format_precious_objects = 0;
516+
set_repository_format_partial_clone(NULL);
517+
repository_format_worktree_config = 0;
518+
}
512519
string_list_clear(&candidate->unknown_extensions, 0);
513520

514521
if (repository_format_worktree_config) {
@@ -538,6 +545,34 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
538545
return 0;
539546
}
540547

548+
int upgrade_repository_format(int target_version)
549+
{
550+
struct strbuf sb = STRBUF_INIT;
551+
struct strbuf err = STRBUF_INIT;
552+
struct strbuf repo_version = STRBUF_INIT;
553+
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
554+
555+
strbuf_git_common_path(&sb, the_repository, "config");
556+
read_repository_format(&repo_fmt, sb.buf);
557+
strbuf_release(&sb);
558+
559+
if (repo_fmt.version >= target_version)
560+
return 0;
561+
562+
if (verify_repository_format(&repo_fmt, &err) < 0 ||
563+
(!repo_fmt.version && repo_fmt.has_extensions)) {
564+
warning("unable to upgrade repository format from %d to %d: %s",
565+
repo_fmt.version, target_version, err.buf);
566+
strbuf_release(&err);
567+
return -1;
568+
}
569+
570+
strbuf_addf(&repo_version, "%d", target_version);
571+
git_config_set("core.repositoryformatversion", repo_version.buf);
572+
strbuf_release(&repo_version);
573+
return 1;
574+
}
575+
541576
static void init_repository_format(struct repository_format *format)
542577
{
543578
const struct repository_format fresh = REPOSITORY_FORMAT_INIT;

t/t0410-partial-clone.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,29 @@ test_expect_success 'extensions.partialclone without filter' '
3030
git -C client fetch origin
3131
'
3232

33+
test_expect_success 'convert shallow clone to partial clone' '
34+
rm -fr server client &&
35+
test_create_repo server &&
36+
test_commit -C server my_commit 1 &&
37+
test_commit -C server my_commit2 1 &&
38+
git clone --depth=1 "file://$(pwd)/server" client &&
39+
git -C client fetch --unshallow --filter="blob:none" &&
40+
test_cmp_config -C client true remote.origin.promisor &&
41+
test_cmp_config -C client blob:none remote.origin.partialclonefilter &&
42+
test_cmp_config -C client 1 core.repositoryformatversion
43+
'
44+
45+
test_expect_success 'convert shallow clone to partial clone must fail with any extension' '
46+
rm -fr server client &&
47+
test_create_repo server &&
48+
test_commit -C server my_commit 1 &&
49+
test_commit -C server my_commit2 1 &&
50+
git clone --depth=1 "file://$(pwd)/server" client &&
51+
test_cmp_config -C client 0 core.repositoryformatversion &&
52+
git -C client config extensions.partialclone origin &&
53+
test_must_fail git -C client fetch --unshallow --filter="blob:none"
54+
'
55+
3356
test_expect_success 'missing reflog object, but promised by a commit, passes fsck' '
3457
rm -rf repo &&
3558
test_create_repo repo &&

t/t1090-sparse-checkout-scope.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ test_expect_success 'in partial clone, sparse checkout only fetches needed blobs
6363
git -C server commit -m message &&
6464
6565
test_config -C client core.sparsecheckout 1 &&
66-
test_config -C client extensions.partialclone origin &&
6766
echo "!/*" >client/.git/info/sparse-checkout &&
6867
echo "/a" >>client/.git/info/sparse-checkout &&
6968
git -C client fetch --filter=blob:none origin &&

t/t2404-worktree-config.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ test_expect_success 'config --worktree without extension' '
2323
'
2424

2525
test_expect_success 'enable worktreeConfig extension' '
26+
git config core.repositoryformatversion 1 &&
2627
git config extensions.worktreeConfig true &&
27-
test_cmp_config true extensions.worktreeConfig
28+
test_cmp_config true extensions.worktreeConfig &&
29+
test_cmp_config 1 core.repositoryformatversion
2830
'
2931

3032
test_expect_success 'config is shared as before' '

t/t5500-fetch-pack.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,6 @@ fetch_filter_blob_limit_zero () {
10001000
test_config -C "$SERVER" uploadpack.allowfilter 1 &&
10011001

10021002
git clone "$URL" client &&
1003-
test_config -C client extensions.partialclone origin &&
10041003

10051004
test_commit -C "$SERVER" two &&
10061005

t/t5702-protocol-v2.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,6 @@ test_expect_success 'partial fetch' '
349349
rm -rf client "$(pwd)/trace" &&
350350
git init client &&
351351
SERVER="file://$(pwd)/server" &&
352-
test_config -C client extensions.partialClone "$SERVER" &&
353352
354353
GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \
355354
fetch --filter=blob:none "$SERVER" master:refs/heads/other &&

0 commit comments

Comments
 (0)