[PATCH v5 2/2] setup: allow cwd/.git to be a symlink to a directory
- From
Tian Yuchen <a3205153416@gmail.com>
- Date
- Feb 18, 2026, 05:18 UTC
- Message-ID
- <20260218051850.164972-3-a3205153416@gmail.com>
- In-Reply-To
- <20260218051850.164972-1-a3205153416@gmail.com>
Strictly enforcing 'lstat()' prevents valid '.git' symlinks.
Switch 'setup_git_directory_gently_1()' to use 'stat()' to allow filesystem resolution.
Calling the refactored 'read_gitfile_error_die()' to ensure safety:
1. Happy cases ('ENOENT', 'IS_A_DIR') are ignored automatically;
2. Invalid types (like FIFOs and sockets) trigger 'die()' via
'NOT_A_FILE'.Add 't/t0009-git-dir-validation.sh' to verify symlink support and FIFO rejection, and register it in 't/meson.build'.
Signed-off-by: Tian Yuchen <a3205153416@gmail.com> --- setup.c | 18 ++++----- t/meson.build | 1 + t/t0009-git-dir-validation.sh | 72 +++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 10 deletions(-) create mode 100755 t/t0009-git-dir-validation.sh
diff --git a/setup.c b/setup.c index 0ca129623e..6e6068e5eb 100644 --- a/setup.c +++ b/setup.c @@ -1590,17 +1590,15 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir, gitdirenv = read_gitfile_gently(dir->buf, die_on_error ? NULL : &error_code); if (!gitdirenv) { - if (die_on_error || - error_code == READ_GITFILE_ERR_NOT_A_FILE) { - /* NEEDSWORK: fail if .git is not file nor dir */ - if (is_git_directory(dir->buf)) { - gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT; - gitdir_path = xstrdup(dir->buf); - } - } else if (error_code != READ_GITFILE_ERR_STAT_FAILED) - return GIT_DIR_INVALID_GITFILE; - } else + if (error_code) + read_gitfile_error_die(error_code, dir->buf, NULL); + if (is_git_directory(dir->buf)) { + gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT; + gitdir_path = xstrdup(dir->buf); + } + } else { gitfile = xstrdup(dir->buf); + } /* * Earlier, we tentatively added DEFAULT_GIT_DIR_ENVIRONMENT * to check that directory for a repository. diff --git a/t/meson.build b/t/meson.build index f80e366cff..c4afaacee5 100644 --- a/t/meson.build +++ b/t/meson.build @@ -80,6 +80,7 @@ integration_tests = [ 't0006-date.sh', 't0007-git-var.sh', 't0008-ignores.sh', + 't0009-git-dir-validation.sh', 't0010-racy-git.sh', 't0012-help.sh', 't0013-sha1dc.sh', diff --git a/t/t0009-git-dir-validation.sh b/t/t0009-git-dir-validation.sh new file mode 100755 index 0000000000..9b3925c85f --- /dev/null +++ b/t/t0009-git-dir-validation.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +test_description='setup: validation of .git file/directory types + +Verify that setup_git_directory() correctly handles: +1. Valid .git directories (including symlinks to them). +2. Invalid .git files (FIFOs, sockets) by erroring out. +3. Invalid .git files (garbage) by erroring out. +' + +. ./test-lib.sh + +test_expect_success 'setup: create parent git repository' ' + git init parent && + test_commit -C parent "root-commit" +' + +test_expect_success SYMLINKS 'setup: .git as a symlink to a directory is valid' ' + mkdir -p parent/link-to-dir && + ( + cd parent/link-to-dir && + git init real-repo && + ln -s real-repo/.git .git && + git rev-parse --git-dir >actual && + echo .git >expect && + test_cmp expect actual + ) +' + +test_expect_success PIPE 'setup: .git as a FIFO (named pipe) is rejected' ' + mkdir -p parent/fifo-trap && + ( + cd parent/fifo-trap && + mkfifo .git && + test_must_fail git rev-parse --git-dir 2>stderr && + grep "not a regular file" stderr + ) +' + +test_expect_success SYMLINKS,PIPE 'setup: .git as a symlink to a FIFO is rejected' ' + mkdir -p parent/symlink-fifo-trap && + ( + cd parent/symlink-fifo-trap && + mkfifo target-fifo && + ln -s target-fifo .git && + test_must_fail git rev-parse --git-dir 2>stderr && + grep "not a regular file" stderr + ) +' + +test_expect_success 'setup: .git with garbage content is rejected' ' + mkdir -p parent/garbage-trap && + ( + cd parent/garbage-trap && + echo "garbage" >.git && + test_must_fail git rev-parse --git-dir 2>stderr && + grep "invalid gitfile format" stderr + ) +' + +test_expect_success 'setup: .git as an empty directory is ignored' ' + mkdir -p parent/empty-dir && + ( + cd parent/empty-dir && + mkdir .git && + git rev-parse --git-dir >actual && + echo "$TRASH_DIRECTORY/parent/.git" >expect && + test_cmp expect actual + ) +' + +test_done
-- 2.43.0