Revert "check_repository_format_gently(): refuse extensions for old repositories"

This reverts commit 14c7fa269e.

The core.repositoryFormatVersion field was introduced in ab9cb76f66
(Repository format version check., 2005-11-25), providing a welcome
bit of forward compatibility, thanks to some welcome analysis by
Martin Atukunda.  The semantics are simple: a repository with
core.repositoryFormatVersion set to 0 should be comprehensible by all
Git implementations in active use; and Git implementations should
error out early instead of trying to act on Git repositories with
higher core.repositoryFormatVersion values representing new formats
that they do not understand.

A new repository format did not need to be defined until 00a09d57eb
(introduce "extensions" form of core.repositoryformatversion,
2015-06-23).  This provided a finer-grained extension mechanism for
Git repositories.  In a repository with core.repositoryFormatVersion
set to 1, Git implementations can act on "extensions.*" settings that
modify how a repository is interpreted.  In repository format version
1, unrecognized extensions settings cause Git to error out.

What happens if a user sets an extension setting but forgets to
increase the repository format version to 1?  The extension settings
were still recognized in that case; worse, unrecognized extensions
settings do *not* cause Git to error out.  So combining repository
format version 0 with extensions settings produces in some sense the
worst of both worlds.

To improve that situation, since 14c7fa269e
(check_repository_format_gently(): refuse extensions for old
repositories, 2020-06-05) Git instead ignores extensions in v0 mode.
This way, v0 repositories get the historical (pre-2015) behavior and
maintain compatibility with Git implementations that do not know about
the v1 format.  Unfortunately, users had been using this sort of
configuration and this behavior change came to many as a surprise:

- users of "git config --worktree" that had followed its advice
  to enable extensions.worktreeConfig (without also increasing the
  repository format version) would find their worktree configuration
  no longer taking effect

- tools such as copybara[*] that had set extensions.partialClone in
  existing repositories (without also increasing the repository format
  version) would find that setting no longer taking effect

The behavior introduced in 14c7fa269e might be a good behavior if we
were traveling back in time to 2015, but we're far too late.  For some
reason I thought that it was what had been originally implemented and
that it had regressed.  Apologies for not doing my research when
14c7fa269e was under development.

Let's return to the behavior we've had since 2015: always act on
extensions.* settings, regardless of repository format version.  While
we're here, include some tests to describe the effect on the "upgrade
repository version" code path.

[*] ca76c0b1e1

Reported-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jonathan Nieder 2020-07-15 23:24:29 -07:00 committed by Junio C Hamano
parent 14c7fa269e
commit 11664196ac
2 changed files with 16 additions and 11 deletions

12
setup.c
View File

@ -507,15 +507,9 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
die("%s", err.buf); die("%s", err.buf);
} }
if (candidate->version >= 1) { repository_format_precious_objects = candidate->precious_objects;
repository_format_precious_objects = candidate->precious_objects; set_repository_format_partial_clone(candidate->partial_clone);
set_repository_format_partial_clone(candidate->partial_clone); repository_format_worktree_config = candidate->worktree_config;
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) {

View File

@ -42,14 +42,25 @@ test_expect_success 'convert shallow clone to partial clone' '
test_cmp_config -C client 1 core.repositoryformatversion test_cmp_config -C client 1 core.repositoryformatversion
' '
test_expect_success 'convert shallow clone to partial clone must fail with any extension' ' test_expect_success 'converting to partial clone fails with noop extension' '
rm -fr server client && rm -fr server client &&
test_create_repo server && test_create_repo server &&
test_commit -C server my_commit 1 && test_commit -C server my_commit 1 &&
test_commit -C server my_commit2 1 && test_commit -C server my_commit2 1 &&
git clone --depth=1 "file://$(pwd)/server" client && git clone --depth=1 "file://$(pwd)/server" client &&
test_cmp_config -C client 0 core.repositoryformatversion && test_cmp_config -C client 0 core.repositoryformatversion &&
git -C client config extensions.partialclone origin && git -C client config extensions.noop true &&
test_must_fail git -C client fetch --unshallow --filter="blob:none"
'
test_expect_success 'converting to partial clone fails with unrecognized 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.nonsense true &&
test_must_fail git -C client fetch --unshallow --filter="blob:none" test_must_fail git -C client fetch --unshallow --filter="blob:none"
' '