From 150c31bf88ee3021a51c0482279c7ccac68b0e0e Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 30 Jan 2025 17:24:17 +0100 Subject: [PATCH 1/3] t0001: remove duplicate test The test in question is an exact copy of the testcase preceding it. Remove it. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- t/t0001-init.sh | 9 --------- 1 file changed, 9 deletions(-) diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 72a0c2e7d4..213d5984b1 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -861,15 +861,6 @@ test_expect_success 're-init with includeIf.onbranch condition' ' test_cmp expect actual ' -test_expect_success 're-init with includeIf.onbranch condition' ' - test_when_finished "rm -rf repo" && - git init repo && - git -c includeIf.onbranch:nonexistent.path=/does/not/exist init repo && - echo $GIT_DEFAULT_REF_FORMAT >expect && - git -C repo rev-parse --show-ref-format >actual && - test_cmp expect actual -' - test_expect_success 're-init skips non-matching includeIf.onbranch' ' test_when_finished "rm -rf repo config" && cat >config <<-EOF && From 796fda3f786b3cd5518462b46895244dfecad63c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 30 Jan 2025 17:24:18 +0100 Subject: [PATCH 2/3] setup: fix reinit of repos with incompatible GIT_DEFAULT_REF_FORMAT The GIT_DEFAULT_REF_FORMAT environment variable can be set to influence the default ref format that new repostiories shall be initialized with. While this is the expected behaviour when creating a new repository, it is not when reinitializing a repository: we should retain the ref format currently used by it in that case. This doesn't work correctly right now: $ git init --ref-format=files repo Initialized empty Git repository in /tmp/repo/.git/ $ GIT_DEFAULT_REF_FORMAT=reftable git init repo fatal: could not open '/tmp/repo/.git/refs/heads' for writing: Is a directory Instead of retaining the current ref format, the reinitialization tries to reinitialize the repository with the different format. This action fails when git-init(1) tries to write the ".git/refs/heads" stub, which in the context of the reftable backend is always written as a file so that we can detect clients which inadvertently try to access the repo with the wrong ref format. Seems like the protection mechanism works for this case, as well. Fix the issue by ignoring the environment variable in case the repo has already been initialized with a ref storage format. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- setup.c | 4 +++- t/t0001-init.sh | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/setup.c b/setup.c index 8a488f3e7c..53ffeabc5b 100644 --- a/setup.c +++ b/setup.c @@ -2534,7 +2534,9 @@ static void repository_format_configure(struct repository_format *repo_fmt, ref_format = ref_storage_format_by_name(env); if (ref_format == REF_STORAGE_FORMAT_UNKNOWN) die(_("unknown ref storage format '%s'"), env); - repo_fmt->ref_storage_format = ref_format; + if (repo_fmt->version < 0 || + repo_fmt->ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN) + repo_fmt->ref_storage_format = ref_format; } else if (cfg.ref_format != REF_STORAGE_FORMAT_UNKNOWN) { repo_fmt->ref_storage_format = cfg.ref_format; } diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 213d5984b1..6dff8b75f1 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -697,6 +697,15 @@ do git -C refformat rev-parse --show-ref-format >actual && test_cmp expect actual ' + + test_expect_success "reinit repository with GIT_DEFAULT_REF_FORMAT=$format does not change format" ' + test_when_finished "rm -rf refformat" && + git init refformat && + git -C refformat rev-parse --show-ref-format >expect && + GIT_DEFAULT_REF_FORMAT=$format git init refformat && + git -C refformat rev-parse --show-ref-format >actual && + test_cmp expect actual + ' done test_expect_success "--ref-format= overrides GIT_DEFAULT_REF_FORMAT" ' From 7e88640cd1801b6fe0288f744da7310b4749c0c8 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 30 Jan 2025 17:24:19 +0100 Subject: [PATCH 3/3] setup: fix reinit of repos with incompatible GIT_DEFAULT_HASH The exact same issue as described in the preceding commit also exists for GIT_DEFAULT_HASH. Thus, reinitializing a repository that e.g. uses SHA1 with `GIT_DEFAULT_HASH=sha256 git init` will cause the object format of that repository to change to SHA256. This is of course bogus as any existing objects and refs will not be converted, thus causing repository corruption: $ git init repo Initialized empty Git repository in /tmp/repo/.git/ $ cd repo/ $ git commit --allow-empty -m message [main (root-commit) 35a7344] message $ GIT_DEFAULT_HASH=sha256 git init Reinitialized existing Git repository in /tmp/repo/.git/ $ git show fatal: your current branch appears to be broken Fix the issue by ignoring the environment variable in case the repo has already been initialized with an object hash. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- setup.c | 4 +++- t/t0001-init.sh | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/setup.c b/setup.c index 53ffeabc5b..7da7aa8984 100644 --- a/setup.c +++ b/setup.c @@ -2517,7 +2517,9 @@ static void repository_format_configure(struct repository_format *repo_fmt, int env_algo = hash_algo_by_name(env); if (env_algo == GIT_HASH_UNKNOWN) die(_("unknown hash algorithm '%s'"), env); - repo_fmt->hash_algo = env_algo; + if (repo_fmt->version < 0 || + repo_fmt->hash_algo == GIT_HASH_UNKNOWN) + repo_fmt->hash_algo = env_algo; } else if (cfg.hash != GIT_HASH_UNKNOWN) { repo_fmt->hash_algo = cfg.hash; } diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 6dff8b75f1..c49d9e0d38 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -586,6 +586,18 @@ test_expect_success 'GIT_DEFAULT_HASH overrides init.defaultObjectFormat' ' echo sha256 >expected ' +for hash in sha1 sha256 +do + test_expect_success "reinit repository with GIT_DEFAULT_HASH=$hash does not change format" ' + test_when_finished "rm -rf repo" && + git init repo && + git -C repo rev-parse --show-object-format >expect && + GIT_DEFAULT_HASH=$hash git init repo && + git -C repo rev-parse --show-object-format >actual && + test_cmp expect actual + ' +done + test_expect_success 'extensions.objectFormat is not allowed with repo version 0' ' test_when_finished "rm -rf explicit-v0" && git init --object-format=sha256 explicit-v0 &&