The object format for repositories can either be configured explicitly by passing the `--object-format=` option to git-init(1) or git-clone(1), or globally by setting the `GIT_DEFAULT_HASH` environment variable. While the former makes sense, setting random environment variables is not really a good user experience in case someone decides to only use SHA256 repositories. It is only natural to expect for a user that things like this can also be configured via their config. As such, introduce a new config "init.defaultObjectFormat", similar to "init.defaultBranch", that allows the user to configure the default object format when creating new repos. Signed-off-by: Patrick Steinhardt <ps@xxxxxx> --- Documentation/config/init.txt | 5 ++++ setup.c | 40 ++++++++++++++++++++++++++++ t/t0001-init.sh | 50 +++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/Documentation/config/init.txt b/Documentation/config/init.txt index af03acdbcb..d6f8b6e61b 100644 --- a/Documentation/config/init.txt +++ b/Documentation/config/init.txt @@ -8,3 +8,8 @@ endif::[] `init.defaultBranch`:: Allows overriding the default branch name e.g. when initializing a new repository. +`init.defaultObjectFormat`:: + Allows overriding the default object format for new repositories. See + `--object-format=` in linkgit:git-init[1]. Both the command line option + and the `GIT_DEFAULT_HASH` environment variable take precedence over + this config. diff --git a/setup.c b/setup.c index 5dfcdc99dd..770ad1393f 100644 --- a/setup.c +++ b/setup.c @@ -2284,11 +2284,49 @@ static void separate_git_dir(const char *git_dir, const char *git_link) write_file(git_link, "gitdir: %s", git_dir); } +struct default_format_config { + int hash; +}; + +static int read_default_format_config(const char *key, const char *value, + const struct config_context *ctx UNUSED, + void *payload) +{ + struct default_format_config *cfg = payload; + char *str = NULL; + int ret; + + if (!strcmp(key, "init.defaultobjectformat")) { + ret = git_config_string(&str, key, value); + if (ret) + goto out; + cfg->hash = hash_algo_by_name(str); + if (cfg->hash == GIT_HASH_UNKNOWN) + warning(_("unknown hash algorithm '%s'"), str); + goto out; + } + + ret = 0; +out: + free(str); + return ret; +} + static void repository_format_configure(struct repository_format *repo_fmt, int hash, enum ref_storage_format ref_format) { + struct default_format_config cfg = { + .hash = GIT_HASH_UNKNOWN, + }; + struct config_options opts = { + .respect_includes = 1, + .ignore_repo = 1, + .ignore_worktree = 1, + }; const char *env; + config_with_options(read_default_format_config, &cfg, NULL, NULL, &opts); + /* * If we already have an initialized repo, don't allow the user to * specify a different algorithm, as that could cause corruption. @@ -2304,6 +2342,8 @@ static void repository_format_configure(struct repository_format *repo_fmt, if (env_algo == GIT_HASH_UNKNOWN) die(_("unknown hash algorithm '%s'"), env); repo_fmt->hash_algo = env_algo; + } else if (cfg.hash != GIT_HASH_UNKNOWN) { + repo_fmt->hash_algo = cfg.hash; } repo_set_hash_algo(the_repository, repo_fmt->hash_algo); diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 795408e16c..cd34710f32 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -523,6 +523,56 @@ test_expect_success 'init honors --object-format' ' test_cmp expected actual ' +test_expect_success 'init honors init.defaultObjectFormat' ' + test_when_finished "rm -rf sha1 sha256" && + + test_config_global init.defaultObjectFormat sha1 && + ( + sane_unset GIT_DEFAULT_HASH && + git init sha1 && + git -C sha1 rev-parse --show-object-format >actual && + echo sha1 >expected && + test_cmp expected actual + ) && + + test_config_global init.defaultObjectFormat sha256 && + ( + sane_unset GIT_DEFAULT_HASH && + git init sha256 && + git -C sha256 rev-parse --show-object-format >actual && + echo sha256 >expected && + test_cmp expected actual + ) +' + +test_expect_success 'init warns about invalid init.defaultObjectFormat' ' + test_when_finished "rm -rf repo" && + test_config_global init.defaultObjectFormat garbage && + + echo "warning: unknown hash algorithm ${SQ}garbage${SQ}" >expect && + git init repo 2>err && + test_cmp expect err && + + git -C repo rev-parse --show-object-format >actual && + echo $GIT_DEFAULT_HASH >expected && + test_cmp expected actual +' + +test_expect_success '--object-format overrides GIT_DEFAULT_HASH' ' + test_when_finished "rm -rf repo" && + GIT_DEFAULT_HASH=sha1 git init --object-format=sha256 repo && + git -C repo rev-parse --show-object-format >actual && + echo sha256 >expected +' + +test_expect_success 'GIT_DEFAULT_HASH overrides init.defaultObjectFormat' ' + test_when_finished "rm -rf repo" && + test_config_global init.defaultObjectFormat sha1 && + GIT_DEFAULT_HASH=sha256 git init repo && + git -C repo rev-parse --show-object-format >actual && + echo sha256 >expected +' + 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 && -- 2.46.0.46.g406f326d27.dirty