diff options
| author | Tian Yuchen <a3205153416@gmail.com> | 2026-03-04 22:15:26 +0800 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2026-03-04 09:23:48 -0800 |
| commit | 1dd27bfbfdc0f3b2071ecb8b505476f4caa56a13 (patch) | |
| tree | 1af307b75631d8e12873ffb9440f6c0f8927a250 /setup.c | |
| parent | 67ad42147a7acc2af6074753ebd03d904476118f (diff) | |
| download | git-1dd27bfbfdc0f3b2071ecb8b505476f4caa56a13.tar.xz | |
setup: improve error diagnosis for invalid .git files
'read_gitfile_gently()' treats any non-regular file as
'READ_GITFILE_ERR_NOT_A_FILE' and fails to discern between 'ENOENT'
and other stat failures. This flawed error reporting is noted by two
'NEEDSWORK' comments.
Address these comments by introducing two new error codes:
'READ_GITFILE_ERR_MISSING'(which groups the "file missing" scenarios
together) and 'READ_GITFILE_ERR_IS_A_DIR':
1. Update 'read_gitfile_error_die()' to treat 'IS_A_DIR', 'MISSING',
'NOT_A_FILE' and 'STAT_FAILED' as non-fatal no-ops. This accommodates
intentional non-repo scenarios (e.g., GIT_DIR=/dev/null).
2. Explicitly catch 'NOT_A_FILE' and 'STAT_FAILED' during
discovery and call 'die()' if 'die_on_error' is set.
3. Unconditionally pass '&error_code' to 'read_gitfile_gently()'.
4. Only invoke 'is_git_directory()' when we explicitly receive
'READ_GITFILE_ERR_IS_A_DIR', avoiding redundant checks.
Additionally, audit external callers of 'read_gitfile_gently()' in
'submodule.c' and 'worktree.c' to accommodate the refined error codes.
Signed-off-by: Tian Yuchen <a3205153416@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'setup.c')
| -rw-r--r-- | setup.c | 47 |
1 files changed, 36 insertions, 11 deletions
@@ -895,8 +895,10 @@ int verify_repository_format(const struct repository_format *format, void read_gitfile_error_die(int error_code, const char *path, const char *dir) { switch (error_code) { - case READ_GITFILE_ERR_STAT_FAILED: case READ_GITFILE_ERR_NOT_A_FILE: + case READ_GITFILE_ERR_STAT_FAILED: + case READ_GITFILE_ERR_MISSING: + case READ_GITFILE_ERR_IS_A_DIR: /* non-fatal; follow return path */ break; case READ_GITFILE_ERR_OPEN_FAILED: @@ -939,8 +941,14 @@ const char *read_gitfile_gently(const char *path, int *return_error_code) static struct strbuf realpath = STRBUF_INIT; if (stat(path, &st)) { - /* NEEDSWORK: discern between ENOENT vs other errors */ - error_code = READ_GITFILE_ERR_STAT_FAILED; + if (errno == ENOENT || errno == ENOTDIR) + error_code = READ_GITFILE_ERR_MISSING; + else + error_code = READ_GITFILE_ERR_STAT_FAILED; + goto cleanup_return; + } + if (S_ISDIR(st.st_mode)) { + error_code = READ_GITFILE_ERR_IS_A_DIR; goto cleanup_return; } if (!S_ISREG(st.st_mode)) { @@ -1576,20 +1584,37 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir, if (offset > min_offset) strbuf_addch(dir, '/'); strbuf_addstr(dir, DEFAULT_GIT_DIR_ENVIRONMENT); - gitdirenv = read_gitfile_gently(dir->buf, die_on_error ? - NULL : &error_code); + gitdirenv = read_gitfile_gently(dir->buf, &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 */ + switch (error_code) { + case READ_GITFILE_ERR_MISSING: + /* no .git in this directory, move on */ + break; + case READ_GITFILE_ERR_IS_A_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 + break; + case READ_GITFILE_ERR_STAT_FAILED: + if (die_on_error) + die(_("error reading '%s'"), dir->buf); + else + return GIT_DIR_INVALID_GITFILE; + case READ_GITFILE_ERR_NOT_A_FILE: + if (die_on_error) + die(_("not a regular file: '%s'"), dir->buf); + else + return GIT_DIR_INVALID_GITFILE; + default: + if (die_on_error) + read_gitfile_error_die(error_code, dir->buf, NULL); + else + return GIT_DIR_INVALID_GITFILE; + } + } else { gitfile = xstrdup(dir->buf); + } /* * Earlier, we tentatively added DEFAULT_GIT_DIR_ENVIRONMENT * to check that directory for a repository. |
