From ce70cbc294f2f1f9a853307d35a78baa16207e58 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 19 May 2026 11:52:06 +0200 Subject: [PATCH] setup: stop using `the_repository` in `is_inside_git_dir()` The function `is_inside_git_dir()` verifies whether or not the current working directory is located inside the gitdir of `the_repository`. This is done by taking the gitdir path and verifying that it's a prefix of the current working directory. This information is cached so that we don't have to re-do this change multiple times. Furthermore, we proactively set the value in multiple locations so that we don't even have to perform the check when we have discovered the repository. While we could simply move the caching variable into the repository, the current layout doesn't really feel sensible in the first place: - It can easily lead to false positives or negatives if at any point in time we may switch the current working directory. - We don't call the function in a hot loop, and neither is it overly expensive to compute. Drop the caching infrastructure and instead compute the property ad-hoc via an injected repository. Note that there is one small gotcha: we often end up with relative gitdir paths, and if so `is_inside_dir()` might fail. This wasn't an issue before because of how we proactively set the cached value during repository discovery. Now that we stop doing that it becomes a problem though, which we work around by resolving the gitdir via `realpath()`. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/rev-parse.c | 2 +- setup.c | 14 ++++++-------- setup.h | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 218b5f34d6..a216be63cf 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -1063,7 +1063,7 @@ int cmd_rev_parse(int argc, continue; } if (!strcmp(arg, "--is-inside-git-dir")) { - printf("%s\n", is_inside_git_dir() ? "true" + printf("%s\n", is_inside_git_dir(the_repository) ? "true" : "false"); continue; } diff --git a/setup.c b/setup.c index ba2898473a..80f3ba0d62 100644 --- a/setup.c +++ b/setup.c @@ -26,7 +26,6 @@ #include "trace2.h" #include "worktree.h" -static int inside_git_dir = -1; static int inside_work_tree = -1; static int work_tree_config_is_bogus; enum allowed_bare_repo { @@ -299,7 +298,7 @@ void verify_filename(const char *prefix, */ void verify_non_filename(const char *prefix, const char *arg) { - if (!is_inside_work_tree() || is_inside_git_dir()) + if (!is_inside_work_tree() || is_inside_git_dir(the_repository)) return; if (*arg == '-') return; /* flag */ @@ -470,11 +469,12 @@ int is_nonbare_repository_dir(struct strbuf *path) return ret; } -int is_inside_git_dir(void) +int is_inside_git_dir(struct repository *repo) { - if (inside_git_dir < 0) - inside_git_dir = is_inside_dir(repo_get_git_dir(the_repository)); - return inside_git_dir; + struct strbuf buf = STRBUF_INIT; + int ret = is_inside_dir(strbuf_realpath(&buf, repo_get_git_dir(repo), 1)); + strbuf_release(&buf); + return ret; } int is_inside_work_tree(void) @@ -1251,7 +1251,6 @@ static const char *setup_discovered_git_dir(struct repository *repo, set_git_work_tree("."); if (strcmp(gitdir, DEFAULT_GIT_DIR_ENVIRONMENT)) set_git_dir(repo, gitdir, 0); - inside_git_dir = 0; inside_work_tree = 1; if (offset >= cwd->len) return NULL; @@ -1287,7 +1286,6 @@ static const char *setup_bare_git_dir(struct repository *repo, return setup_explicit_git_dir(repo, gitdir, cwd, repo_fmt, nongit_ok); } - inside_git_dir = 1; inside_work_tree = 0; if (offset != cwd->len) { if (chdir(cwd->buf)) diff --git a/setup.h b/setup.h index 80bc6e5f07..115bda647c 100644 --- a/setup.h +++ b/setup.h @@ -4,7 +4,7 @@ #include "refs.h" #include "string-list.h" -int is_inside_git_dir(void); +int is_inside_git_dir(struct repository *repo); int is_inside_work_tree(void); int get_common_dir_noenv(struct strbuf *sb, const char *gitdir); int get_common_dir(struct strbuf *sb, const char *gitdir);