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 <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed May 19, 2026 at 11:52 UTC ce70cbc294f2f1f9a853307d35a78baa16207e58
3 files changed +8 -10
builtin/rev-parse.c
+1 -1
@@ -1063,7 +1063,7 @@ int cmd_rev_parse(int argc,
1063 continue;
1064 }
1065 if (!strcmp(arg, "--is-inside-git-dir")) {
1066 - printf("%s\n", is_inside_git_dir() ? "true"
1066 + printf("%s\n", is_inside_git_dir(the_repository) ? "true"
1067 : "false");
1068 continue;
1069 }
setup.c
+6 -8
@@ -26,7 +26,6 @@
26 #include "trace2.h"
27 #include "worktree.h"
28
29 -static int inside_git_dir = -1;
29 static int inside_work_tree = -1;
30 static int work_tree_config_is_bogus;
31 enum allowed_bare_repo {
@@ -299,7 +298,7 @@ void verify_filename(const char *prefix,
298 */
299 void verify_non_filename(const char *prefix, const char *arg)
300 {
302 - if (!is_inside_work_tree() || is_inside_git_dir())
301 + if (!is_inside_work_tree() || is_inside_git_dir(the_repository))
302 return;
303 if (*arg == '-')
304 return; /* flag */
@@ -470,11 +469,12 @@ int is_nonbare_repository_dir(struct strbuf *path)
469 return ret;
470 }
471
473 -int is_inside_git_dir(void)
472 +int is_inside_git_dir(struct repository *repo)
473 {
475 - if (inside_git_dir < 0)
476 - inside_git_dir = is_inside_dir(repo_get_git_dir(the_repository));
477 - return inside_git_dir;
474 + struct strbuf buf = STRBUF_INIT;
475 + int ret = is_inside_dir(strbuf_realpath(&buf, repo_get_git_dir(repo), 1));
476 + strbuf_release(&buf);
477 + return ret;
478 }
479
480 int is_inside_work_tree(void)
@@ -1251,7 +1251,6 @@ static const char *setup_discovered_git_dir(struct repository *repo,
1251 set_git_work_tree(".");
1252 if (strcmp(gitdir, DEFAULT_GIT_DIR_ENVIRONMENT))
1253 set_git_dir(repo, gitdir, 0);
1254 - inside_git_dir = 0;
1254 inside_work_tree = 1;
1255 if (offset >= cwd->len)
1256 return NULL;
@@ -1287,7 +1286,6 @@ static const char *setup_bare_git_dir(struct repository *repo,
1286 return setup_explicit_git_dir(repo, gitdir, cwd, repo_fmt, nongit_ok);
1287 }
1288
1290 - inside_git_dir = 1;
1289 inside_work_tree = 0;
1290 if (offset != cwd->len) {
1291 if (chdir(cwd->buf))
setup.h
+1 -1
@@ -4,7 +4,7 @@
4 #include "refs.h"
5 #include "string-list.h"
6
7 -int is_inside_git_dir(void);
7 +int is_inside_git_dir(struct repository *repo);
8 int is_inside_work_tree(void);
9 int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
10 int get_common_dir(struct strbuf *sb, const char *gitdir);