]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/init-db: handle bare clones when core.bare set to false
authorbrian m. carlson <sandals@crustytoothpaste.net>
Wed, 10 Mar 2021 01:11:20 +0000 (01:11 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 10 Mar 2021 23:06:48 +0000 (15:06 -0800)
In 552955ed7f ("clone: use more conventional config/option layering",
2020-10-01), clone learned to read configuration options earlier in its
execution, before creating the new repository.  However, that led to a
problem: if the core.bare setting is set to false in the global config,
cloning a bare repository segfaults.  This happens because the
repository is falsely thought to be non-bare, but clone has set the work
tree to NULL, which is then dereferenced.

The code to initialize the repository already considers the fact that a
user might want to override the --bare option for git init, but it
doesn't take into account clone, which uses a different option.  Let's
just check that the work tree is not NULL, since that's how clone
indicates that the repository is bare.  This is also the case for git
init, so we won't be regressing that case.

Reported-by: Joseph Vusich <jvusich@amazon.com>
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/init-db.c
t/t5606-clone-options.sh

index dcc45bef5148117c4b0c3180fcbd94d9f099a1cc..f82efe4aff6dcecb4422d1cb21ae69832719124b 100644 (file)
@@ -212,6 +212,7 @@ static int create_default_files(const char *template_path,
        int reinit;
        int filemode;
        struct strbuf err = STRBUF_INIT;
+       const char *work_tree = get_git_work_tree();
 
        /* Just look for `init.templatedir` */
        init_db_template_dir = NULL; /* re-set in case it was set before */
@@ -235,7 +236,7 @@ static int create_default_files(const char *template_path,
         * We must make sure command-line options continue to override any
         * values we might have just re-read from the config.
         */
-       is_bare_repository_cfg = init_is_bare_repository;
+       is_bare_repository_cfg = init_is_bare_repository || !work_tree;
        if (init_shared_repository != -1)
                set_shared_repository(init_shared_repository);
 
@@ -299,7 +300,6 @@ static int create_default_files(const char *template_path,
        if (is_bare_repository())
                git_config_set("core.bare", "true");
        else {
-               const char *work_tree = get_git_work_tree();
                git_config_set("core.bare", "false");
                /* allow template config file to override the default */
                if (log_all_ref_updates == LOG_REFS_UNSET)
index 7f082fb23b6af9292b279f9db129b8eb23a6e94b..88349343e8a6400603c8699c88edb1be669d9c45 100755 (executable)
@@ -101,6 +101,14 @@ test_expect_success 'redirected clone -v does show progress' '
 
 '
 
+test_expect_success 'clone does not segfault with --bare and core.bare=false' '
+       test_config_global core.bare false &&
+       git clone --bare parent clone-bare &&
+       echo true >expect &&
+       git -C clone-bare rev-parse --is-bare-repository >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'chooses correct default initial branch name' '
        git init --bare empty &&
        GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \