]> git.ipfire.org Git - thirdparty/git.git/commitdiff
setup: stop using `the_repository` in `setup_work_tree()`
authorPatrick Steinhardt <ps@pks.im>
Tue, 19 May 2026 09:52:13 +0000 (11:52 +0200)
committerJunio C Hamano <gitster@pobox.com>
Tue, 19 May 2026 10:36:24 +0000 (19:36 +0900)
Stop using `the_repository` in `setup_work_tree()` and instead accept
the repository as a parameter. The injection of `the_repository` is thus
bumped one level higher, where callers now pass it in explicitly.

Note that the function tracks two bits of information via global
variables. This of course doesn't make much sense anymore now that we
can set up worktrees for arbitrary repositories:

  - We track whether the worktree has already been initialized and, if
    so, we skip the call to `chdir_notify()` and setenv(3p). It does not
    make much sense to store this info in the repository, as we _would_
    want to update the environment when switching between worktrees back
    and forth.

    So instead of storing this info in the repository, we drop this
    state entirely and live with the fact that we may execute the logic
    twice. It should ultimately be idempotent though and thus not be
    much of a problem.

  - We track whether the worktree configuration is bogus. If so, and if
    later on some caller tries to setup the worktree, then we'll die
    instead. This is indeed information that we can move into the
    repository itself.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
21 files changed:
blame.c
builtin/check-attr.c
builtin/clone.c
builtin/describe.c
builtin/diff-index.c
builtin/diff.c
builtin/difftool.c
builtin/grep.c
builtin/ls-files.c
builtin/read-tree.c
builtin/reset.c
builtin/rm.c
builtin/sparse-checkout.c
builtin/submodule--helper.c
builtin/update-index.c
git.c
repository.h
setup.c
setup.h
t/helper/test-subprocess.c
wt-status.c

diff --git a/blame.c b/blame.c
index a3c49d132e4ae1c7bc67b1d1c110e2d87099aa25..977cbb70974f8c345356c0c930223c6cd8383337 100644 (file)
--- a/blame.c
+++ b/blame.c
@@ -2813,7 +2813,7 @@ void setup_scoreboard(struct blame_scoreboard *sb,
                }
 
                if (!sb->contents_from)
-                       setup_work_tree();
+                       setup_work_tree(the_repository);
 
                sb->final = fake_working_tree_commit(sb->repo,
                                                     &sb->revs->diffopt,
index 04b86e42ae66ca544ef45a486986f4081d5132f1..98f64d5b922e6cccfd9e982488783b103843c098 100644 (file)
@@ -117,7 +117,7 @@ int cmd_check_attr(int argc,
        int cnt, i, doubledash, filei;
 
        if (!is_bare_repository())
-               setup_work_tree();
+               setup_work_tree(the_repository);
 
        repo_config(the_repository, git_default_config, NULL);
 
index d23b0cafcfec308e15453253fdddfccd970b8e74..09f6d976587cab3e1c749c90c4e72e1c8efc9029 100644 (file)
@@ -669,7 +669,7 @@ static int checkout(int submodule_progress,
        }
 
        /* We need to be in the new work tree for the checkout */
-       setup_work_tree();
+       setup_work_tree(the_repository);
 
        repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
 
index bffeed13a3cb14d7ce738597460c29556fe8aa2a..1c47d7c0b7c38d23032179fb5b0800d7170c4aeb 100644 (file)
@@ -781,7 +781,7 @@ int cmd_describe(int argc,
                        struct rev_info revs;
                        int fd;
 
-                       setup_work_tree();
+                       setup_work_tree(the_repository);
                        prepare_repo_settings(the_repository);
                        the_repository->settings.command_requires_full_index = 0;
                        repo_read_index(the_repository);
index 522dacfc4cf09739cc31d691c474d2f3b20b7665..3db7cffede578c6f6a82f48dcc2df2f1a334a1d9 100644 (file)
@@ -69,7 +69,7 @@ int cmd_diff_index(int argc,
            rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)
                usage(diff_cache_usage);
        if (!(option & DIFF_INDEX_CACHED)) {
-               setup_work_tree();
+               setup_work_tree(the_repository);
                if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0) {
                        perror("repo_read_index_preload");
                        return -1;
index 7ddebce2ac7cecc558c51595a9e13624a355a1eb..1ede873ac1895df335e8cae4f6ee707520aea39c 100644 (file)
@@ -159,7 +159,7 @@ static void builtin_diff_index(struct rev_info *revs,
            revs->max_age != -1)
                usage(builtin_diff_usage);
        if (!(option & DIFF_INDEX_CACHED)) {
-               setup_work_tree();
+               setup_work_tree(the_repository);
                if (repo_read_index_preload(the_repository,
                                            &revs->diffopt.pathspec, 0) < 0) {
                        die_errno("repo_read_index_preload");
@@ -281,7 +281,7 @@ static void builtin_diff_files(struct rev_info *revs, int argc, const char **arg
            (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
                diff_merges_set_dense_combined_if_unset(revs);
 
-       setup_work_tree();
+       setup_work_tree(the_repository);
        if (repo_read_index_preload(the_repository, &revs->diffopt.pathspec,
                                    0) < 0) {
                die_errno("repo_read_index_preload");
index e4bc1f831696a8eace3931567d815fb4fd794b88..2a21005f2ee26489d8e2a5d0b7d0d4eaa6a8bdae 100644 (file)
@@ -767,7 +767,7 @@ int cmd_difftool(int argc,
                die(_("difftool requires worktree or --no-index"));
 
        if (!no_index){
-               setup_work_tree();
+               setup_work_tree(repo);
                setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(repo)), 1);
                setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(repo)), 1);
        } else if (dir_diff)
index 4ec0c016b1f11cebed076b22f4b0fb599a07d08e..679f8b567a15782efb0f9377f81d29d37bab97cf 100644 (file)
@@ -1272,7 +1272,7 @@ int cmd_grep(int argc,
                die(_("--[no-]exclude-standard cannot be used for tracked contents"));
        } else if (!list.nr) {
                if (!cached)
-                       setup_work_tree();
+                       setup_work_tree(the_repository);
 
                hit = grep_cache(&opt, &pathspec, cached);
        } else {
index 09d95111b35b9f5032721d8b21cad3d8363fe2a2..e1a22b41b94c08383ef342cc878949fd47f7921a 100644 (file)
@@ -704,7 +704,7 @@ int cmd_ls_files(int argc,
                exc_given = 1;
 
        if (require_work_tree && !is_inside_work_tree(repo))
-               setup_work_tree();
+               setup_work_tree(repo);
 
        if (recurse_submodules &&
            (show_deleted || show_others || show_unmerged ||
index 460b21e40ac914cd43a439064d537c9b3dd35a19..999a82ecdfd7374a9ebbee67692c5b0676ea88e2 100644 (file)
@@ -229,7 +229,7 @@ int cmd_read_tree(int argc,
                opts.preserve_ignored = 0;
        /* otherwise, opts.preserve_ignored is irrelevant */
        if (opts.merge && !opts.index_only)
-               setup_work_tree();
+               setup_work_tree(the_repository);
 
        if (opts.skip_sparse_checkout)
                ensure_full_index(the_repository->index);
index 11f57605b510aee87c30787ea3ee01f998b836f4..3be6bd0121afe5094c8e7e7b011ef589391452f8 100644 (file)
@@ -468,7 +468,7 @@ int cmd_reset(int argc,
                trace2_cmd_mode(reset_type_names[reset_type]);
 
        if (reset_type != SOFT && (reset_type != MIXED || repo_get_work_tree(the_repository)))
-               setup_work_tree();
+               setup_work_tree(the_repository);
 
        if (reset_type == MIXED && is_bare_repository())
                die(_("%s reset is not allowed in a bare repository"),
index 05d89e98c3c6b80d8542ecfaefe51859cb072334..081d0bc3754c52bfee8c6ba19b06e748e452b899 100644 (file)
@@ -296,7 +296,7 @@ int cmd_rm(int argc,
                die(_("No pathspec was given. Which files should I remove?"));
 
        if (!index_only)
-               setup_work_tree();
+               setup_work_tree(the_repository);
 
        prepare_repo_settings(the_repository);
        the_repository->settings.command_requires_full_index = 0;
index 2af50fb2f9cb22563a1ea57db254a9ebf80d407b..d89acbeb533bd80e49e7a0ed8dabd9e13fc112eb 100644 (file)
@@ -63,7 +63,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,
        int res;
        struct repo_config_values *cfg = repo_config_values(the_repository);
 
-       setup_work_tree();
+       setup_work_tree(the_repository);
        if (!cfg->apply_sparse_checkout)
                die(_("this worktree is not sparse"));
 
@@ -229,7 +229,7 @@ static int update_working_directory(struct repository *r,
        o.dst_index = r->index;
        o.skip_sparse_checkout = 0;
 
-       setup_work_tree();
+       setup_work_tree(the_repository);
 
        repo_hold_locked_index(r, &lock_file, LOCK_DIE_ON_ERROR);
 
@@ -468,7 +468,7 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix,
                OPT_END(),
        };
 
-       setup_work_tree();
+       setup_work_tree(the_repository);
        repo_read_index(repo);
 
        init_opts.cone_mode = -1;
@@ -802,7 +802,7 @@ static int sparse_checkout_add(int argc, const char **argv, const char *prefix,
        int ret;
        struct repo_config_values *cfg = repo_config_values(the_repository);
 
-       setup_work_tree();
+       setup_work_tree(the_repository);
        if (!cfg->apply_sparse_checkout)
                die(_("no sparse-checkout to add to"));
 
@@ -856,7 +856,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix,
        struct strvec patterns = STRVEC_INIT;
        int ret;
 
-       setup_work_tree();
+       setup_work_tree(the_repository);
        repo_read_index(repo);
 
        set_opts.cone_mode = -1;
@@ -912,7 +912,7 @@ static int sparse_checkout_reapply(int argc, const char **argv,
        };
        struct repo_config_values *cfg = repo_config_values(the_repository);
 
-       setup_work_tree();
+       setup_work_tree(the_repository);
        if (!cfg->apply_sparse_checkout)
                die(_("must be in a sparse-checkout to reapply sparsity patterns"));
 
@@ -975,7 +975,7 @@ static int sparse_checkout_clean(int argc, const char **argv,
                OPT_END(),
        };
 
-       setup_work_tree();
+       setup_work_tree(the_repository);
        if (!cfg->apply_sparse_checkout)
                die(_("must be in a sparse-checkout to clean directories"));
        if (!core_sparse_checkout_cone)
@@ -1053,7 +1053,7 @@ static int sparse_checkout_disable(int argc, const char **argv,
         * forcibly return to a dense checkout regardless of initial state.
         */
 
-       setup_work_tree();
+       setup_work_tree(the_repository);
        argc = parse_options(argc, argv, prefix,
                             builtin_sparse_checkout_disable_options,
                             builtin_sparse_checkout_disable_usage, 0);
index 2f589e3b378d3f6f25ce620caaeb0dfba4582f62..1cc82a134db22e35e095dae1602953f0a48ec2de 100644 (file)
@@ -1250,7 +1250,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
 
        if (!info->cached) {
                if (diff_cmd == DIFF_INDEX)
-                       setup_work_tree();
+                       setup_work_tree(the_repository);
                if (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0) {
                        perror("repo_read_index_preload");
                        ret = -1;
index 7434112b8e69b0df64ba156f381bd4f16ab22915..d6dabacfd1275d41612a9d3344f859f3c9fcd48e 100644 (file)
@@ -732,7 +732,7 @@ struct refresh_params {
 
 static int refresh(struct refresh_params *o, unsigned int flag)
 {
-       setup_work_tree();
+       setup_work_tree(the_repository);
        repo_read_index(the_repository);
        *o->has_errors |= refresh_index(the_repository->index, o->flags | flag, NULL,
                                        NULL, NULL);
@@ -901,7 +901,7 @@ static enum parse_opt_result reupdate_callback(
        BUG_ON_OPT_ARG(arg);
 
        /* consume remaining arguments. */
-       setup_work_tree();
+       setup_work_tree(the_repository);
        *has_errors = do_reupdate(ctx->argv + 1, prefix);
        if (*has_errors)
                the_repository->index->cache_changed = 0;
@@ -1157,7 +1157,7 @@ int cmd_update_index(int argc,
                                transaction = NULL;
                        }
 
-                       setup_work_tree();
+                       setup_work_tree(the_repository);
                        p = prefix_path(the_repository, prefix, prefix_length, path);
                        update_one(p);
                        if (set_executable_bit)
@@ -1199,7 +1199,7 @@ int cmd_update_index(int argc,
                struct strbuf buf = STRBUF_INIT;
                struct strbuf unquoted = STRBUF_INIT;
 
-               setup_work_tree();
+               setup_work_tree(the_repository);
                while (getline_fn(&buf, stdin) != EOF) {
                        char *p;
                        if (!nul_term_line && buf.buf[0] == '"') {
@@ -1253,7 +1253,7 @@ int cmd_update_index(int argc,
                report(_("Untracked cache disabled"));
                break;
        case UC_TEST:
-               setup_work_tree();
+               setup_work_tree(the_repository);
                return !test_if_untracked_cache_is_supported();
        case UC_ENABLE:
        case UC_FORCE:
diff --git a/git.c b/git.c
index 5a40eab8a26a66276444586b5898409f718515b3..eaede42c4e864491cf4ad393e240e0296c2f7c85 100644 (file)
--- a/git.c
+++ b/git.c
@@ -497,7 +497,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv, struct
        commit_pager_choice();
 
        if (!help && p->option & NEED_WORK_TREE)
-               setup_work_tree();
+               setup_work_tree(the_repository);
 
        trace_argv_printf(argv, "trace: built-in: git");
        trace2_cmd_name(p->cmd);
index 4969d8b8ebed607207940e36a7b53e2fef63f2dc..832451fc6165938310d0c8311aef98046006ba73 100644 (file)
@@ -114,6 +114,7 @@ struct repository {
         * A NULL value indicates that there is no working directory.
         */
        char *worktree;
+       bool worktree_config_is_bogus;
 
        /*
         * Path from the root of the top-level superproject down to this
diff --git a/setup.c b/setup.c
index cb479cd91a871bb8f164bb46b1ca21aa2858a2fa..50324f8f37081aec71ef0b625a17a34d501f7428 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -26,7 +26,6 @@
 #include "trace2.h"
 #include "worktree.h"
 
-static int work_tree_config_is_bogus;
 enum allowed_bare_repo {
        ALLOWED_BARE_REPO_EXPLICIT = 0,
        ALLOWED_BARE_REPO_ALL,
@@ -494,18 +493,14 @@ int is_inside_work_tree(struct repository *repo)
        return ret;
 }
 
-void setup_work_tree(void)
+void setup_work_tree(struct repository *repo)
 {
        const char *work_tree;
-       static int initialized = 0;
 
-       if (initialized)
-               return;
-
-       if (work_tree_config_is_bogus)
+       if (repo->worktree_config_is_bogus)
                die(_("unable to set up work tree using invalid config"));
 
-       work_tree = repo_get_work_tree(the_repository);
+       work_tree = repo_get_work_tree(repo);
        if (!work_tree || chdir_notify(work_tree))
                die(_("this operation must be run in a work tree"));
 
@@ -515,8 +510,6 @@ void setup_work_tree(void)
         */
        if (getenv(GIT_WORK_TREE_ENVIRONMENT))
                setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
-
-       initialized = 1;
 }
 
 static void setup_original_cwd(struct repository *repo)
@@ -1164,7 +1157,7 @@ static const char *setup_explicit_git_dir(struct repository *repo,
                if (git_work_tree_cfg) {
                        /* #22.2, #30 */
                        warning("core.bare and core.worktree do not make sense");
-                       work_tree_config_is_bogus = 1;
+                       repo->worktree_config_is_bogus = true;
                }
 
                /* #18, #26 */
diff --git a/setup.h b/setup.h
index d0cfdfd44a67a84f52679a8044b9fcb74a400e48..8fed365637ec2bf32a6ee75818ec31f0288a3421 100644 (file)
--- a/setup.h
+++ b/setup.h
@@ -56,7 +56,7 @@ const char *resolve_gitdir_gently(const char *suspect, int *return_error_code);
 void die_upon_dubious_ownership(const char *gitfile, const char *worktree,
                                const char *gitdir);
 
-void setup_work_tree(void);
+void setup_work_tree(struct repository *repo);
 
 /*
  * discover_git_directory_reason() is similar to discover_git_directory(),
index c344f1694df28da085340b5f556ecae9bfcbb56f..8a070e47cddb519b2f07f8e7743de55bdf3f514b 100644 (file)
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
 #include "test-tool.h"
 #include "run-command.h"
 #include "setup.h"
@@ -11,7 +13,7 @@ int cmd__subprocess(int argc, const char **argv)
        if (nogit)
                die("No git repo found");
        if (argc > 1 && !strcmp(argv[1], "--setup-work-tree")) {
-               setup_work_tree();
+               setup_work_tree(the_repository);
                argv++;
        }
        cp.git_cmd = 1;
index c12fca707812990153da6e393f5a8cc111944ec8..b17372390cf96cff01819f923ddabad141484851 100644 (file)
@@ -1206,7 +1206,7 @@ static void wt_longstatus_print_verbose(struct wt_status *s)
                status_printf_ln(s, c,
                        "--------------------------------------------------");
                status_printf_ln(s, c, _("Changes not staged for commit:"));
-               setup_work_tree();
+               setup_work_tree(the_repository);
                rev.diffopt.a_prefix = "i/";
                rev.diffopt.b_prefix = "w/";
                run_diff_files(&rev, 0);