{"thread":{"id":"62019","subject":"[PATCH 00/21] environment: guard reliance on `the_repository`","startedAt":"2024-08-29T09:38:23Z","lastAt":"2024-09-12T20:40:50Z","messageCount":92,"participants":["Patrick Steinhardt","Junio C Hamano","Justin Tobler","James Liu","karthik nayak"],"isPatch":true,"patchVersion":1,"patchTotal":21},"messages":[{"id":"501807","messageId":"cover.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":null,"subject":"[PATCH 00/21] environment: guard reliance on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:19Z","receivedAt":"2024-08-29T09:38:23Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis patch series is the next part in the epic to get rid of\n`the_repository`. This time around I focussed on the environment\nsubsystem, which relies on `the_repository` both implicitly and\nexplicitly.\n\nThe series is structured as follows:\n\n  - Patches 1 to 6 moves functions that belong to the repository\n    subsystem.\n\n  - Patches 7 and 8 adapt the config subsystem to stop depending on the\n    `the_repository` again, which had to be added by the preceding\n    patches.\n\n  - Patches 9 to 11 move various functionality that is misplaced and\n    that depends on `the_repository`.\n\n  - Patches 12 and 13 guard functionality that relies on global state\n    in the environment subsystem via `USE_THE_REPOSITORY_VARIBABLE`.\n\n  - Patches 14 to 21 demonstrate how to get rid of global config\n    variables part of the environment subsystem for a subset of them.\n    Overall, I think that our reliance on global variables is broken\n    because those variables may or may not point to the actual config of\n    a specific repository we currently hold. They may not even hold\n    state of `the_repository`, but might've been changed by subsequent\n    logic where we parse another repository's config.\n\nI'm a bit unhappy that I wasn't able to adapt `is_bare_repository()` to\ntake a `struct repository` yet, and as a consequence a bunch of code\nneeds to declare `USE_THE_REPOSITORY_VARIBABLE` again. But it depends on\nanother global variable `is_bare_repository_cfg` which is being modified\nquite heavily in multiple subsystems, and the resulting semantics are...\nconfusing. I guess we'll need another biggish patch series to clean up\nthis mess by making the setup subsystem not rely on such global state\nanymore.\n\nThe series is built on top of 17d4b10aea (The tenth batch, 2024-08-28).\nIt merges with `next` rather cleanish, except for a single merge\nconflict with headers.\n\nThanks!\n\nPatrick\n\nPatrick Steinhardt (21):\n  environment: make `get_git_dir()` accept a repository\n  environment: make `get_git_common_dir()` accept a repository\n  environment: make `get_object_directory()` accept a repository\n  environment: make `get_index_file()` accept a repository\n  environment: make `get_graft_file()` accept a repository\n  environment: make `get_git_work_tree()` accept a repository\n  config: document `read_early_config()` and `read_very_early_config()`\n  config: make dependency on repo in `read_early_config()` explicit\n  environment: move `odb_mkstemp()` into object layer\n  environment: make `get_git_namespace()` self-contained\n  environment: move `set_git_dir()` and related into setup layer\n  environment: reorder header to split out `the_repository`-free section\n  environment: guard state depending on a repository\n  repo-settings: split out declarations into a standalone header\n  branch: stop modifying `log_all_ref_updates` variable\n  refs: stop modifying global `log_all_ref_updates` variable\n  repo-settings: track defaults close to `struct repo_settings`\n  environment: stop storing \"core.logAllRefUpdates\" globally\n  environment: stop storing \"core.preferSymlinkRefs\" globally\n  environment: stop storing \"core.warnAmbiguousRefs\" globally\n  environment: stop storing \"core.notesRef\" globally\n\n alias.c                     |   6 +-\n apply.c                     |   2 +-\n branch.c                    |   5 +-\n builtin/am.c                |  13 +-\n builtin/blame.c             |   2 +-\n builtin/checkout.c          |   4 +-\n builtin/commit-graph.c      |   4 +-\n builtin/commit.c            |  12 +-\n builtin/config.c            |   4 +-\n builtin/count-objects.c     |   2 +-\n builtin/difftool.c          |   8 +-\n builtin/fsmonitor--daemon.c |   6 +-\n builtin/gc.c                |   2 +-\n builtin/init-db.c           |   4 +-\n builtin/merge.c             |  17 +--\n builtin/multi-pack-index.c  |   2 +-\n builtin/notes.c             |  22 ++--\n builtin/pack-objects.c      |   2 +-\n builtin/prune.c             |   8 +-\n builtin/repack.c            |   7 +-\n builtin/replace.c           |   2 +-\n builtin/reset.c             |   4 +-\n builtin/rev-parse.c         |   9 +-\n builtin/stash.c             |  16 +--\n builtin/submodule--helper.c |   2 +-\n builtin/update-index.c      |   4 +-\n builtin/worktree.c          |   4 +-\n builtin/write-tree.c        |   3 +-\n bulk-checkin.c              |   4 +-\n bundle-uri.c                |   1 +\n cache-tree.c                |   3 +-\n commit.c                    |   4 +-\n config.c                    |  42 +------\n config.h                    |  13 +-\n dir.c                       |   2 +-\n environment.c               | 237 +++++-------------------------------\n environment.h               | 142 ++++++++++-----------\n fetch-pack.c                |   2 +-\n fsmonitor.c                 |   2 +-\n help.c                      |   2 +-\n http-backend.c              |   2 +-\n name-hash.c                 |   3 +\n notes.c                     |  21 ++--\n notes.h                     |   3 +-\n object-file.c               |  37 +++++-\n object-name.c               |   4 +-\n object-store-ll.h           |  15 +++\n pack-write.c                |   2 +-\n packfile.c                  |   2 +-\n pager.c                     |   7 +-\n path.c                      |   2 +\n pathspec.c                  |   4 +-\n preload-index.c             |   3 +\n prompt.c                    |   2 +\n prune-packed.c              |   4 +-\n read-cache.c                |   5 +-\n ref-filter.c                |   2 +-\n refs.c                      |   7 +-\n refs.h                      |   4 +-\n refs/files-backend.c        |  31 +++--\n refs/reftable-backend.c     |  22 ++--\n repo-settings.c             |  35 +++++-\n repo-settings.h             |  75 ++++++++++++\n repository.c                |  40 ++++++\n repository.h                |  58 ++-------\n server-info.c               |   3 +-\n setup.c                     | 152 +++++++++++++++++++----\n setup.h                     |   5 +-\n sparse-index.c              |   2 +\n statinfo.c                  |   2 +\n submodule.c                 |   2 +-\n t/helper/test-config.c      |   3 +-\n t/helper/test-path-utils.c  |   2 +\n tmp-objdir.c                |   7 +-\n trace.c                     |   8 +-\n trace2/tr2_cfg.c            |   4 +-\n transport-helper.c          |   2 +-\n tree-diff.c                 |   3 +\n userdiff.c                  |   2 +\n worktree.c                  |  12 +-\n wt-status.c                 |   2 +-\n 81 files changed, 677 insertions(+), 554 deletions(-)\n create mode 100644 repo-settings.h\n\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501808","messageId":"0fe3e3e1cccf2eae7d81ccecf431da623b39fa79.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 01/21] environment: make `get_git_dir()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:22Z","receivedAt":"2024-08-29T09:38:25Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_git_dir()` function retrieves the path to the Git directory for\n`the_repository`. Make it accept a `struct repository` such that it can\nwork on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n apply.c                     |  2 +-\n builtin/am.c                |  5 +++--\n builtin/commit.c            |  6 +++---\n builtin/config.c            |  2 +-\n builtin/difftool.c          |  4 ++--\n builtin/fsmonitor--daemon.c |  3 ++-\n builtin/merge.c             |  3 ++-\n builtin/stash.c             |  2 +-\n cache-tree.c                |  3 ++-\n config.c                    |  4 +++-\n environment.c               | 10 ++--------\n environment.h               |  1 -\n pathspec.c                  |  2 +-\n read-cache.c                |  5 +++--\n repository.c                |  7 +++++++\n repository.h                |  2 ++\n setup.c                     | 12 ++++++------\n setup.h                     |  2 +-\n trace.c                     |  4 +++-\n transport-helper.c          |  2 +-\n worktree.c                  |  4 ++--\n 21 files changed, 48 insertions(+), 37 deletions(-)\n\ndiff --git a/apply.c b/apply.c\nindex 6e1060a952c..19fbb8fb93f 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -4111,7 +4111,7 @@ static int read_apply_cache(struct apply_state *state)\n {\n \tif (state->index_file)\n \t\treturn read_index_from(state->repo->index, state->index_file,\n-\t\t\t\t       get_git_dir());\n+\t\t\t\t       repo_get_git_dir(the_repository));\n \telse\n \t\treturn repo_read_index(state->repo);\n }\ndiff --git a/builtin/am.c b/builtin/am.c\nindex d8875ad4022..405214e242a 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1544,7 +1544,8 @@ static int run_apply(const struct am_state *state, const char *index_file)\n \tif (index_file) {\n \t\t/* Reload index as apply_all_patches() will have modified it. */\n \t\tdiscard_index(the_repository->index);\n-\t\tread_index_from(the_repository->index, index_file, get_git_dir());\n+\t\tread_index_from(the_repository->index, index_file,\n+\t\t\t\trepo_get_git_dir(the_repository));\n \t}\n \n \treturn 0;\n@@ -1587,7 +1588,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa\n \t\treturn error(\"could not build fake ancestor\");\n \n \tdiscard_index(the_repository->index);\n-\tread_index_from(the_repository->index, index_path, get_git_dir());\n+\tread_index_from(the_repository->index, index_path, repo_get_git_dir(the_repository));\n \n \tif (write_index_as_tree(&bases[0], the_repository->index, index_path, 0, NULL))\n \t\treturn error(_(\"Repository lacks necessary blobs to fall back on 3-way merge.\"));\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex b2033c48877..55124ee28f0 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -407,7 +407,7 @@ static const char *prepare_index(const char **argv, const char *prefix,\n \n \t\tdiscard_index(the_repository->index);\n \t\tread_index_from(the_repository->index, get_lock_file_path(&index_lock),\n-\t\t\t\tget_git_dir());\n+\t\t\t\trepo_get_git_dir(the_repository));\n \t\tif (cache_tree_update(the_repository->index, WRITE_TREE_SILENT) == 0) {\n \t\t\tif (reopen_lock_file(&index_lock) < 0)\n \t\t\t\tdie(_(\"unable to write index file\"));\n@@ -534,7 +534,7 @@ static const char *prepare_index(const char **argv, const char *prefix,\n \n \tdiscard_index(the_repository->index);\n \tret = get_lock_file_path(&false_lock);\n-\tread_index_from(the_repository->index, ret, get_git_dir());\n+\tread_index_from(the_repository->index, ret, repo_get_git_dir(the_repository));\n out:\n \tstring_list_clear(&partial, 0);\n \tclear_pathspec(&pathspec);\n@@ -1072,7 +1072,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\t */\n \t\tdiscard_index(the_repository->index);\n \t}\n-\tread_index_from(the_repository->index, index_file, get_git_dir());\n+\tread_index_from(the_repository->index, index_file, repo_get_git_dir(the_repository));\n \n \tif (cache_tree_update(the_repository->index, 0)) {\n \t\terror(_(\"Error building trees\"));\ndiff --git a/builtin/config.c b/builtin/config.c\nindex e00d983596b..c10697a2efb 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -808,7 +808,7 @@ static void location_options_init(struct config_location_options *opts,\n \t\topts->options.respect_includes = opts->respect_includes_opt;\n \tif (startup_info->have_repository) {\n \t\topts->options.commondir = get_git_common_dir();\n-\t\topts->options.git_dir = get_git_dir();\n+\t\topts->options.git_dir = repo_get_git_dir(the_repository);\n \t}\n }\n \ndiff --git a/builtin/difftool.c b/builtin/difftool.c\nindex dcc68e190c2..da9315e84d4 100644\n--- a/builtin/difftool.c\n+++ b/builtin/difftool.c\n@@ -214,7 +214,7 @@ static void changed_files(struct hashmap *result, const char *index_path,\n \tstruct child_process update_index = CHILD_PROCESS_INIT;\n \tstruct child_process diff_files = CHILD_PROCESS_INIT;\n \tstruct strbuf buf = STRBUF_INIT;\n-\tconst char *git_dir = absolute_path(get_git_dir());\n+\tconst char *git_dir = absolute_path(repo_get_git_dir(the_repository));\n \tFILE *fp;\n \n \tstrvec_pushl(&update_index.args,\n@@ -737,7 +737,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)\n \n \tif (!no_index){\n \t\tsetup_work_tree();\n-\t\tsetenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);\n+\t\tsetenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1);\n \t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);\n \t} else if (dir_diff)\n \t\tdie(_(\"options '%s' and '%s' cannot be used together\"), \"--dir-diff\", \"--no-index\");\ndiff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c\nindex 1593713f4cb..c54e736716a 100644\n--- a/builtin/fsmonitor--daemon.c\n+++ b/builtin/fsmonitor--daemon.c\n@@ -1311,7 +1311,8 @@ static int fsmonitor_run_daemon(void)\n \tstrbuf_addstr(&state.path_gitdir_watch, \"/.git\");\n \tif (!is_directory(state.path_gitdir_watch.buf)) {\n \t\tstrbuf_reset(&state.path_gitdir_watch);\n-\t\tstrbuf_addstr(&state.path_gitdir_watch, absolute_path(get_git_dir()));\n+\t\tstrbuf_addstr(&state.path_gitdir_watch,\n+\t\t\t      absolute_path(repo_get_git_dir(the_repository)));\n \t\tstate.nr_paths_watching = 2;\n \t}\n \ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 662a49a0e8c..6c22912b63c 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -855,7 +855,8 @@ static void prepare_to_commit(struct commit_list *remoteheads)\n \t\tif (invoked_hook)\n \t\t\tdiscard_index(the_repository->index);\n \t}\n-\tread_index_from(the_repository->index, index_file, get_git_dir());\n+\tread_index_from(the_repository->index, index_file,\n+\t\t\trepo_get_git_dir(the_repository));\n \tstrbuf_addbuf(&msg, &merge_msg);\n \tif (squash)\n \t\tBUG(\"the control must not reach here under --squash\");\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex fcfd97972a4..ed56299098e 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -642,7 +642,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\tstrvec_pushf(&cp.env, GIT_WORK_TREE_ENVIRONMENT\"=%s\",\n \t\t\t     absolute_path(get_git_work_tree()));\n \t\tstrvec_pushf(&cp.env, GIT_DIR_ENVIRONMENT\"=%s\",\n-\t\t\t     absolute_path(get_git_dir()));\n+\t\t\t     absolute_path(repo_get_git_dir(the_repository)));\n \t\tstrvec_push(&cp.args, \"status\");\n \t\trun_command(&cp);\n \t}\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 50610c3f3cb..4e7ef7a7656 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -725,7 +725,8 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,\n \n \thold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);\n \n-\tentries = read_index_from(index_state, index_path, get_git_dir());\n+\tentries = read_index_from(index_state, index_path,\n+\t\t\t\t  repo_get_git_dir(the_repository));\n \tif (entries < 0) {\n \t\tret = WRITE_TREE_UNREADABLE_INDEX;\n \t\tgoto out;\ndiff --git a/config.c b/config.c\nindex 56b5862e59d..1733ba85dcd 100644\n--- a/config.c\n+++ b/config.c\n@@ -6,6 +6,8 @@\n  *\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"advice.h\"\n@@ -2212,7 +2214,7 @@ void read_early_config(config_fn_t cb, void *data)\n \n \tif (have_git_dir()) {\n \t\topts.commondir = get_git_common_dir();\n-\t\topts.git_dir = get_git_dir();\n+\t\topts.git_dir = repo_get_git_dir(the_repository);\n \t/*\n \t * When setup_git_directory() was not yet asked to discover the\n \t * GIT_DIR, we ask discover_git_directory() to figure out whether there\ndiff --git a/environment.c b/environment.c\nindex 1d6c48b52df..040b1ff1ba8 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -228,13 +228,6 @@ int have_git_dir(void)\n \t\t|| the_repository->gitdir;\n }\n \n-const char *get_git_dir(void)\n-{\n-\tif (!the_repository->gitdir)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->gitdir;\n-}\n-\n const char *get_git_common_dir(void)\n {\n \tif (!the_repository->commondir)\n@@ -352,7 +345,8 @@ static void update_relative_gitdir(const char *name UNUSED,\n \t\t\t\t   const char *new_cwd,\n \t\t\t\t   void *data UNUSED)\n {\n-\tchar *path = reparent_relative_path(old_cwd, new_cwd, get_git_dir());\n+\tchar *path = reparent_relative_path(old_cwd, new_cwd,\n+\t\t\t\t\t    repo_get_git_dir(the_repository));\n \tstruct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();\n \n \ttrace_printf_key(&trace_setup_key,\ndiff --git a/environment.h b/environment.h\nindex 0148738ed63..06d37d5c82b 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_git_dir(void);\n const char *get_git_common_dir(void);\n const char *get_object_directory(void);\n char *get_index_file(void);\ndiff --git a/pathspec.c b/pathspec.c\nindex fe1f0f41af0..416fe1e3dcc 100644\n--- a/pathspec.c\n+++ b/pathspec.c\n@@ -497,7 +497,7 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,\n \t\t\t\t    copyfrom);\n \t\t\thint_path = get_git_work_tree();\n \t\t\tif (!hint_path)\n-\t\t\t\thint_path = get_git_dir();\n+\t\t\t\thint_path = repo_get_git_dir(the_repository);\n \t\t\tdie(_(\"%s: '%s' is outside repository at '%s'\"), elt,\n \t\t\t    copyfrom, absolute_path(hint_path));\n \t\t}\ndiff --git a/read-cache.c b/read-cache.c\nindex 4e67dc182e7..c5794fbf2c9 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -3238,10 +3238,11 @@ static int should_delete_shared_index(const char *shared_index_path)\n static int clean_shared_index_files(const char *current_hex)\n {\n \tstruct dirent *de;\n-\tDIR *dir = opendir(get_git_dir());\n+\tDIR *dir = opendir(repo_get_git_dir(the_repository));\n \n \tif (!dir)\n-\t\treturn error_errno(_(\"unable to open git dir: %s\"), get_git_dir());\n+\t\treturn error_errno(_(\"unable to open git dir: %s\"),\n+\t\t\t\t   repo_get_git_dir(the_repository));\n \n \twhile ((de = readdir(dir)) != NULL) {\n \t\tconst char *sha1_hex;\ndiff --git a/repository.c b/repository.c\nindex 9825a308993..6f43f2e8344 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -91,6 +91,13 @@ static void expand_base_dir(char **out, const char *in,\n \t\t*out = xstrfmt(\"%s/%s\", base_dir, def_in);\n }\n \n+const char *repo_get_git_dir(struct repository *repo)\n+{\n+\tif (!repo->gitdir)\n+\t\tBUG(\"git environment hasn't been setup\");\n+\treturn repo->gitdir;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex af6ea0a62cd..cf2172c0aa5 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -206,6 +206,8 @@ struct repository {\n extern struct repository *the_repository;\n #endif\n \n+const char *repo_get_git_dir(struct repository *repo);\n+\n /*\n  * Define a custom repository layout. Any field can be NULL, which\n  * will default back to the path according to the default layout.\ndiff --git a/setup.c b/setup.c\nindex 29f86739212..4a9c60922e7 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -149,7 +149,7 @@ char *prefix_path(const char *prefix, int len, const char *path)\n \tif (!r) {\n \t\tconst char *hint_path = get_git_work_tree();\n \t\tif (!hint_path)\n-\t\t\thint_path = get_git_dir();\n+\t\t\thint_path = repo_get_git_dir(the_repository);\n \t\tdie(_(\"'%s' is outside repository at '%s'\"), path,\n \t\t    absolute_path(hint_path));\n \t}\n@@ -468,7 +468,7 @@ int is_nonbare_repository_dir(struct strbuf *path)\n int is_inside_git_dir(void)\n {\n \tif (inside_git_dir < 0)\n-\t\tinside_git_dir = is_inside_dir(get_git_dir());\n+\t\tinside_git_dir = is_inside_dir(repo_get_git_dir(the_repository));\n \treturn inside_git_dir;\n }\n \n@@ -1836,7 +1836,7 @@ void check_repository_format(struct repository_format *fmt)\n \tstruct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;\n \tif (!fmt)\n \t\tfmt = &repo_fmt;\n-\tcheck_repository_format_gently(get_git_dir(), fmt, NULL);\n+\tcheck_repository_format_gently(repo_get_git_dir(the_repository), fmt, NULL);\n \tstartup_info->have_repository = 1;\n \trepo_set_hash_algo(the_repository, fmt->hash_algo);\n \trepo_set_compat_hash_algo(the_repository, fmt->compat_hash_algo);\n@@ -2224,7 +2224,7 @@ static int create_default_files(const char *template_path,\n \t * shared-repository settings, we would need to fix them up.\n \t */\n \tif (get_shared_repository()) {\n-\t\tadjust_shared_perm(get_git_dir());\n+\t\tadjust_shared_perm(repo_get_git_dir(the_repository));\n \t}\n \n \tinitialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, 0);\n@@ -2434,12 +2434,12 @@ int init_db(const char *git_dir, const char *real_git_dir,\n \t\t\tdie(_(\"%s already exists\"), real_git_dir);\n \n \t\tset_git_dir(real_git_dir, 1);\n-\t\tgit_dir = get_git_dir();\n+\t\tgit_dir = repo_get_git_dir(the_repository);\n \t\tseparate_git_dir(git_dir, original_git_dir);\n \t}\n \telse {\n \t\tset_git_dir(git_dir, 1);\n-\t\tgit_dir = get_git_dir();\n+\t\tgit_dir = repo_get_git_dir(the_repository);\n \t}\n \tstartup_info->have_repository = 1;\n \ndiff --git a/setup.h b/setup.h\nindex cd8dbc24976..fd2df7cd525 100644\n--- a/setup.h\n+++ b/setup.h\n@@ -176,7 +176,7 @@ int verify_repository_format(const struct repository_format *format,\n \t\t\t     struct strbuf *err);\n \n /*\n- * Check the repository format version in the path found in get_git_dir(),\n+ * Check the repository format version in the path found in repo_get_git_dir(the_repository),\n  * and die if it is a version we don't understand. Generally one would\n  * set_git_dir() before calling this, and use it only for \"are we in a valid\n  * repo?\".\ndiff --git a/trace.c b/trace.c\nindex 8669ddfca25..988b494a954 100644\n--- a/trace.c\n+++ b/trace.c\n@@ -21,6 +21,8 @@\n  *  along with this program; if not, see <https://www.gnu.org/licenses/>.\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"environment.h\"\n@@ -311,7 +313,7 @@ void trace_repo_setup(void)\n \tif (!startup_info->prefix)\n \t\tprefix = \"(null)\";\n \n-\ttrace_printf_key(&trace_setup_key, \"setup: git_dir: %s\\n\", quote_crnl(get_git_dir()));\n+\ttrace_printf_key(&trace_setup_key, \"setup: git_dir: %s\\n\", quote_crnl(repo_get_git_dir(the_repository)));\n \ttrace_printf_key(&trace_setup_key, \"setup: git_common_dir: %s\\n\", quote_crnl(get_git_common_dir()));\n \ttrace_printf_key(&trace_setup_key, \"setup: worktree: %s\\n\", quote_crnl(git_work_tree));\n \ttrace_printf_key(&trace_setup_key, \"setup: cwd: %s\\n\", quote_crnl(cwd));\ndiff --git a/transport-helper.c b/transport-helper.c\nindex 09b3560ffdc..abe16eea651 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -143,7 +143,7 @@ static struct child_process *get_helper(struct transport *transport)\n \n \tif (have_git_dir())\n \t\tstrvec_pushf(&helper->env, \"%s=%s\",\n-\t\t\t     GIT_DIR_ENVIRONMENT, get_git_dir());\n+\t\t\t     GIT_DIR_ENVIRONMENT, repo_get_git_dir(the_repository));\n \n \thelper->trace2_child_class = helper->args.v[0]; /* \"remote-<name>\" */\n \ndiff --git a/worktree.c b/worktree.c\nindex 30a947426ee..11335c5d9a3 100644\n--- a/worktree.c\n+++ b/worktree.c\n@@ -57,7 +57,7 @@ static void add_head_info(struct worktree *wt)\n \n static int is_current_worktree(struct worktree *wt)\n {\n-\tchar *git_dir = absolute_pathdup(get_git_dir());\n+\tchar *git_dir = absolute_pathdup(repo_get_git_dir(the_repository));\n \tconst char *wt_git_dir = get_worktree_git_dir(wt);\n \tint is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir));\n \tfree(git_dir);\n@@ -171,7 +171,7 @@ struct worktree **get_worktrees(void)\n const char *get_worktree_git_dir(const struct worktree *wt)\n {\n \tif (!wt)\n-\t\treturn get_git_dir();\n+\t\treturn repo_get_git_dir(the_repository);\n \telse if (!wt->id)\n \t\treturn get_git_common_dir();\n \telse\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501809","messageId":"cdd6dd308c3e1dc0e53fe2d66f8dd0a2b4a9fb22.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 02/21] environment: make `get_git_common_dir()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:26Z","receivedAt":"2024-08-29T09:38:33Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_git_common_dir()` function retrieves the path to the common\ndirectory for `the_repository`. Make it accept a `struct repository`\nsuch that it can work on arbitrary repositories and make it part of the\nrepository subsystem. This reduces our reliance on `the_repository` and\nclarifies scope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/config.c    | 2 +-\n builtin/gc.c        | 2 +-\n builtin/rev-parse.c | 2 +-\n builtin/worktree.c  | 4 ++--\n config.c            | 2 +-\n environment.c       | 7 -------\n environment.h       | 1 -\n repository.c        | 7 +++++++\n repository.h        | 1 +\n setup.c             | 2 +-\n submodule.c         | 2 +-\n trace.c             | 2 +-\n worktree.c          | 8 ++++----\n 13 files changed, 21 insertions(+), 21 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex c10697a2efb..34a371414e8 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -807,7 +807,7 @@ static void location_options_init(struct config_location_options *opts,\n \telse\n \t\topts->options.respect_includes = opts->respect_includes_opt;\n \tif (startup_info->have_repository) {\n-\t\topts->options.commondir = get_git_common_dir();\n+\t\topts->options.commondir = repo_get_common_dir(the_repository);\n \t\topts->options.git_dir = repo_get_git_dir(the_repository);\n \t}\n }\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex 427faf1cfe1..0f3d74f8bd0 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -2132,7 +2132,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority\n \tget_schedule_cmd(&cmd, NULL);\n \n \tstrbuf_addf(&tfilename, \"%s/schedule_%s_XXXXXX\",\n-\t\t    get_git_common_dir(), frequency);\n+\t\t    repo_get_common_dir(the_repository), frequency);\n \ttfile = xmks_tempfile(tfilename.buf);\n \tstrbuf_release(&tfilename);\n \ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex 4285dc34a7b..4308a2a8549 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -1042,7 +1042,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--git-common-dir\")) {\n-\t\t\t\tprint_path(get_git_common_dir(), prefix, format, DEFAULT_RELATIVE_IF_SHARED);\n+\t\t\t\tprint_path(repo_get_common_dir(the_repository), prefix, format, DEFAULT_RELATIVE_IF_SHARED);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--is-inside-git-dir\")) {\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 41e7f6a3271..645b548bf3b 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -219,7 +219,7 @@ static void prune_worktrees(void)\n \t}\n \tclosedir(dir);\n \n-\tstrbuf_add_absolute_path(&main_path, get_git_common_dir());\n+\tstrbuf_add_absolute_path(&main_path, repo_get_common_dir(the_repository));\n \t/* massage main worktree absolute path to match 'gitdir' content */\n \tstrbuf_strip_suffix(&main_path, \"/.\");\n \tstring_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));\n@@ -492,7 +492,7 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/gitdir\", sb_repo.buf);\n \tstrbuf_realpath(&realpath, sb_git.buf, 1);\n \twrite_file(sb.buf, \"%s\", realpath.buf);\n-\tstrbuf_realpath(&realpath, get_git_common_dir(), 1);\n+\tstrbuf_realpath(&realpath, repo_get_common_dir(the_repository), 1);\n \twrite_file(sb_git.buf, \"gitdir: %s/worktrees/%s\",\n \t\t   realpath.buf, name);\n \tstrbuf_reset(&sb);\ndiff --git a/config.c b/config.c\nindex 1733ba85dcd..0b87f0f9050 100644\n--- a/config.c\n+++ b/config.c\n@@ -2213,7 +2213,7 @@ void read_early_config(config_fn_t cb, void *data)\n \topts.respect_includes = 1;\n \n \tif (have_git_dir()) {\n-\t\topts.commondir = get_git_common_dir();\n+\t\topts.commondir = repo_get_common_dir(the_repository);\n \t\topts.git_dir = repo_get_git_dir(the_repository);\n \t/*\n \t * When setup_git_directory() was not yet asked to discover the\ndiff --git a/environment.c b/environment.c\nindex 040b1ff1ba8..7c4a142ca25 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -228,13 +228,6 @@ int have_git_dir(void)\n \t\t|| the_repository->gitdir;\n }\n \n-const char *get_git_common_dir(void)\n-{\n-\tif (!the_repository->commondir)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->commondir;\n-}\n-\n const char *get_git_namespace(void)\n {\n \tif (!git_namespace)\ndiff --git a/environment.h b/environment.h\nindex 06d37d5c82b..d778614158f 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_git_common_dir(void);\n const char *get_object_directory(void);\n char *get_index_file(void);\n char *get_graft_file(struct repository *r);\ndiff --git a/repository.c b/repository.c\nindex 6f43f2e8344..acf654d7ab6 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -98,6 +98,13 @@ const char *repo_get_git_dir(struct repository *repo)\n \treturn repo->gitdir;\n }\n \n+const char *repo_get_common_dir(struct repository *repo)\n+{\n+\tif (!repo->commondir)\n+\t\tBUG(\"git environment hasn't been setup\");\n+\treturn repo->commondir;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex cf2172c0aa5..404435ad029 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -207,6 +207,7 @@ extern struct repository *the_repository;\n #endif\n \n const char *repo_get_git_dir(struct repository *repo);\n+const char *repo_get_common_dir(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/setup.c b/setup.c\nindex 4a9c60922e7..fe4a5dfc43b 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2068,7 +2068,7 @@ static void copy_templates(const char *option_template)\n \t\tgoto close_free_return;\n \t}\n \n-\tstrbuf_addstr(&path, get_git_common_dir());\n+\tstrbuf_addstr(&path, repo_get_common_dir(the_repository));\n \tstrbuf_complete(&path, '/');\n \tcopy_templates_1(&path, &template_path, dir);\n close_free_return:\ndiff --git a/submodule.c b/submodule.c\nindex 97516b0fec1..c7d164a31ab 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -2462,7 +2462,7 @@ void absorb_git_dir_into_superproject(const char *path,\n \t} else {\n \t\t/* Is it already absorbed into the superprojects git dir? */\n \t\tchar *real_sub_git_dir = real_pathdup(sub_git_dir, 1);\n-\t\tchar *real_common_git_dir = real_pathdup(get_git_common_dir(), 1);\n+\t\tchar *real_common_git_dir = real_pathdup(repo_get_common_dir(the_repository), 1);\n \n \t\tif (!starts_with(real_sub_git_dir, real_common_git_dir))\n \t\t\trelocate_single_git_dir_into_superproject(path, super_prefix);\ndiff --git a/trace.c b/trace.c\nindex 988b494a954..2d9ae1c1525 100644\n--- a/trace.c\n+++ b/trace.c\n@@ -314,7 +314,7 @@ void trace_repo_setup(void)\n \t\tprefix = \"(null)\";\n \n \ttrace_printf_key(&trace_setup_key, \"setup: git_dir: %s\\n\", quote_crnl(repo_get_git_dir(the_repository)));\n-\ttrace_printf_key(&trace_setup_key, \"setup: git_common_dir: %s\\n\", quote_crnl(get_git_common_dir()));\n+\ttrace_printf_key(&trace_setup_key, \"setup: git_common_dir: %s\\n\", quote_crnl(repo_get_common_dir(the_repository)));\n \ttrace_printf_key(&trace_setup_key, \"setup: worktree: %s\\n\", quote_crnl(git_work_tree));\n \ttrace_printf_key(&trace_setup_key, \"setup: cwd: %s\\n\", quote_crnl(cwd));\n \ttrace_printf_key(&trace_setup_key, \"setup: prefix: %s\\n\", quote_crnl(prefix));\ndiff --git a/worktree.c b/worktree.c\nindex 11335c5d9a3..0f032ccedff 100644\n--- a/worktree.c\n+++ b/worktree.c\n@@ -72,7 +72,7 @@ static struct worktree *get_main_worktree(int skip_reading_head)\n \tstruct worktree *worktree = NULL;\n \tstruct strbuf worktree_path = STRBUF_INIT;\n \n-\tstrbuf_add_real_path(&worktree_path, get_git_common_dir());\n+\tstrbuf_add_real_path(&worktree_path, repo_get_common_dir(the_repository));\n \tstrbuf_strip_suffix(&worktree_path, \"/.git\");\n \n \tCALLOC_ARRAY(worktree, 1);\n@@ -143,7 +143,7 @@ static struct worktree **get_worktrees_internal(int skip_reading_head)\n \n \tlist[counter++] = get_main_worktree(skip_reading_head);\n \n-\tstrbuf_addf(&path, \"%s/worktrees\", get_git_common_dir());\n+\tstrbuf_addf(&path, \"%s/worktrees\", repo_get_common_dir(the_repository));\n \tdir = opendir(path.buf);\n \tstrbuf_release(&path);\n \tif (dir) {\n@@ -173,7 +173,7 @@ const char *get_worktree_git_dir(const struct worktree *wt)\n \tif (!wt)\n \t\treturn repo_get_git_dir(the_repository);\n \telse if (!wt->id)\n-\t\treturn get_git_common_dir();\n+\t\treturn repo_get_common_dir(the_repository);\n \telse\n \t\treturn git_common_path(\"worktrees/%s\", wt->id);\n }\n@@ -626,7 +626,7 @@ static int is_main_worktree_path(const char *path)\n \n \tstrbuf_add_real_path(&target, path);\n \tstrbuf_strip_suffix(&target, \"/.git\");\n-\tstrbuf_add_real_path(&maindir, get_git_common_dir());\n+\tstrbuf_add_real_path(&maindir, repo_get_common_dir(the_repository));\n \tstrbuf_strip_suffix(&maindir, \"/.git\");\n \tcmp = fspathcmp(maindir.buf, target.buf);\n \n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501810","messageId":"bb01e4fab9dd612a0b868b7eddeecc0fcaab3dfb.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 03/21] environment: make `get_object_directory()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:33Z","receivedAt":"2024-08-29T09:38:36Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_object_directory()` function retrieves the path to the object\ndirectory for `the_repository`. Make it accept a `struct repository`\nsuch that it can work on arbitrary repositories and make it part of the\nrepository subsystem. This reduces our reliance on `the_repository` and\nclarifies scope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/commit-graph.c     | 4 ++--\n builtin/count-objects.c    | 2 +-\n builtin/multi-pack-index.c | 2 +-\n builtin/pack-objects.c     | 2 +-\n builtin/prune.c            | 8 ++++----\n builtin/repack.c           | 7 ++++---\n bulk-checkin.c             | 4 ++--\n environment.c              | 7 -------\n environment.h              | 1 -\n fetch-pack.c               | 2 +-\n http-backend.c             | 2 +-\n object-file.c              | 4 ++--\n pack-write.c               | 2 +-\n packfile.c                 | 2 +-\n prune-packed.c             | 4 +++-\n repository.c               | 7 +++++++\n repository.h               | 1 +\n server-info.c              | 3 ++-\n setup.c                    | 2 +-\n tmp-objdir.c               | 7 ++++---\n 20 files changed, 39 insertions(+), 34 deletions(-)\n\ndiff --git a/builtin/commit-graph.c b/builtin/commit-graph.c\nindex 7102ee90a00..d7ebdf5c0d8 100644\n--- a/builtin/commit-graph.c\n+++ b/builtin/commit-graph.c\n@@ -95,7 +95,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(builtin_commit_graph_verify_usage, options);\n \n \tif (!opts.obj_dir)\n-\t\topts.obj_dir = get_object_directory();\n+\t\topts.obj_dir = repo_get_object_directory(the_repository);\n \tif (opts.shallow)\n \t\tflags |= COMMIT_GRAPH_VERIFY_SHALLOW;\n \tif (opts.progress)\n@@ -275,7 +275,7 @@ static int graph_write(int argc, const char **argv, const char *prefix)\n \tif (opts.reachable + opts.stdin_packs + opts.stdin_commits > 1)\n \t\tdie(_(\"use at most one of --reachable, --stdin-commits, or --stdin-packs\"));\n \tif (!opts.obj_dir)\n-\t\topts.obj_dir = get_object_directory();\n+\t\topts.obj_dir = repo_get_object_directory(the_repository);\n \tif (opts.append)\n \t\tflags |= COMMIT_GRAPH_WRITE_APPEND;\n \tif (opts.split)\ndiff --git a/builtin/count-objects.c b/builtin/count-objects.c\nindex ec6098a149d..bd99eeaa954 100644\n--- a/builtin/count-objects.c\n+++ b/builtin/count-objects.c\n@@ -116,7 +116,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)\n \t\treport_linked_checkout_garbage(the_repository);\n \t}\n \n-\tfor_each_loose_file_in_objdir(get_object_directory(),\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n \t\t\t\t      count_loose, count_cruft, NULL, NULL);\n \n \tif (verbose) {\ndiff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c\nindex 8805cbbeb3b..0b82f7480da 100644\n--- a/builtin/multi-pack-index.c\n+++ b/builtin/multi-pack-index.c\n@@ -63,7 +63,7 @@ static int parse_object_dir(const struct option *opt, const char *arg,\n \tchar **value = opt->value;\n \tfree(*value);\n \tif (unset)\n-\t\t*value = xstrdup(get_object_directory());\n+\t\t*value = xstrdup(repo_get_object_directory(the_repository));\n \telse\n \t\t*value = real_pathdup(arg, 1);\n \treturn 0;\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 778be80f564..44341b206d4 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -3940,7 +3940,7 @@ static int add_loose_object(const struct object_id *oid, const char *path,\n  */\n static void add_unreachable_loose_objects(void)\n {\n-\tfor_each_loose_file_in_objdir(get_object_directory(),\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n \t\t\t\t      add_loose_object,\n \t\t\t\t      NULL, NULL, NULL);\n }\ndiff --git a/builtin/prune.c b/builtin/prune.c\nindex 57fe31467fe..47eeabbd13a 100644\n--- a/builtin/prune.c\n+++ b/builtin/prune.c\n@@ -193,12 +193,12 @@ int cmd_prune(int argc, const char **argv, const char *prefix)\n \t\trevs.exclude_promisor_objects = 1;\n \t}\n \n-\tfor_each_loose_file_in_objdir(get_object_directory(), prune_object,\n-\t\t\t\t      prune_cruft, prune_subdir, &revs);\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n+\t\t\t\t      prune_object, prune_cruft, prune_subdir, &revs);\n \n \tprune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0);\n-\tremove_temporary_files(get_object_directory());\n-\ts = mkpathdup(\"%s/pack\", get_object_directory());\n+\tremove_temporary_files(repo_get_object_directory(the_repository));\n+\ts = mkpathdup(\"%s/pack\", repo_get_object_directory(the_repository));\n \tremove_temporary_files(s);\n \tfree(s);\n \ndiff --git a/builtin/repack.c b/builtin/repack.c\nindex 62cfa50c50f..40feacb73f8 100644\n--- a/builtin/repack.c\n+++ b/builtin/repack.c\n@@ -1240,7 +1240,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \tif (write_midx && write_bitmaps) {\n \t\tstruct strbuf path = STRBUF_INIT;\n \n-\t\tstrbuf_addf(&path, \"%s/%s_XXXXXX\", get_object_directory(),\n+\t\tstrbuf_addf(&path, \"%s/%s_XXXXXX\", repo_get_object_directory(the_repository),\n \t\t\t    \"bitmap-ref-tips\");\n \n \t\trefs_snapshot = xmks_tempfile(path.buf);\n@@ -1249,7 +1249,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\tstrbuf_release(&path);\n \t}\n \n-\tpackdir = mkpathdup(\"%s/pack\", get_object_directory());\n+\tpackdir = mkpathdup(\"%s/pack\", repo_get_object_directory(the_repository));\n \tpacktmp_name = xstrfmt(\".tmp-%d-pack\", (int)getpid());\n \tpacktmp = mkpathdup(\"%s/%s\", packdir, packtmp_name);\n \n@@ -1519,7 +1519,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\tunsigned flags = 0;\n \t\tif (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL, 0))\n \t\t\tflags |= MIDX_WRITE_INCREMENTAL;\n-\t\twrite_midx_file(get_object_directory(), NULL, NULL, flags);\n+\t\twrite_midx_file(repo_get_object_directory(the_repository),\n+\t\t\t\tNULL, NULL, flags);\n \t}\n \n cleanup:\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex 9089c214fa4..2753d5bbe4a 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -75,7 +75,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state)\n \t\tclose(fd);\n \t}\n \n-\tstrbuf_addf(&packname, \"%s/pack/pack-%s.\", get_object_directory(),\n+\tstrbuf_addf(&packname, \"%s/pack/pack-%s.\", repo_get_object_directory(the_repository),\n \t\t    hash_to_hex(hash));\n \tfinish_tmp_packfile(&packname, state->pack_tmp_name,\n \t\t\t    state->written, state->nr_written,\n@@ -113,7 +113,7 @@ static void flush_batch_fsync(void)\n \t * to ensure that the data in each new object file is durable before\n \t * the final name is visible.\n \t */\n-\tstrbuf_addf(&temp_path, \"%s/bulk_fsync_XXXXXX\", get_object_directory());\n+\tstrbuf_addf(&temp_path, \"%s/bulk_fsync_XXXXXX\", repo_get_object_directory(the_repository));\n \ttemp = xmks_tempfile(temp_path.buf);\n \tfsync_or_die(get_tempfile_fd(temp), get_tempfile_path(temp));\n \tdelete_tempfile(&temp);\ndiff --git a/environment.c b/environment.c\nindex 7c4a142ca25..0a2057399e0 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -273,13 +273,6 @@ const char *get_git_work_tree(void)\n \treturn the_repository->worktree;\n }\n \n-const char *get_object_directory(void)\n-{\n-\tif (!the_repository->objects->odb)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->objects->odb->path;\n-}\n-\n int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n {\n \tint fd;\ndiff --git a/environment.h b/environment.h\nindex d778614158f..91125d82991 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_object_directory(void);\n char *get_index_file(void);\n char *get_graft_file(struct repository *r);\n void set_git_dir(const char *path, int make_realpath);\ndiff --git a/fetch-pack.c b/fetch-pack.c\nindex 58b4581ad80..fddb90f2e78 100644\n--- a/fetch-pack.c\n+++ b/fetch-pack.c\n@@ -1839,7 +1839,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,\n \n \t\tstring_list_append_nodup(pack_lockfiles,\n \t\t\t\t\t xstrfmt(\"%s/pack/pack-%s.keep\",\n-\t\t\t\t\t\t get_object_directory(),\n+\t\t\t\t\t\t repo_get_object_directory(the_repository),\n \t\t\t\t\t\t packname));\n \t}\n \tstring_list_clear(&packfile_uris, 0);\ndiff --git a/http-backend.c b/http-backend.c\nindex 79ce097359b..73eec4ea3d8 100644\n--- a/http-backend.c\n+++ b/http-backend.c\n@@ -601,7 +601,7 @@ static void get_head(struct strbuf *hdr, char *arg UNUSED)\n \n static void get_info_packs(struct strbuf *hdr, char *arg UNUSED)\n {\n-\tsize_t objdirlen = strlen(get_object_directory());\n+\tsize_t objdirlen = strlen(repo_get_object_directory(the_repository));\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct packed_git *p;\n \tsize_t cnt = 0;\ndiff --git a/object-file.c b/object-file.c\nindex c5994202ba0..fa4121b98ad 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2053,7 +2053,7 @@ static int start_loose_object_common(struct strbuf *tmp_file,\n \t\telse if (errno == EACCES)\n \t\t\treturn error(_(\"insufficient permission for adding \"\n \t\t\t\t       \"an object to repository database %s\"),\n-\t\t\t\t     get_object_directory());\n+\t\t\t\t     repo_get_object_directory(the_repository));\n \t\telse\n \t\t\treturn error_errno(\n \t\t\t\t_(\"unable to create temporary file\"));\n@@ -2228,7 +2228,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,\n \t\tprepare_loose_object_bulk_checkin();\n \n \t/* Since oid is not determined, save tmp file to odb path. */\n-\tstrbuf_addf(&filename, \"%s/\", get_object_directory());\n+\tstrbuf_addf(&filename, \"%s/\", repo_get_object_directory(the_repository));\n \thdrlen = format_object_header(hdr, sizeof(hdr), OBJ_BLOB, len);\n \n \t/*\ndiff --git a/pack-write.c b/pack-write.c\nindex d07f03d0ab0..6cd3f9ef4c6 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -473,7 +473,7 @@ char *index_pack_lockfile(int ip_out, int *is_well_formed)\n \t\tpackname[len-1] = 0;\n \t\tif (skip_prefix(packname, \"keep\\t\", &name))\n \t\t\treturn xstrfmt(\"%s/pack/pack-%s.keep\",\n-\t\t\t\t       get_object_directory(), name);\n+\t\t\t\t       repo_get_object_directory(the_repository), name);\n \t\treturn NULL;\n \t}\n \tif (is_well_formed)\ndiff --git a/packfile.c b/packfile.c\nindex cf12a539eac..df4ba677197 100644\n--- a/packfile.c\n+++ b/packfile.c\n@@ -30,7 +30,7 @@ char *odb_pack_name(struct strbuf *buf,\n \t\t    const char *ext)\n {\n \tstrbuf_reset(buf);\n-\tstrbuf_addf(buf, \"%s/pack/pack-%s.%s\", get_object_directory(),\n+\tstrbuf_addf(buf, \"%s/pack/pack-%s.%s\", repo_get_object_directory(the_repository),\n \t\t    hash_to_hex(hash), ext);\n \treturn buf->buf;\n }\ndiff --git a/prune-packed.c b/prune-packed.c\nindex e54daf740a2..4418268207f 100644\n--- a/prune-packed.c\n+++ b/prune-packed.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\n@@ -37,7 +39,7 @@ void prune_packed_objects(int opts)\n \tif (opts & PRUNE_PACKED_VERBOSE)\n \t\tprogress = start_delayed_progress(_(\"Removing duplicate objects\"), 256);\n \n-\tfor_each_loose_file_in_objdir(get_object_directory(),\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n \t\t\t\t      prune_object, NULL, prune_subdir, &opts);\n \n \t/* Ensure we show 100% before finishing progress */\ndiff --git a/repository.c b/repository.c\nindex acf654d7ab6..914ee25a1f0 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -105,6 +105,13 @@ const char *repo_get_common_dir(struct repository *repo)\n \treturn repo->commondir;\n }\n \n+const char *repo_get_object_directory(struct repository *repo)\n+{\n+\tif (!repo->objects->odb)\n+\t\tBUG(\"git environment hasn't been setup\");\n+\treturn repo->objects->odb->path;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex 404435ad029..778f1511ab1 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -208,6 +208,7 @@ extern struct repository *the_repository;\n \n const char *repo_get_git_dir(struct repository *repo);\n const char *repo_get_common_dir(struct repository *repo);\n+const char *repo_get_object_directory(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/server-info.c b/server-info.c\nindex 1508fa6f825..ffca36f4675 100644\n--- a/server-info.c\n+++ b/server-info.c\n@@ -342,7 +342,8 @@ static int write_pack_info_file(struct update_info_ctx *uic)\n \n static int update_info_packs(int force)\n {\n-\tchar *infofile = mkpathdup(\"%s/info/packs\", get_object_directory());\n+\tchar *infofile = mkpathdup(\"%s/info/packs\",\n+\t\t\t\t   repo_get_object_directory(the_repository));\n \tint ret;\n \n \tinit_pack_info(infofile, force);\ndiff --git a/setup.c b/setup.c\nindex fe4a5dfc43b..1ebcab625fe 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2282,7 +2282,7 @@ static void create_object_directory(void)\n \tstruct strbuf path = STRBUF_INIT;\n \tsize_t baselen;\n \n-\tstrbuf_addstr(&path, get_object_directory());\n+\tstrbuf_addstr(&path, repo_get_object_directory(the_repository));\n \tbaselen = path.len;\n \n \tsafe_create_dir(path.buf, 1);\ndiff --git a/tmp-objdir.c b/tmp-objdir.c\nindex a8e4553f274..b648bf97992 100644\n--- a/tmp-objdir.c\n+++ b/tmp-objdir.c\n@@ -132,7 +132,8 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix)\n \t * can recognize any stale objdirs left behind by a crash and delete\n \t * them.\n \t */\n-\tstrbuf_addf(&t->path, \"%s/tmp_objdir-%s-XXXXXX\", get_object_directory(), prefix);\n+\tstrbuf_addf(&t->path, \"%s/tmp_objdir-%s-XXXXXX\",\n+\t\t    repo_get_object_directory(the_repository), prefix);\n \n \tif (!mkdtemp(t->path.buf)) {\n \t\t/* free, not destroy, as we never touched the filesystem */\n@@ -152,7 +153,7 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix)\n \t}\n \n \tenv_append(&t->env, ALTERNATE_DB_ENVIRONMENT,\n-\t\t   absolute_path(get_object_directory()));\n+\t\t   absolute_path(repo_get_object_directory(the_repository)));\n \tenv_replace(&t->env, DB_ENVIRONMENT, absolute_path(t->path.buf));\n \tenv_replace(&t->env, GIT_QUARANTINE_ENVIRONMENT,\n \t\t    absolute_path(t->path.buf));\n@@ -267,7 +268,7 @@ int tmp_objdir_migrate(struct tmp_objdir *t)\n \t}\n \n \tstrbuf_addbuf(&src, &t->path);\n-\tstrbuf_addstr(&dst, get_object_directory());\n+\tstrbuf_addstr(&dst, repo_get_object_directory(the_repository));\n \n \tret = migrate_paths(&src, &dst);\n \n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501811","messageId":"d857c5fab44a8592b397dd0495c6582b9d22227d.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 04/21] environment: make `get_index_file()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:35Z","receivedAt":"2024-08-29T09:38:38Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_index_file()` function retrieves the path to the index file\nof `the_repository`. Make it accept a `struct repository` such that it\ncan work on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/am.c           |  8 ++++++--\n builtin/commit.c       |  6 +++---\n builtin/merge.c        | 14 ++++++++------\n builtin/stash.c        | 12 ++++++------\n builtin/update-index.c |  2 +-\n builtin/write-tree.c   |  3 ++-\n environment.c          |  7 -------\n environment.h          |  1 -\n repository.c           |  7 +++++++\n repository.h           |  1 +\n wt-status.c            |  2 +-\n 11 files changed, 35 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 405214e242a..5498ddeb6aa 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1668,7 +1668,9 @@ static void do_commit(const struct am_state *state)\n \tif (!state->no_verify && run_hooks(the_repository, \"pre-applypatch\"))\n \t\texit(1);\n \n-\tif (write_index_as_tree(&tree, the_repository->index, get_index_file(), 0, NULL))\n+\tif (write_index_as_tree(&tree, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository),\n+\t\t\t\t0, NULL))\n \t\tdie(_(\"git write-tree failed to write a tree\"));\n \n \tif (!repo_get_oid_commit(the_repository, \"HEAD\", &parent)) {\n@@ -2078,7 +2080,9 @@ static int clean_index(const struct object_id *head, const struct object_id *rem\n \tif (fast_forward_to(head_tree, head_tree, 1))\n \t\treturn -1;\n \n-\tif (write_index_as_tree(&index, the_repository->index, get_index_file(), 0, NULL))\n+\tif (write_index_as_tree(&index, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository),\n+\t\t\t\t0, NULL))\n \t\treturn -1;\n \n \tindex_tree = parse_tree_indirect(&index);\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 55124ee28f0..dea1733c6f6 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -472,7 +472,7 @@ static const char *prepare_index(const char **argv, const char *prefix,\n \t\t\t\t       COMMIT_LOCK | SKIP_IF_UNCHANGED))\n \t\t\tdie(_(\"unable to write new index file\"));\n \t\tcommit_style = COMMIT_AS_IS;\n-\t\tret = get_index_file();\n+\t\tret = repo_get_index_file(the_repository);\n \t\tgoto out;\n \t}\n \n@@ -1873,8 +1873,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \n \trepo_rerere(the_repository, 0);\n \trun_auto_maintenance(quiet);\n-\trun_commit_hook(use_editor, get_index_file(), NULL, \"post-commit\",\n-\t\t\tNULL);\n+\trun_commit_hook(use_editor, repo_get_index_file(the_repository),\n+\t\t\tNULL, \"post-commit\", NULL);\n \tif (amend && !no_post_rewrite) {\n \t\tcommit_post_rewrite(the_repository, current_head, &oid);\n \t}\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 6c22912b63c..80ea1d52eef 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -695,7 +695,9 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,\n \n static void write_tree_trivial(struct object_id *oid)\n {\n-\tif (write_index_as_tree(oid, the_repository->index, get_index_file(), 0, NULL))\n+\tif (write_index_as_tree(oid, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository),\n+\t\t\t\t0, NULL))\n \t\tdie(_(\"git write-tree failed to write a tree\"));\n }\n \n@@ -757,7 +759,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,\n \t\t}\n \t\tif (write_locked_index(the_repository->index, &lock,\n \t\t\t\t       COMMIT_LOCK | SKIP_IF_UNCHANGED))\n-\t\t\tdie(_(\"unable to write %s\"), get_index_file());\n+\t\t\tdie(_(\"unable to write %s\"), repo_get_index_file(the_repository));\n \t\treturn clean ? 0 : 1;\n \t} else {\n \t\treturn try_merge_command(the_repository,\n@@ -839,7 +841,7 @@ static void write_merge_heads(struct commit_list *);\n static void prepare_to_commit(struct commit_list *remoteheads)\n {\n \tstruct strbuf msg = STRBUF_INIT;\n-\tconst char *index_file = get_index_file();\n+\tconst char *index_file = repo_get_index_file(the_repository);\n \n \tif (!no_verify) {\n \t\tint invoked_hook;\n@@ -879,8 +881,8 @@ static void prepare_to_commit(struct commit_list *remoteheads)\n \t\tappend_signoff(&msg, ignored_log_message_bytes(msg.buf, msg.len), 0);\n \twrite_merge_heads(remoteheads);\n \twrite_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len);\n-\tif (run_commit_hook(0 < option_edit, get_index_file(), NULL,\n-\t\t\t    \"prepare-commit-msg\",\n+\tif (run_commit_hook(0 < option_edit, repo_get_index_file(the_repository),\n+\t\t\t    NULL, \"prepare-commit-msg\",\n \t\t\t    git_path_merge_msg(the_repository), \"merge\", NULL))\n \t\tabort_commit(remoteheads, NULL);\n \tif (0 < option_edit) {\n@@ -888,7 +890,7 @@ static void prepare_to_commit(struct commit_list *remoteheads)\n \t\t\tabort_commit(remoteheads, NULL);\n \t}\n \n-\tif (!no_verify && run_commit_hook(0 < option_edit, get_index_file(),\n+\tif (!no_verify && run_commit_hook(0 < option_edit, repo_get_index_file(the_repository),\n \t\t\t\t\t  NULL, \"commit-msg\",\n \t\t\t\t\t  git_path_merge_msg(the_repository), NULL))\n \t\tabort_commit(remoteheads, NULL);\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex ed56299098e..ae42da02b97 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -539,8 +539,8 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\t\t\t\t NULL, NULL, NULL))\n \t\treturn error(_(\"could not write index\"));\n \n-\tif (write_index_as_tree(&c_tree, the_repository->index, get_index_file(), 0,\n-\t\t\t\tNULL))\n+\tif (write_index_as_tree(&c_tree, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository), 0, NULL))\n \t\treturn error(_(\"cannot apply a stash in the middle of a merge\"));\n \n \tif (index) {\n@@ -565,7 +565,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\t\tdiscard_index(the_repository->index);\n \t\t\trepo_read_index(the_repository);\n \t\t\tif (write_index_as_tree(&index_tree, the_repository->index,\n-\t\t\t\t\t\tget_index_file(), 0, NULL))\n+\t\t\t\t\t\trepo_get_index_file(the_repository), 0, NULL))\n \t\t\t\treturn error(_(\"could not save index tree\"));\n \n \t\t\treset_head();\n@@ -1405,8 +1405,8 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \n \tstrbuf_addf(&commit_tree_label, \"index on %s\\n\", msg.buf);\n \tcommit_list_insert(head_commit, &parents);\n-\tif (write_index_as_tree(&info->i_tree, the_repository->index, get_index_file(), 0,\n-\t\t\t\tNULL) ||\n+\tif (write_index_as_tree(&info->i_tree, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository), 0, NULL) ||\n \t    commit_tree(commit_tree_label.buf, commit_tree_label.len,\n \t\t\t&info->i_tree, parents, &info->i_commit, NULL, NULL)) {\n \t\tif (!quiet)\n@@ -1904,7 +1904,7 @@ int cmd_stash(int argc, const char **argv, const char *prefix)\n \tprepare_repo_settings(the_repository);\n \tthe_repository->settings.command_requires_full_index = 0;\n \n-\tindex_file = get_index_file();\n+\tindex_file = repo_get_index_file(the_repository);\n \tstrbuf_addf(&stash_index_path, \"%s.stash.%\" PRIuMAX, index_file,\n \t\t    (uintmax_t)pid);\n \ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex 35a1f957adc..86c5d40e400 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -1239,7 +1239,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t\tif (newfd < 0) {\n \t\t\tif (refresh_args.flags & REFRESH_QUIET)\n \t\t\t\texit(128);\n-\t\t\tunable_to_lock_die(get_index_file(), lock_error);\n+\t\t\tunable_to_lock_die(repo_get_index_file(the_repository), lock_error);\n \t\t}\n \t\tif (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))\n \t\t\tdie(\"Unable to write new index file\");\ndiff --git a/builtin/write-tree.c b/builtin/write-tree.c\nindex 8c75b4609b5..a1b29737214 100644\n--- a/builtin/write-tree.c\n+++ b/builtin/write-tree.c\n@@ -44,7 +44,8 @@ int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix)\n \tprepare_repo_settings(the_repository);\n \tthe_repository->settings.command_requires_full_index = 0;\n \n-\tret = write_index_as_tree(&oid, the_repository->index, get_index_file(),\n+\tret = write_index_as_tree(&oid, the_repository->index,\n+\t\t\t\t  repo_get_index_file(the_repository),\n \t\t\t\t  flags, tree_prefix);\n \tswitch (ret) {\n \tcase 0:\ndiff --git a/environment.c b/environment.c\nindex 0a2057399e0..10ef77576c3 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -306,13 +306,6 @@ int odb_pack_keep(const char *name)\n \treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n }\n \n-char *get_index_file(void)\n-{\n-\tif (!the_repository->index_file)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->index_file;\n-}\n-\n char *get_graft_file(struct repository *r)\n {\n \tif (!r->graft_file)\ndiff --git a/environment.h b/environment.h\nindex 91125d82991..ff590cfff73 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-char *get_index_file(void);\n char *get_graft_file(struct repository *r);\n void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\ndiff --git a/repository.c b/repository.c\nindex 914ee25a1f0..a9bbde80b5d 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -112,6 +112,13 @@ const char *repo_get_object_directory(struct repository *repo)\n \treturn repo->objects->odb->path;\n }\n \n+const char *repo_get_index_file(struct repository *repo)\n+{\n+\tif (!repo->index_file)\n+\t\tBUG(\"git environment hasn't been setup\");\n+\treturn repo->index_file;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex 778f1511ab1..15660ac2f19 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -209,6 +209,7 @@ extern struct repository *the_repository;\n const char *repo_get_git_dir(struct repository *repo);\n const char *repo_get_common_dir(struct repository *repo);\n const char *repo_get_object_directory(struct repository *repo);\n+const char *repo_get_index_file(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/wt-status.c b/wt-status.c\nindex b477239039d..b41db1451ba 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -152,7 +152,7 @@ void wt_status_prepare(struct repository *r, struct wt_status *s)\n \t\t\t\t\t\"HEAD\", 0, NULL, NULL);\n \ts->reference = \"HEAD\";\n \ts->fp = stdout;\n-\ts->index_file = get_index_file();\n+\ts->index_file = repo_get_index_file(the_repository);\n \ts->change.strdup_strings = 1;\n \ts->untracked.strdup_strings = 1;\n \ts->ignored.strdup_strings = 1;\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501812","messageId":"ac27d7128a41e4693a19afe0b1931d0c1db75d09.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 05/21] environment: make `get_graft_file()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:38Z","receivedAt":"2024-08-29T09:38:41Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_graft_file()` function retrieves the path to the graft file of\n`the_repository`. Make it accept a `struct repository` such that it can\nwork on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/replace.c | 2 +-\n commit.c          | 4 ++--\n environment.c     | 7 -------\n environment.h     | 2 --\n repository.c      | 7 +++++++\n repository.h      | 1 +\n 6 files changed, 11 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 34cc4672bc1..04fbe580895 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -514,7 +514,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle)\n \n static int convert_graft_file(int force)\n {\n-\tconst char *graft_file = get_graft_file(the_repository);\n+\tconst char *graft_file = repo_get_graft_file(the_repository);\n \tFILE *fp = fopen_or_warn(graft_file, \"r\");\n \tstruct strbuf buf = STRBUF_INIT, err = STRBUF_INIT;\n \tstruct strvec args = STRVEC_INIT;\ndiff --git a/commit.c b/commit.c\nindex 3238772f521..1f710a92a17 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -292,14 +292,14 @@ static int read_graft_file(struct repository *r, const char *graft_file)\n \n void prepare_commit_graft(struct repository *r)\n {\n-\tchar *graft_file;\n+\tconst char *graft_file;\n \n \tif (r->parsed_objects->commit_graft_prepared)\n \t\treturn;\n \tif (!startup_info->have_repository)\n \t\treturn;\n \n-\tgraft_file = get_graft_file(r);\n+\tgraft_file = repo_get_graft_file(r);\n \tread_graft_file(r, graft_file);\n \t/* make sure shallows are read */\n \tis_repository_shallow(r);\ndiff --git a/environment.c b/environment.c\nindex 10ef77576c3..371f01a705d 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -306,13 +306,6 @@ int odb_pack_keep(const char *name)\n \treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n }\n \n-char *get_graft_file(struct repository *r)\n-{\n-\tif (!r->graft_file)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn r->graft_file;\n-}\n-\n static void set_git_dir_1(const char *path)\n {\n \txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\ndiff --git a/environment.h b/environment.h\nindex ff590cfff73..d12c48481b6 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -1,7 +1,6 @@\n #ifndef ENVIRONMENT_H\n #define ENVIRONMENT_H\n \n-struct repository;\n struct strvec;\n \n /*\n@@ -106,7 +105,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-char *get_graft_file(struct repository *r);\n void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\ndiff --git a/repository.c b/repository.c\nindex a9bbde80b5d..cdefcb4002d 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -119,6 +119,13 @@ const char *repo_get_index_file(struct repository *repo)\n \treturn repo->index_file;\n }\n \n+const char *repo_get_graft_file(struct repository *repo)\n+{\n+\tif (!repo->graft_file)\n+\t\tBUG(\"git environment hasn't been setup\");\n+\treturn repo->graft_file;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex 15660ac2f19..ad0f984b444 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -210,6 +210,7 @@ const char *repo_get_git_dir(struct repository *repo);\n const char *repo_get_common_dir(struct repository *repo);\n const char *repo_get_object_directory(struct repository *repo);\n const char *repo_get_index_file(struct repository *repo);\n+const char *repo_get_graft_file(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501813","messageId":"7fc346d3bb5c470a373d089b60f10204d3fd8efb.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 06/21] environment: make `get_git_work_tree()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:41Z","receivedAt":"2024-08-29T09:38:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_git_work_tree()` function retrieves the path of the work tree\nof `the_repository`. Make it accept a `struct repository` such that it\ncan work on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/blame.c             |  2 +-\n builtin/difftool.c          |  4 ++--\n builtin/fsmonitor--daemon.c |  3 ++-\n builtin/init-db.c           |  4 ++--\n builtin/reset.c             |  4 ++--\n builtin/rev-parse.c         |  4 ++--\n builtin/stash.c             |  2 +-\n builtin/submodule--helper.c |  2 +-\n builtin/update-index.c      |  2 +-\n dir.c                       |  2 +-\n environment.c               |  7 +------\n environment.h               |  1 -\n fsmonitor.c                 |  2 +-\n pathspec.c                  |  2 +-\n repository.c                |  5 +++++\n repository.h                |  1 +\n setup.c                     | 16 ++++++++--------\n trace.c                     |  2 +-\n 18 files changed, 33 insertions(+), 32 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 35e975fb132..1ffdda50904 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -1081,7 +1081,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t\tpath = add_prefix(prefix, argv[1]);\n \t\t\targv[1] = argv[2];\n \t\t} else {\t/* (2a) */\n-\t\t\tif (argc == 2 && is_a_rev(argv[1]) && !get_git_work_tree())\n+\t\t\tif (argc == 2 && is_a_rev(argv[1]) && !repo_get_work_tree(the_repository))\n \t\t\t\tdie(\"missing <path> to blame\");\n \t\t\tpath = add_prefix(prefix, argv[argc - 1]);\n \t\t}\ndiff --git a/builtin/difftool.c b/builtin/difftool.c\nindex da9315e84d4..7c16c55baaf 100644\n--- a/builtin/difftool.c\n+++ b/builtin/difftool.c\n@@ -377,7 +377,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,\n \tstruct hashmap wt_modified, tmp_modified;\n \tint indices_loaded = 0;\n \n-\tworkdir = get_git_work_tree();\n+\tworkdir = repo_get_work_tree(the_repository);\n \n \t/* Setup temp directories */\n \ttmp = getenv(\"TMPDIR\");\n@@ -738,7 +738,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)\n \tif (!no_index){\n \t\tsetup_work_tree();\n \t\tsetenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1);\n-\t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);\n+\t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(the_repository)), 1);\n \t} else if (dir_diff)\n \t\tdie(_(\"options '%s' and '%s' cannot be used together\"), \"--dir-diff\", \"--no-index\");\n \ndiff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c\nindex c54e736716a..d7de0427845 100644\n--- a/builtin/fsmonitor--daemon.c\n+++ b/builtin/fsmonitor--daemon.c\n@@ -1291,7 +1291,8 @@ static int fsmonitor_run_daemon(void)\n \n \t/* Prepare to (recursively) watch the <worktree-root> directory. */\n \tstrbuf_init(&state.path_worktree_watch, 0);\n-\tstrbuf_addstr(&state.path_worktree_watch, absolute_path(get_git_work_tree()));\n+\tstrbuf_addstr(&state.path_worktree_watch,\n+\t\t      absolute_path(repo_get_work_tree(the_repository)));\n \tstate.nr_paths_watching = 1;\n \n \tstrbuf_init(&state.alias.alias, 0);\ndiff --git a/builtin/init-db.c b/builtin/init-db.c\nindex 582dcf20f86..fb04962dcea 100644\n--- a/builtin/init-db.c\n+++ b/builtin/init-db.c\n@@ -231,9 +231,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)\n \t\t\tset_git_work_tree(work_tree);\n \t\telse\n \t\t\tset_git_work_tree(git_work_tree_cfg);\n-\t\tif (access(get_git_work_tree(), X_OK))\n+\t\tif (access(repo_get_work_tree(the_repository), X_OK))\n \t\t\tdie_errno (_(\"Cannot access work tree '%s'\"),\n-\t\t\t\t   get_git_work_tree());\n+\t\t\t\t   repo_get_work_tree(the_repository));\n \t}\n \telse {\n \t\tif (real_git_dir)\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 5f941fb3a29..2e5f477339b 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -441,7 +441,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \telse\n \t\ttrace2_cmd_mode(reset_type_names[reset_type]);\n \n-\tif (reset_type != SOFT && (reset_type != MIXED || get_git_work_tree()))\n+\tif (reset_type != SOFT && (reset_type != MIXED || repo_get_work_tree(the_repository)))\n \t\tsetup_work_tree();\n \n \tif (reset_type == MIXED && is_bare_repository())\n@@ -474,7 +474,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\t\t\tgoto cleanup;\n \t\t\t}\n \t\t\tthe_repository->index->updated_skipworktree = 1;\n-\t\t\tif (!no_refresh && get_git_work_tree()) {\n+\t\t\tif (!no_refresh && repo_get_work_tree(the_repository)) {\n \t\t\t\tuint64_t t_begin, t_delta_in_ms;\n \n \t\t\t\tt_begin = getnanotime();\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex 4308a2a8549..65b0b5e2c0a 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -966,7 +966,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--show-toplevel\")) {\n-\t\t\t\tconst char *work_tree = get_git_work_tree();\n+\t\t\t\tconst char *work_tree = repo_get_work_tree(the_repository);\n \t\t\t\tif (work_tree)\n \t\t\t\t\tprint_path(work_tree, prefix, format, DEFAULT_UNMODIFIED);\n \t\t\t\telse\n@@ -991,7 +991,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tconst char *pfx = prefix;\n \t\t\t\tif (!is_inside_work_tree()) {\n \t\t\t\t\tconst char *work_tree =\n-\t\t\t\t\t\tget_git_work_tree();\n+\t\t\t\t\t\trepo_get_work_tree(the_repository);\n \t\t\t\t\tif (work_tree)\n \t\t\t\t\t\tprintf(\"%s\\n\", work_tree);\n \t\t\t\t\tcontinue;\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex ae42da02b97..bc22164dd75 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -640,7 +640,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\tcp.git_cmd = 1;\n \t\tcp.dir = prefix;\n \t\tstrvec_pushf(&cp.env, GIT_WORK_TREE_ENVIRONMENT\"=%s\",\n-\t\t\t     absolute_path(get_git_work_tree()));\n+\t\t\t     absolute_path(repo_get_work_tree(the_repository)));\n \t\tstrvec_pushf(&cp.env, GIT_DIR_ENVIRONMENT\"=%s\",\n \t\t\t     absolute_path(repo_get_git_dir(the_repository)));\n \t\tstrvec_push(&cp.args, \"status\");\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 85fb23dee84..865b454d693 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1709,7 +1709,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,\n \t\texit(128);\n \n \tif (!is_absolute_path(clone_data->path))\n-\t\tclone_data_path = to_free = xstrfmt(\"%s/%s\", get_git_work_tree(),\n+\t\tclone_data_path = to_free = xstrfmt(\"%s/%s\", repo_get_work_tree(the_repository),\n \t\t\t\t\t\t    clone_data->path);\n \n \tif (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)\ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex 86c5d40e400..8baa2256194 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -1194,7 +1194,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t\t\t\t  \"remove or change it, if you really want to \"\n \t\t\t\t  \"enable the untracked cache\"));\n \t\tadd_untracked_cache(the_repository->index);\n-\t\treport(_(\"Untracked cache enabled for '%s'\"), get_git_work_tree());\n+\t\treport(_(\"Untracked cache enabled for '%s'\"), repo_get_work_tree(the_repository));\n \t\tbreak;\n \tdefault:\n \t\tBUG(\"bad untracked_cache value: %d\", untracked_cache);\ndiff --git a/dir.c b/dir.c\nindex 5a23376bdae..2a8690dadd0 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -2838,7 +2838,7 @@ static const char *get_ident_string(void)\n \t\treturn sb.buf;\n \tif (uname(&uts) < 0)\n \t\tdie_errno(_(\"failed to get kernel name and information\"));\n-\tstrbuf_addf(&sb, \"Location %s, system %s\", get_git_work_tree(),\n+\tstrbuf_addf(&sb, \"Location %s, system %s\", repo_get_work_tree(the_repository),\n \t\t    uts.sysname);\n \treturn sb.buf;\n }\ndiff --git a/environment.c b/environment.c\nindex 371f01a705d..4d0637b3822 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -219,7 +219,7 @@ void setup_git_env(const char *git_dir)\n int is_bare_repository(void)\n {\n \t/* if core.bare is not 'false', let's see if there is a work tree */\n-\treturn is_bare_repository_cfg && !get_git_work_tree();\n+\treturn is_bare_repository_cfg && !repo_get_work_tree(the_repository);\n }\n \n int have_git_dir(void)\n@@ -268,11 +268,6 @@ void set_git_work_tree(const char *new_work_tree)\n \trepo_set_worktree(the_repository, new_work_tree);\n }\n \n-const char *get_git_work_tree(void)\n-{\n-\treturn the_repository->worktree;\n-}\n-\n int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n {\n \tint fd;\ndiff --git a/environment.h b/environment.h\nindex d12c48481b6..52e1803aba6 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -108,7 +108,6 @@ extern char *git_work_tree_cfg;\n void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\n-const char *get_git_work_tree(void);\n void set_git_work_tree(const char *tree);\n \n #define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\ndiff --git a/fsmonitor.c b/fsmonitor.c\nindex 28130f748f7..cbc12f060e2 100644\n--- a/fsmonitor.c\n+++ b/fsmonitor.c\n@@ -169,7 +169,7 @@ static int query_fsmonitor_hook(struct repository *r,\n \tstrvec_pushf(&cp.args, \"%d\", version);\n \tstrvec_pushf(&cp.args, \"%s\", last_update);\n \tcp.use_shell = 1;\n-\tcp.dir = get_git_work_tree();\n+\tcp.dir = repo_get_work_tree(the_repository);\n \n \ttrace2_region_enter(\"fsm_hook\", \"query\", NULL);\n \ndiff --git a/pathspec.c b/pathspec.c\nindex 416fe1e3dcc..0fc6f84a6e6 100644\n--- a/pathspec.c\n+++ b/pathspec.c\n@@ -495,7 +495,7 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,\n \t\t\tif (!have_git_dir())\n \t\t\t\tdie(_(\"'%s' is outside the directory tree\"),\n \t\t\t\t    copyfrom);\n-\t\t\thint_path = get_git_work_tree();\n+\t\t\thint_path = repo_get_work_tree(the_repository);\n \t\t\tif (!hint_path)\n \t\t\t\thint_path = repo_get_git_dir(the_repository);\n \t\t\tdie(_(\"%s: '%s' is outside repository at '%s'\"), elt,\ndiff --git a/repository.c b/repository.c\nindex cdefcb4002d..92238da3d9e 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -126,6 +126,11 @@ const char *repo_get_graft_file(struct repository *repo)\n \treturn repo->graft_file;\n }\n \n+const char *repo_get_work_tree(struct repository *repo)\n+{\n+\treturn repo->worktree;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex ad0f984b444..c603e969ae7 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -211,6 +211,7 @@ const char *repo_get_common_dir(struct repository *repo);\n const char *repo_get_object_directory(struct repository *repo);\n const char *repo_get_index_file(struct repository *repo);\n const char *repo_get_graft_file(struct repository *repo);\n+const char *repo_get_work_tree(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/setup.c b/setup.c\nindex 1ebcab625fe..1bfec288ab6 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -51,7 +51,7 @@ static int abspath_part_inside_repo(char *path)\n \tsize_t wtlen;\n \tchar *path0;\n \tint off;\n-\tconst char *work_tree = precompose_string_if_needed(get_git_work_tree());\n+\tconst char *work_tree = precompose_string_if_needed(repo_get_work_tree(the_repository));\n \tstruct strbuf realpath = STRBUF_INIT;\n \n \tif (!work_tree)\n@@ -147,7 +147,7 @@ char *prefix_path(const char *prefix, int len, const char *path)\n {\n \tchar *r = prefix_path_gently(prefix, len, NULL, path);\n \tif (!r) {\n-\t\tconst char *hint_path = get_git_work_tree();\n+\t\tconst char *hint_path = repo_get_work_tree(the_repository);\n \t\tif (!hint_path)\n \t\t\thint_path = repo_get_git_dir(the_repository);\n \t\tdie(_(\"'%s' is outside repository at '%s'\"), path,\n@@ -475,7 +475,7 @@ int is_inside_git_dir(void)\n int is_inside_work_tree(void)\n {\n \tif (inside_work_tree < 0)\n-\t\tinside_work_tree = is_inside_dir(get_git_work_tree());\n+\t\tinside_work_tree = is_inside_dir(repo_get_work_tree(the_repository));\n \treturn inside_work_tree;\n }\n \n@@ -490,7 +490,7 @@ void setup_work_tree(void)\n \tif (work_tree_config_is_bogus)\n \t\tdie(_(\"unable to set up work tree using invalid config\"));\n \n-\twork_tree = get_git_work_tree();\n+\twork_tree = repo_get_work_tree(the_repository);\n \tif (!work_tree || chdir_notify(work_tree))\n \t\tdie(_(\"this operation must be run in a work tree\"));\n \n@@ -547,7 +547,7 @@ static void setup_original_cwd(void)\n \t * Get our worktree; we only protect the current working directory\n \t * if it's in the worktree.\n \t */\n-\tworktree = get_git_work_tree();\n+\tworktree = repo_get_work_tree(the_repository);\n \tif (!worktree)\n \t\tgoto no_prevention_needed;\n \n@@ -1062,9 +1062,9 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,\n \t\tset_git_work_tree(\".\");\n \n \t/* set_git_work_tree() must have been called by now */\n-\tworktree = get_git_work_tree();\n+\tworktree = repo_get_work_tree(the_repository);\n \n-\t/* both get_git_work_tree() and cwd are already normalized */\n+\t/* both repo_get_work_tree() and cwd are already normalized */\n \tif (!strcmp(cwd->buf, worktree)) { /* cwd == worktree */\n \t\tset_git_dir(gitdirenv, 0);\n \t\tfree(gitfile);\n@@ -2192,7 +2192,7 @@ static int create_default_files(const char *template_path,\n \tchar *path;\n \tint reinit;\n \tint filemode;\n-\tconst char *work_tree = get_git_work_tree();\n+\tconst char *work_tree = repo_get_work_tree(the_repository);\n \n \t/*\n \t * First copy the templates -- we might have the default\ndiff --git a/trace.c b/trace.c\nindex 2d9ae1c1525..094588c2165 100644\n--- a/trace.c\n+++ b/trace.c\n@@ -307,7 +307,7 @@ void trace_repo_setup(void)\n \n \tcwd = xgetcwd();\n \n-\tif (!(git_work_tree = get_git_work_tree()))\n+\tif (!(git_work_tree = repo_get_work_tree(the_repository)))\n \t\tgit_work_tree = \"(null)\";\n \n \tif (!startup_info->prefix)\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501814","messageId":"d2f81a540a28fd7944c40d9afd8da5eaa90d4c87.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 07/21] config: document `read_early_config()` and `read_very_early_config()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:44Z","receivedAt":"2024-08-29T09:38:50Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"It's not clear what `read_early_config()` and `read_very_early_config()`\ndo differently compared to `repo_read_config()` from just looking at\ntheir names. Document both of these in the header file to clarify their\nintent.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c |  4 ----\n config.h | 11 +++++++++++\n 2 files changed, 11 insertions(+), 4 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 0b87f0f9050..a8357ea9544 100644\n--- a/config.c\n+++ b/config.c\n@@ -2234,10 +2234,6 @@ void read_early_config(config_fn_t cb, void *data)\n \tstrbuf_release(&gitdir);\n }\n \n-/*\n- * Read config but only enumerate system and global settings.\n- * Omit any repo-local, worktree-local, or command-line settings.\n- */\n void read_very_early_config(config_fn_t cb, void *data)\n {\n \tstruct config_options opts = { 0 };\ndiff --git a/config.h b/config.h\nindex d0497157c52..f5fa833cb98 100644\n--- a/config.h\n+++ b/config.h\n@@ -192,7 +192,18 @@ int git_config_from_blob_oid(config_fn_t fn, const char *name,\n void git_config_push_parameter(const char *text);\n void git_config_push_env(const char *spec);\n int git_config_from_parameters(config_fn_t fn, void *data);\n+\n+/*\n+ * Read config when the Git directory has not yet been set up. In case\n+ * `the_repository` has not yet been set up, try to discover the Git\n+ * directory to read the configuration from.\n+ */\n void read_early_config(config_fn_t cb, void *data);\n+\n+/*\n+ * Read config but only enumerate system and global settings.\n+ * Omit any repo-local, worktree-local, or command-line settings.\n+ */\n void read_very_early_config(config_fn_t cb, void *data);\n \n /**\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501815","messageId":"85e40696cc96c0956de4c9221e7ae49b1789163b.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 08/21] config: make dependency on repo in `read_early_config()` explicit","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:50Z","receivedAt":"2024-08-29T09:38:53Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `read_early_config()` function can be used to read configuration\nwhere a repository has not yet been set up. As such, it is optional\nwhether or not `the_repository` has already been initialized. If it was\ninitialized we use its commondir and gitdir. If not, the function will\ntry to detect the Git directories by itself and, if found, also parse\ntheir config files.\n\nThis means that we implicitly rely on `the_repository`. Make this\ndependency explicit by passing a `struct repository`. This allows us to\nagain drop the `USE_THE_REPOSITORY_VARIABLE` define in \"config.c\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n alias.c                |  6 ++++--\n config.c               | 10 ++++------\n config.h               |  2 +-\n help.c                 |  2 +-\n pager.c                |  7 +++++--\n t/helper/test-config.c |  3 ++-\n trace2/tr2_cfg.c       |  4 +++-\n 7 files changed, 20 insertions(+), 14 deletions(-)\n\ndiff --git a/alias.c b/alias.c\nindex 4daafd9bdae..1a1a141a0ae 100644\n--- a/alias.c\n+++ b/alias.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"alias.h\"\n #include \"config.h\"\n@@ -37,7 +39,7 @@ char *alias_lookup(const char *alias)\n {\n \tstruct config_alias_data data = { alias, NULL };\n \n-\tread_early_config(config_alias_cb, &data);\n+\tread_early_config(the_repository, config_alias_cb, &data);\n \n \treturn data.v;\n }\n@@ -46,7 +48,7 @@ void list_aliases(struct string_list *list)\n {\n \tstruct config_alias_data data = { NULL, NULL, list };\n \n-\tread_early_config(config_alias_cb, &data);\n+\tread_early_config(the_repository, config_alias_cb, &data);\n }\n \n void quote_cmdline(struct strbuf *buf, const char **argv)\ndiff --git a/config.c b/config.c\nindex a8357ea9544..043e1c8a078 100644\n--- a/config.c\n+++ b/config.c\n@@ -6,8 +6,6 @@\n  *\n  */\n \n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"advice.h\"\n@@ -2204,7 +2202,7 @@ static void configset_iter(struct config_set *set, config_fn_t fn, void *data)\n \t}\n }\n \n-void read_early_config(config_fn_t cb, void *data)\n+void read_early_config(struct repository *repo, config_fn_t cb, void *data)\n {\n \tstruct config_options opts = {0};\n \tstruct strbuf commondir = STRBUF_INIT;\n@@ -2212,9 +2210,9 @@ void read_early_config(config_fn_t cb, void *data)\n \n \topts.respect_includes = 1;\n \n-\tif (have_git_dir()) {\n-\t\topts.commondir = repo_get_common_dir(the_repository);\n-\t\topts.git_dir = repo_get_git_dir(the_repository);\n+\tif (repo && repo->gitdir) {\n+\t\topts.commondir = repo_get_common_dir(repo);\n+\t\topts.git_dir = repo_get_git_dir(repo);\n \t/*\n \t * When setup_git_directory() was not yet asked to discover the\n \t * GIT_DIR, we ask discover_git_directory() to figure out whether there\ndiff --git a/config.h b/config.h\nindex f5fa833cb98..5c730c4f899 100644\n--- a/config.h\n+++ b/config.h\n@@ -198,7 +198,7 @@ int git_config_from_parameters(config_fn_t fn, void *data);\n  * `the_repository` has not yet been set up, try to discover the Git\n  * directory to read the configuration from.\n  */\n-void read_early_config(config_fn_t cb, void *data);\n+void read_early_config(struct repository *repo, config_fn_t cb, void *data);\n \n /*\n  * Read config but only enumerate system and global settings.\ndiff --git a/help.c b/help.c\nindex c03863f2265..413c93edaea 100644\n--- a/help.c\n+++ b/help.c\n@@ -618,7 +618,7 @@ const char *help_unknown_cmd(const char *cmd)\n \tmemset(&other_cmds, 0, sizeof(other_cmds));\n \tmemset(&aliases, 0, sizeof(aliases));\n \n-\tread_early_config(git_unknown_cmd_config, NULL);\n+\tread_early_config(the_repository, git_unknown_cmd_config, NULL);\n \n \t/*\n \t * Disable autocorrection prompt in a non-interactive session\ndiff --git a/pager.c b/pager.c\nindex 9c24ce62633..40b664f893c 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"config.h\"\n #include \"editor.h\"\n@@ -92,7 +94,8 @@ const char *git_pager(int stdout_is_tty)\n \tpager = getenv(\"GIT_PAGER\");\n \tif (!pager) {\n \t\tif (!pager_program)\n-\t\t\tread_early_config(core_pager_config, NULL);\n+\t\t\tread_early_config(the_repository,\n+\t\t\t\t\t  core_pager_config, NULL);\n \t\tpager = pager_program;\n \t}\n \tif (!pager)\n@@ -298,7 +301,7 @@ int check_pager_config(const char *cmd)\n \tdata.want = -1;\n \tdata.value = NULL;\n \n-\tread_early_config(pager_command_config, &data);\n+\tread_early_config(the_repository, pager_command_config, &data);\n \n \tif (data.value)\n \t\tpager_program = data.value;\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex e193079ed54..33247f0e92e 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -96,7 +96,8 @@ int cmd__config(int argc, const char **argv)\n \tstruct config_set cs;\n \n \tif (argc == 3 && !strcmp(argv[1], \"read_early_config\")) {\n-\t\tread_early_config(early_config_cb, (void *)argv[2]);\n+\t\tread_early_config(the_repository, early_config_cb,\n+\t\t\t\t  (void *)argv[2]);\n \t\treturn 0;\n \t}\n \ndiff --git a/trace2/tr2_cfg.c b/trace2/tr2_cfg.c\nindex d96d908bb9d..22a99a0682a 100644\n--- a/trace2/tr2_cfg.c\n+++ b/trace2/tr2_cfg.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"config.h\"\n #include \"strbuf.h\"\n@@ -124,7 +126,7 @@ void tr2_cfg_list_config_fl(const char *file, int line)\n \tstruct tr2_cfg_data data = { file, line };\n \n \tif (tr2_cfg_load_patterns() > 0)\n-\t\tread_early_config(tr2_cfg_cb, &data);\n+\t\tread_early_config(the_repository, tr2_cfg_cb, &data);\n }\n \n void tr2_list_env_vars_fl(const char *file, int line)\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501816","messageId":"8321454adc8f4a1ebf68cd5adc93a19ef03c8f27.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 09/21] environment: move `odb_mkstemp()` into object layer","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:53Z","receivedAt":"2024-08-29T09:38:56Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `odb_mkstemp()` function is quite clearly tied to the object store,\nbut regardless of that it is located in \"environment.c\". Move it over,\nwhich also helps to get rid of dependencies on `the_repository` in the\nenvironment subsystem.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n bundle-uri.c      |  1 +\n environment.c     | 34 ----------------------------------\n environment.h     | 15 ---------------\n object-file.c     | 33 +++++++++++++++++++++++++++++++++\n object-store-ll.h | 15 +++++++++++++++\n 5 files changed, 49 insertions(+), 49 deletions(-)\n\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 1e0ee156ba3..c5f9948d6bf 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -13,6 +13,7 @@\n #include \"config.h\"\n #include \"fetch-pack.h\"\n #include \"remote.h\"\n+#include \"object-store-ll.h\"\n \n static struct {\n \tenum bundle_list_heuristic heuristic;\ndiff --git a/environment.c b/environment.c\nindex 4d0637b3822..f337efd1dd5 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -23,7 +23,6 @@\n #include \"commit.h\"\n #include \"strvec.h\"\n #include \"object-file.h\"\n-#include \"object-store-ll.h\"\n #include \"path.h\"\n #include \"replace-object.h\"\n #include \"tmp-objdir.h\"\n@@ -268,39 +267,6 @@ void set_git_work_tree(const char *new_work_tree)\n \trepo_set_worktree(the_repository, new_work_tree);\n }\n \n-int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n-{\n-\tint fd;\n-\t/*\n-\t * we let the umask do its job, don't try to be more\n-\t * restrictive except to remove write permission.\n-\t */\n-\tint mode = 0444;\n-\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n-\tfd = git_mkstemp_mode(temp_filename->buf, mode);\n-\tif (0 <= fd)\n-\t\treturn fd;\n-\n-\t/* slow path */\n-\t/* some mkstemp implementations erase temp_filename on failure */\n-\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n-\tsafe_create_leading_directories(temp_filename->buf);\n-\treturn xmkstemp_mode(temp_filename->buf, mode);\n-}\n-\n-int odb_pack_keep(const char *name)\n-{\n-\tint fd;\n-\n-\tfd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n-\tif (0 <= fd)\n-\t\treturn fd;\n-\n-\t/* slow path */\n-\tsafe_create_leading_directories_const(name);\n-\treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n-}\n-\n static void set_git_dir_1(const char *path)\n {\n \txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\ndiff --git a/environment.h b/environment.h\nindex 52e1803aba6..682d4f2e3b5 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -200,21 +200,6 @@ extern int grafts_keep_true_parents;\n \n extern int repository_format_precious_objects;\n \n-/*\n- * Create a temporary file rooted in the object database directory, or\n- * die on failure. The filename is taken from \"pattern\", which should have the\n- * usual \"XXXXXX\" trailer, and the resulting filename is written into the\n- * \"template\" buffer. Returns the open descriptor.\n- */\n-int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);\n-\n-/*\n- * Create a pack .keep file named \"name\" (which should generally be the output\n- * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on\n- * error.\n- */\n-int odb_pack_keep(const char *name);\n-\n const char *get_log_output_encoding(void);\n const char *get_commit_output_encoding(void);\n \ndiff --git a/object-file.c b/object-file.c\nindex fa4121b98ad..968da27cd41 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -419,6 +419,39 @@ enum scld_error safe_create_leading_directories_const(const char *path)\n \treturn result;\n }\n \n+int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n+{\n+\tint fd;\n+\t/*\n+\t * we let the umask do its job, don't try to be more\n+\t * restrictive except to remove write permission.\n+\t */\n+\tint mode = 0444;\n+\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n+\tfd = git_mkstemp_mode(temp_filename->buf, mode);\n+\tif (0 <= fd)\n+\t\treturn fd;\n+\n+\t/* slow path */\n+\t/* some mkstemp implementations erase temp_filename on failure */\n+\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n+\tsafe_create_leading_directories(temp_filename->buf);\n+\treturn xmkstemp_mode(temp_filename->buf, mode);\n+}\n+\n+int odb_pack_keep(const char *name)\n+{\n+\tint fd;\n+\n+\tfd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n+\tif (0 <= fd)\n+\t\treturn fd;\n+\n+\t/* slow path */\n+\tsafe_create_leading_directories_const(name);\n+\treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n+}\n+\n static void fill_loose_path(struct strbuf *buf, const struct object_id *oid)\n {\n \tint i;\ndiff --git a/object-store-ll.h b/object-store-ll.h\nindex c5f2bb2fc2f..53b8e693b1b 100644\n--- a/object-store-ll.h\n+++ b/object-store-ll.h\n@@ -231,6 +231,21 @@ struct raw_object_store {\n struct raw_object_store *raw_object_store_new(void);\n void raw_object_store_clear(struct raw_object_store *o);\n \n+/*\n+ * Create a temporary file rooted in the object database directory, or\n+ * die on failure. The filename is taken from \"pattern\", which should have the\n+ * usual \"XXXXXX\" trailer, and the resulting filename is written into the\n+ * \"template\" buffer. Returns the open descriptor.\n+ */\n+int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);\n+\n+/*\n+ * Create a pack .keep file named \"name\" (which should generally be the output\n+ * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on\n+ * error.\n+ */\n+int odb_pack_keep(const char *name);\n+\n /*\n  * Put in `buf` the name of the file in the local object database that\n  * would be used to store a loose object with the specified oid.\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501817","messageId":"0b3916b2d0d33215a86fcbb79302aa6f145e89fc.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 10/21] environment: make `get_git_namespace()` self-contained","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:56Z","receivedAt":"2024-08-29T09:38:59Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The logic to set up and retrieve `git_namespace` is distributed across\ndifferent functions which communicate with each other via a global\nenvironment variable. This is rather pointless though, as the value is\nalways derived from an environment variable, and this environment\nvariable does not change after we have parsed global options.\n\nConvert the function to be fully self-contained such that it lazily\npopulates once called.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n environment.c | 57 ++++++++++++++++++++++++++-------------------------\n 1 file changed, 29 insertions(+), 28 deletions(-)\n\ndiff --git a/environment.c b/environment.c\nindex f337efd1dd5..49844418419 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -122,8 +122,6 @@ int core_preload_index = 1;\n /* This is set by setup_git_dir_gently() and/or git_default_config() */\n char *git_work_tree_cfg;\n \n-static char *git_namespace;\n-\n /*\n  * Repository-local GIT_* environment variables; see environment.h for details.\n  */\n@@ -146,27 +144,6 @@ const char * const local_repo_env[] = {\n \tNULL\n };\n \n-static char *expand_namespace(const char *raw_namespace)\n-{\n-\tstruct strbuf buf = STRBUF_INIT;\n-\tstruct strbuf **components, **c;\n-\n-\tif (!raw_namespace || !*raw_namespace)\n-\t\treturn xstrdup(\"\");\n-\n-\tstrbuf_addstr(&buf, raw_namespace);\n-\tcomponents = strbuf_split(&buf, '/');\n-\tstrbuf_reset(&buf);\n-\tfor (c = components; *c; c++)\n-\t\tif (strcmp((*c)->buf, \"/\") != 0)\n-\t\t\tstrbuf_addf(&buf, \"refs/namespaces/%s\", (*c)->buf);\n-\tstrbuf_list_free(components);\n-\tif (check_refname_format(buf.buf, 0))\n-\t\tdie(_(\"bad git namespace path \\\"%s\\\"\"), raw_namespace);\n-\tstrbuf_addch(&buf, '/');\n-\treturn strbuf_detach(&buf, NULL);\n-}\n-\n const char *getenv_safe(struct strvec *argv, const char *name)\n {\n \tconst char *value = getenv(name);\n@@ -205,8 +182,6 @@ void setup_git_env(const char *git_dir)\n \t\t\t\t\t\t\t  : \"refs/replace/\");\n \tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\n \n-\tfree(git_namespace);\n-\tgit_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));\n \tshallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);\n \tif (shallow_file)\n \t\tset_alternate_shallow_file(the_repository, shallow_file, 0);\n@@ -229,9 +204,35 @@ int have_git_dir(void)\n \n const char *get_git_namespace(void)\n {\n-\tif (!git_namespace)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn git_namespace;\n+\tstatic const char *namespace;\n+\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct strbuf **components, **c;\n+\tconst char *raw_namespace;\n+\n+\tif (namespace)\n+\t\treturn namespace;\n+\n+\traw_namespace = getenv(GIT_NAMESPACE_ENVIRONMENT);\n+\tif (!raw_namespace || !*raw_namespace) {\n+\t\tnamespace = \"\";\n+\t\treturn namespace;\n+\t}\n+\n+\tstrbuf_addstr(&buf, raw_namespace);\n+\tcomponents = strbuf_split(&buf, '/');\n+\tstrbuf_reset(&buf);\n+\tfor (c = components; *c; c++)\n+\t\tif (strcmp((*c)->buf, \"/\") != 0)\n+\t\t\tstrbuf_addf(&buf, \"refs/namespaces/%s\", (*c)->buf);\n+\tstrbuf_list_free(components);\n+\tif (check_refname_format(buf.buf, 0))\n+\t\tdie(_(\"bad git namespace path \\\"%s\\\"\"), raw_namespace);\n+\tstrbuf_addch(&buf, '/');\n+\n+\tnamespace = strbuf_detach(&buf, NULL);\n+\n+\treturn namespace;\n }\n \n const char *strip_namespace(const char *namespaced_ref)\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501818","messageId":"c20f6c04dfaee67ffdb8fbcad31672fd6348bb8b.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 11/21] environment: move `set_git_dir()` and related into setup layer","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:38:59Z","receivedAt":"2024-08-29T09:39:02Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The functions `set_git_dir()` and friends are used to set up\nrepositories. As such, they are quite clearly part of the setup\nsubsystem, but still live in \"environment.c\". Move them over, which also\nhelps to get rid of dependencies on `the_repository` in the environment\nsubsystem.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n environment.c | 105 --------------------------------------------\n environment.h |   2 -\n setup.c       | 118 +++++++++++++++++++++++++++++++++++++++++++++++---\n setup.h       |   3 ++\n 4 files changed, 115 insertions(+), 113 deletions(-)\n\ndiff --git a/environment.c b/environment.c\nindex 49844418419..64ae13ef240 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -22,14 +22,9 @@\n #include \"fmt-merge-msg.h\"\n #include \"commit.h\"\n #include \"strvec.h\"\n-#include \"object-file.h\"\n #include \"path.h\"\n-#include \"replace-object.h\"\n-#include \"tmp-objdir.h\"\n #include \"chdir-notify.h\"\n #include \"setup.h\"\n-#include \"shallow.h\"\n-#include \"trace.h\"\n #include \"write-or-die.h\"\n \n int trust_executable_bit = 1;\n@@ -155,41 +150,6 @@ const char *getenv_safe(struct strvec *argv, const char *name)\n \treturn argv->v[argv->nr - 1];\n }\n \n-void setup_git_env(const char *git_dir)\n-{\n-\tchar *git_replace_ref_base;\n-\tconst char *shallow_file;\n-\tconst char *replace_ref_base;\n-\tstruct set_gitdir_args args = { NULL };\n-\tstruct strvec to_free = STRVEC_INIT;\n-\n-\targs.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);\n-\targs.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);\n-\targs.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);\n-\targs.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);\n-\targs.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);\n-\tif (getenv(GIT_QUARANTINE_ENVIRONMENT)) {\n-\t\targs.disable_ref_updates = 1;\n-\t}\n-\n-\trepo_set_gitdir(the_repository, git_dir, &args);\n-\tstrvec_clear(&to_free);\n-\n-\tif (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))\n-\t\tdisable_replace_refs();\n-\treplace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);\n-\tgit_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base\n-\t\t\t\t\t\t\t  : \"refs/replace/\");\n-\tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\n-\n-\tshallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);\n-\tif (shallow_file)\n-\t\tset_alternate_shallow_file(the_repository, shallow_file, 0);\n-\n-\tif (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))\n-\t\tfetch_if_missing = 0;\n-}\n-\n int is_bare_repository(void)\n {\n \t/* if core.bare is not 'false', let's see if there is a work tree */\n@@ -243,71 +203,6 @@ const char *strip_namespace(const char *namespaced_ref)\n \treturn NULL;\n }\n \n-static int git_work_tree_initialized;\n-\n-/*\n- * Note.  This works only before you used a work tree.  This was added\n- * primarily to support git-clone to work in a new repository it just\n- * created, and is not meant to flip between different work trees.\n- */\n-void set_git_work_tree(const char *new_work_tree)\n-{\n-\tif (git_work_tree_initialized) {\n-\t\tstruct strbuf realpath = STRBUF_INIT;\n-\n-\t\tstrbuf_realpath(&realpath, new_work_tree, 1);\n-\t\tnew_work_tree = realpath.buf;\n-\t\tif (strcmp(new_work_tree, the_repository->worktree))\n-\t\t\tdie(\"internal error: work tree has already been set\\n\"\n-\t\t\t    \"Current worktree: %s\\nNew worktree: %s\",\n-\t\t\t    the_repository->worktree, new_work_tree);\n-\t\tstrbuf_release(&realpath);\n-\t\treturn;\n-\t}\n-\tgit_work_tree_initialized = 1;\n-\trepo_set_worktree(the_repository, new_work_tree);\n-}\n-\n-static void set_git_dir_1(const char *path)\n-{\n-\txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\n-\tsetup_git_env(path);\n-}\n-\n-static void update_relative_gitdir(const char *name UNUSED,\n-\t\t\t\t   const char *old_cwd,\n-\t\t\t\t   const char *new_cwd,\n-\t\t\t\t   void *data UNUSED)\n-{\n-\tchar *path = reparent_relative_path(old_cwd, new_cwd,\n-\t\t\t\t\t    repo_get_git_dir(the_repository));\n-\tstruct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();\n-\n-\ttrace_printf_key(&trace_setup_key,\n-\t\t\t \"setup: move $GIT_DIR to '%s'\",\n-\t\t\t path);\n-\tset_git_dir_1(path);\n-\tif (tmp_objdir)\n-\t\ttmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);\n-\tfree(path);\n-}\n-\n-void set_git_dir(const char *path, int make_realpath)\n-{\n-\tstruct strbuf realpath = STRBUF_INIT;\n-\n-\tif (make_realpath) {\n-\t\tstrbuf_realpath(&realpath, path, 1);\n-\t\tpath = realpath.buf;\n-\t}\n-\n-\tset_git_dir_1(path);\n-\tif (!is_absolute_path(path))\n-\t\tchdir_notify_register(NULL, update_relative_gitdir, NULL);\n-\n-\tstrbuf_release(&realpath);\n-}\n-\n const char *get_log_output_encoding(void)\n {\n \treturn git_log_output_encoding ? git_log_output_encoding\ndiff --git a/environment.h b/environment.h\nindex 682d4f2e3b5..b8460396790 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -105,10 +105,8 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\n-void set_git_work_tree(const char *tree);\n \n #define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n \ndiff --git a/setup.c b/setup.c\nindex 1bfec288ab6..a4a9fbb3a2a 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2,24 +2,30 @@\n \n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n+#include \"chdir-notify.h\"\n+#include \"config.h\"\n #include \"copy.h\"\n+#include \"dir.h\"\n #include \"environment.h\"\n #include \"exec-cmd.h\"\n+#include \"exec-cmd.h\"\n #include \"gettext.h\"\n #include \"hex.h\"\n+#include \"object-file.h\"\n #include \"object-name.h\"\n+#include \"path.h\"\n+#include \"quote.h\"\n #include \"refs.h\"\n+#include \"replace-object.h\"\n #include \"repository.h\"\n-#include \"config.h\"\n-#include \"dir.h\"\n #include \"setup.h\"\n+#include \"shallow.h\"\n #include \"string-list.h\"\n-#include \"chdir-notify.h\"\n-#include \"path.h\"\n-#include \"quote.h\"\n+#include \"strvec.h\"\n+#include \"tmp-objdir.h\"\n+#include \"trace.h\"\n #include \"trace2.h\"\n #include \"worktree.h\"\n-#include \"exec-cmd.h\"\n \n static int inside_git_dir = -1;\n static int inside_work_tree = -1;\n@@ -1613,6 +1619,106 @@ enum discovery_result discover_git_directory_reason(struct strbuf *commondir,\n \treturn result;\n }\n \n+void setup_git_env(const char *git_dir)\n+{\n+\tchar *git_replace_ref_base;\n+\tconst char *shallow_file;\n+\tconst char *replace_ref_base;\n+\tstruct set_gitdir_args args = { NULL };\n+\tstruct strvec to_free = STRVEC_INIT;\n+\n+\targs.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);\n+\targs.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);\n+\targs.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);\n+\targs.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);\n+\targs.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);\n+\tif (getenv(GIT_QUARANTINE_ENVIRONMENT)) {\n+\t\targs.disable_ref_updates = 1;\n+\t}\n+\n+\trepo_set_gitdir(the_repository, git_dir, &args);\n+\tstrvec_clear(&to_free);\n+\n+\tif (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))\n+\t\tdisable_replace_refs();\n+\treplace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);\n+\tgit_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base\n+\t\t\t\t\t\t\t  : \"refs/replace/\");\n+\tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\n+\n+\tshallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);\n+\tif (shallow_file)\n+\t\tset_alternate_shallow_file(the_repository, shallow_file, 0);\n+\n+\tif (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))\n+\t\tfetch_if_missing = 0;\n+}\n+\n+static void set_git_dir_1(const char *path)\n+{\n+\txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\n+\tsetup_git_env(path);\n+}\n+\n+static void update_relative_gitdir(const char *name UNUSED,\n+\t\t\t\t   const char *old_cwd,\n+\t\t\t\t   const char *new_cwd,\n+\t\t\t\t   void *data UNUSED)\n+{\n+\tchar *path = reparent_relative_path(old_cwd, new_cwd,\n+\t\t\t\t\t    repo_get_git_dir(the_repository));\n+\tstruct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();\n+\n+\ttrace_printf_key(&trace_setup_key,\n+\t\t\t \"setup: move $GIT_DIR to '%s'\",\n+\t\t\t path);\n+\tset_git_dir_1(path);\n+\tif (tmp_objdir)\n+\t\ttmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);\n+\tfree(path);\n+}\n+\n+void set_git_dir(const char *path, int make_realpath)\n+{\n+\tstruct strbuf realpath = STRBUF_INIT;\n+\n+\tif (make_realpath) {\n+\t\tstrbuf_realpath(&realpath, path, 1);\n+\t\tpath = realpath.buf;\n+\t}\n+\n+\tset_git_dir_1(path);\n+\tif (!is_absolute_path(path))\n+\t\tchdir_notify_register(NULL, update_relative_gitdir, NULL);\n+\n+\tstrbuf_release(&realpath);\n+}\n+\n+static int git_work_tree_initialized;\n+\n+/*\n+ * Note.  This works only before you used a work tree.  This was added\n+ * primarily to support git-clone to work in a new repository it just\n+ * created, and is not meant to flip between different work trees.\n+ */\n+void set_git_work_tree(const char *new_work_tree)\n+{\n+\tif (git_work_tree_initialized) {\n+\t\tstruct strbuf realpath = STRBUF_INIT;\n+\n+\t\tstrbuf_realpath(&realpath, new_work_tree, 1);\n+\t\tnew_work_tree = realpath.buf;\n+\t\tif (strcmp(new_work_tree, the_repository->worktree))\n+\t\t\tdie(\"internal error: work tree has already been set\\n\"\n+\t\t\t    \"Current worktree: %s\\nNew worktree: %s\",\n+\t\t\t    the_repository->worktree, new_work_tree);\n+\t\tstrbuf_release(&realpath);\n+\t\treturn;\n+\t}\n+\tgit_work_tree_initialized = 1;\n+\trepo_set_worktree(the_repository, new_work_tree);\n+}\n+\n const char *setup_git_directory_gently(int *nongit_ok)\n {\n \tstatic struct strbuf cwd = STRBUF_INIT;\ndiff --git a/setup.h b/setup.h\nindex fd2df7cd525..e496ab3e4de 100644\n--- a/setup.h\n+++ b/setup.h\n@@ -94,6 +94,9 @@ static inline int discover_git_directory(struct strbuf *commondir,\n \treturn 0;\n }\n \n+void set_git_dir(const char *path, int make_realpath);\n+void set_git_work_tree(const char *tree);\n+\n const char *setup_git_directory_gently(int *);\n const char *setup_git_directory(void);\n char *prefix_path(const char *prefix, int len, const char *path);\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501819","messageId":"a5a78db1697b96189db71be44973dfbef517a22f.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 12/21] environment: reorder header to split out `the_repository`-free section","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:39:02Z","receivedAt":"2024-08-29T09:39:06Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Reorder the \"environment.h\" header such that declarations which are free\nfrom `the_repository` come before those which aren't. The new structure\nis now:\n\n    - Defines for environment variable names.\n\n    - Things which do not rely on a repository.\n\n    - Things which do, including those that implicitly rely on a parsed\n      repository. This includes for example variables which get\n      populated when reading repository config.\n\nThis will allow us to guard the last category of declarations with\n`USE_THE_REPOSITORY_VARIABLE`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n environment.h | 81 +++++++++++++++++++++++++--------------------------\n 1 file changed, 40 insertions(+), 41 deletions(-)\n\ndiff --git a/environment.h b/environment.h\nindex b8460396790..f1a7c645db5 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -1,22 +1,6 @@\n #ifndef ENVIRONMENT_H\n #define ENVIRONMENT_H\n \n-struct strvec;\n-\n-/*\n- * The character that begins a commented line in user-editable file\n- * that is subject to stripspace.\n- */\n-extern const char *comment_line_str;\n-extern char *comment_line_str_to_free;\n-extern int auto_comment_line_char;\n-\n-/*\n- * Wrapper of getenv() that returns a strdup value. This value is kept\n- * in argv to be freed later.\n- */\n-const char *getenv_safe(struct strvec *argv, const char *name);\n-\n /* Double-check local_repo_env below if you add to this list. */\n #define GIT_DIR_ENVIRONMENT \"GIT_DIR\"\n #define GIT_COMMON_DIR_ENVIRONMENT \"GIT_COMMON_DIR\"\n@@ -86,6 +70,8 @@ const char *getenv_safe(struct strvec *argv, const char *name);\n  */\n #define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT \"GIT_IMPLICIT_WORK_TREE\"\n \n+#define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n+\n /*\n  * Repository-local GIT_* environment variables; these will be cleared\n  * when git spawns a sub-process that runs inside another repository.\n@@ -94,6 +80,28 @@ const char *getenv_safe(struct strvec *argv, const char *name);\n  */\n extern const char * const local_repo_env[];\n \n+struct strvec;\n+\n+/*\n+ * Wrapper of getenv() that returns a strdup value. This value is kept\n+ * in argv to be freed later.\n+ */\n+const char *getenv_safe(struct strvec *argv, const char *name);\n+\n+/*\n+ * Should we print an ellipsis after an abbreviated SHA-1 value\n+ * when doing diff-raw output or indicating a detached HEAD?\n+ */\n+int print_sha1_ellipsis(void);\n+\n+/*\n+ * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value).\n+ */\n+int use_optional_locks(void);\n+\n+const char *get_git_namespace(void);\n+const char *strip_namespace(const char *namespaced_ref);\n+\n void setup_git_env(const char *git_dir);\n \n /*\n@@ -102,13 +110,19 @@ void setup_git_env(const char *git_dir);\n  */\n int have_git_dir(void);\n \n+/*\n+ * Accessors for the core.sharedrepository config which lazy-load the value\n+ * from the config (if not already set). The \"reset\" function can be\n+ * used to unset \"set\" or cached value, meaning that the value will be loaded\n+ * fresh from the config file on the next call to get_shared_repository().\n+ */\n+void set_shared_repository(int value);\n+int get_shared_repository(void);\n+void reset_shared_repository(void);\n+\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_git_namespace(void);\n-const char *strip_namespace(const char *namespaced_ref);\n-\n-#define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n \n /* Environment bits from configuration mechanism */\n extern int trust_executable_bit;\n@@ -134,16 +148,6 @@ extern unsigned long big_file_threshold;\n extern unsigned long pack_size_limit_cfg;\n extern int max_allowed_tree_depth;\n \n-/*\n- * Accessors for the core.sharedrepository config which lazy-load the value\n- * from the config (if not already set). The \"reset\" function can be\n- * used to unset \"set\" or cached value, meaning that the value will be loaded\n- * fresh from the config file on the next call to get_shared_repository().\n- */\n-void set_shared_repository(int value);\n-int get_shared_repository(void);\n-void reset_shared_repository(void);\n-\n extern int core_preload_index;\n extern int precomposed_unicode;\n extern int protect_hfs;\n@@ -153,11 +157,6 @@ extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n-/*\n- * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value).\n- */\n-int use_optional_locks(void);\n-\n enum log_refs_config {\n \tLOG_REFS_UNSET = -1,\n \tLOG_REFS_NONE = 0,\n@@ -172,6 +171,7 @@ enum rebase_setup_type {\n \tAUTOREBASE_REMOTE,\n \tAUTOREBASE_ALWAYS\n };\n+extern enum rebase_setup_type autorebase;\n \n enum push_default_type {\n \tPUSH_DEFAULT_NOTHING = 0,\n@@ -181,15 +181,12 @@ enum push_default_type {\n \tPUSH_DEFAULT_CURRENT,\n \tPUSH_DEFAULT_UNSPECIFIED\n };\n-\n-extern enum rebase_setup_type autorebase;\n extern enum push_default_type push_default;\n \n enum object_creation_mode {\n \tOBJECT_CREATION_USES_HARDLINKS = 0,\n \tOBJECT_CREATION_USES_RENAMES = 1\n };\n-\n extern enum object_creation_mode object_creation_mode;\n \n extern char *notes_ref_name;\n@@ -209,9 +206,11 @@ extern char *askpass_program;\n extern char *excludes_file;\n \n /*\n- * Should we print an ellipsis after an abbreviated SHA-1 value\n- * when doing diff-raw output or indicating a detached HEAD?\n+ * The character that begins a commented line in user-editable file\n+ * that is subject to stripspace.\n  */\n-int print_sha1_ellipsis(void);\n+extern const char *comment_line_str;\n+extern char *comment_line_str_to_free;\n+extern int auto_comment_line_char;\n \n #endif\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501820","messageId":"27a7d00de78098a84ac3ff31aee075a5944821dc.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 13/21] environment: guard state depending on a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:39:07Z","receivedAt":"2024-08-29T09:39:10Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In \"environment.h\" we have quite a lot of functions and variables that\neither explicitly or implicitly depend on `the_repository`.\n\nThe implicit set of stateful declarations includes for example variables\nwhich get populated when parsing a repository's Git configuration. This\nset of variables is broken by design, as their state often depends on\nthe last repository config that has been parsed. So they may or may not\nrepresent the state of `the_repository`.\n\nFixing that is quite a big undertaking, and later patches in this series\nwill demonstrate a solution for a first small set of those variables. So\nfor now, let's guard these with `USE_THE_REPOSITORY_VARIABLE` so that\ncallers are aware of the implicit dependency.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c                   |  2 ++\n environment.h              | 25 ++++++++++++++++++++++++-\n name-hash.c                |  3 +++\n path.c                     |  2 ++\n preload-index.c            |  3 +++\n prompt.c                   |  2 ++\n refs/files-backend.c       |  2 ++\n sparse-index.c             |  2 ++\n statinfo.c                 |  2 ++\n t/helper/test-path-utils.c |  2 ++\n tree-diff.c                |  3 +++\n userdiff.c                 |  2 ++\n 12 files changed, 49 insertions(+), 1 deletion(-)\n\ndiff --git a/config.c b/config.c\nindex 043e1c8a078..f3066c37477 100644\n--- a/config.c\n+++ b/config.c\n@@ -6,6 +6,8 @@\n  *\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"advice.h\"\ndiff --git a/environment.h b/environment.h\nindex f1a7c645db5..934859e1c59 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -102,6 +102,28 @@ int use_optional_locks(void);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\n \n+/*\n+ * TODO: All the below state either explicitly or implicitly relies on\n+ * `the_repository`. We should eventually get rid of these and make the\n+ * dependency on a repository explicit:\n+ *\n+ *   - `setup_git_env()` ideally shouldn't exist as it modifies global state,\n+ *     namely the environment. The current process shouldn't ever access that\n+ *     state via envvars though, but should instead consult a `struct\n+ *     repository`. When spawning new processes, we would ideally also pass a\n+ *     `struct repository` and then set up the environment variables for the\n+ *     child process, only.\n+ *\n+ *   - `have_git_dir()` should not have to exist at all. Instead, we should\n+ *     decide on whether or not we have a `struct repository`.\n+ *\n+ *   - All the global config variables should become tied to a repository. Like\n+ *     this, we'd correctly honor repository-local configuration and be able to\n+ *     distinguish configuration values from different repositories.\n+ *\n+ * Please do not add new global config variables here.\n+ */\n+# ifdef USE_THE_REPOSITORY_VARIABLE\n void setup_git_env(const char *git_dir);\n \n /*\n@@ -213,4 +235,5 @@ extern const char *comment_line_str;\n extern char *comment_line_str_to_free;\n extern int auto_comment_line_char;\n \n-#endif\n+# endif /* USE_THE_REPOSITORY_VARIABLE */\n+#endif /* ENVIRONMENT_H */\ndiff --git a/name-hash.c b/name-hash.c\nindex 3a58ce03d9c..95528e3bcd2 100644\n--- a/name-hash.c\n+++ b/name-hash.c\n@@ -5,6 +5,9 @@\n  *\n  * Copyright (C) 2008 Linus Torvalds\n  */\n+\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\ndiff --git a/path.c b/path.c\nindex a3bf25b7def..93491bab141 100644\n--- a/path.c\n+++ b/path.c\n@@ -2,6 +2,8 @@\n  * Utilities for paths and pathnames\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"environment.h\"\ndiff --git a/preload-index.c b/preload-index.c\nindex 63fd35d64b1..7926eb09a69 100644\n--- a/preload-index.c\n+++ b/preload-index.c\n@@ -1,6 +1,9 @@\n /*\n  * Copyright (C) 2008 Linus Torvalds\n  */\n+\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"pathspec.h\"\n #include \"dir.h\"\ndiff --git a/prompt.c b/prompt.c\nindex 8935fe4dfb9..f21c5bf1c7e 100644\n--- a/prompt.c\n+++ b/prompt.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"parse.h\"\n #include \"environment.h\"\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 1cff65f6ae5..1bbb550f3af 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"../git-compat-util.h\"\n #include \"../copy.h\"\n #include \"../environment.h\"\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 9958656ded1..542ca5f411c 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\ndiff --git a/statinfo.c b/statinfo.c\nindex 3c6bc049c15..30a164b0e68 100644\n--- a/statinfo.c\n+++ b/statinfo.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"statinfo.h\"\ndiff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c\nindex bf0e23ed505..f57c8d706aa 100644\n--- a/t/helper/test-path-utils.c\n+++ b/t/helper/test-path-utils.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"test-tool.h\"\n #include \"abspath.h\"\n #include \"environment.h\"\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 9252481df36..5eab8af631b 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -1,6 +1,9 @@\n /*\n  * Helper functions for tree diff generation\n  */\n+\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"diff.h\"\n #include \"diffcore.h\"\ndiff --git a/userdiff.c b/userdiff.c\nindex 989629149f6..d43d8360d17 100644\n--- a/userdiff.c\n+++ b/userdiff.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"config.h\"\n #include \"userdiff.h\"\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501821","messageId":"b2c11c8e3169da9ff254efd4ba3f7efd0df73b59.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 14/21] repo-settings: split out declarations into a standalone header","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:39:10Z","receivedAt":"2024-08-29T09:39:12Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"While we have \"repo-settings.c\", we do not have a corresponding\n\"repo-settings.h\" file. Instead, this functionality is part of the\n\"repository.h\" header, making it hard to discover.\n\nSplit the declarations out of \"repository.h\" and create a standalone\nheader file with them.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n repo-settings.c |  1 +\n repo-settings.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++\n repository.h    | 51 +-------------------------------------------\n 3 files changed, 58 insertions(+), 50 deletions(-)\n create mode 100644 repo-settings.h\n\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 2b4e68731be..6165546e80a 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -1,5 +1,6 @@\n #include \"git-compat-util.h\"\n #include \"config.h\"\n+#include \"repo-settings.h\"\n #include \"repository.h\"\n #include \"midx.h\"\n \ndiff --git a/repo-settings.h b/repo-settings.h\nnew file mode 100644\nindex 00000000000..ff20a965373\n--- /dev/null\n+++ b/repo-settings.h\n@@ -0,0 +1,56 @@\n+#ifndef REPO_SETTINGS_H\n+#define REPO_SETTINGS_H\n+\n+struct fsmonitor_settings;\n+struct repository;\n+\n+enum untracked_cache_setting {\n+\tUNTRACKED_CACHE_KEEP,\n+\tUNTRACKED_CACHE_REMOVE,\n+\tUNTRACKED_CACHE_WRITE,\n+};\n+\n+enum fetch_negotiation_setting {\n+\tFETCH_NEGOTIATION_CONSECUTIVE,\n+\tFETCH_NEGOTIATION_SKIPPING,\n+\tFETCH_NEGOTIATION_NOOP,\n+};\n+\n+struct repo_settings {\n+\tint initialized;\n+\n+\tint core_commit_graph;\n+\tint commit_graph_generation_version;\n+\tint commit_graph_changed_paths_version;\n+\tint gc_write_commit_graph;\n+\tint fetch_write_commit_graph;\n+\tint command_requires_full_index;\n+\tint sparse_index;\n+\tint pack_read_reverse_index;\n+\tint pack_use_bitmap_boundary_traversal;\n+\tint pack_use_multi_pack_reuse;\n+\n+\t/*\n+\t * Does this repository have core.useReplaceRefs=true (on by\n+\t * default)? This provides a repository-scoped version of this\n+\t * config, though it could be disabled process-wide via some Git\n+\t * builtins or the --no-replace-objects option. See\n+\t * replace_refs_enabled() for more details.\n+\t */\n+\tint read_replace_refs;\n+\n+\tstruct fsmonitor_settings *fsmonitor; /* lazily loaded */\n+\n+\tint index_version;\n+\tint index_skip_hash;\n+\tenum untracked_cache_setting core_untracked_cache;\n+\n+\tint pack_use_sparse;\n+\tenum fetch_negotiation_setting fetch_negotiation_algorithm;\n+\n+\tint core_multi_pack_index;\n+};\n+\n+void prepare_repo_settings(struct repository *r);\n+\n+#endif /* REPO_SETTINGS_H */\ndiff --git a/repository.h b/repository.h\nindex c603e969ae7..24a66a496a6 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -2,9 +2,9 @@\n #define REPOSITORY_H\n \n #include \"strmap.h\"\n+#include \"repo-settings.h\"\n \n struct config_set;\n-struct fsmonitor_settings;\n struct git_hash_algo;\n struct index_state;\n struct lock_file;\n@@ -14,59 +14,12 @@ struct submodule_cache;\n struct promisor_remote_config;\n struct remote_state;\n \n-enum untracked_cache_setting {\n-\tUNTRACKED_CACHE_KEEP,\n-\tUNTRACKED_CACHE_REMOVE,\n-\tUNTRACKED_CACHE_WRITE,\n-};\n-\n-enum fetch_negotiation_setting {\n-\tFETCH_NEGOTIATION_CONSECUTIVE,\n-\tFETCH_NEGOTIATION_SKIPPING,\n-\tFETCH_NEGOTIATION_NOOP,\n-};\n-\n enum ref_storage_format {\n \tREF_STORAGE_FORMAT_UNKNOWN,\n \tREF_STORAGE_FORMAT_FILES,\n \tREF_STORAGE_FORMAT_REFTABLE,\n };\n \n-struct repo_settings {\n-\tint initialized;\n-\n-\tint core_commit_graph;\n-\tint commit_graph_generation_version;\n-\tint commit_graph_changed_paths_version;\n-\tint gc_write_commit_graph;\n-\tint fetch_write_commit_graph;\n-\tint command_requires_full_index;\n-\tint sparse_index;\n-\tint pack_read_reverse_index;\n-\tint pack_use_bitmap_boundary_traversal;\n-\tint pack_use_multi_pack_reuse;\n-\n-\t/*\n-\t * Does this repository have core.useReplaceRefs=true (on by\n-\t * default)? This provides a repository-scoped version of this\n-\t * config, though it could be disabled process-wide via some Git\n-\t * builtins or the --no-replace-objects option. See\n-\t * replace_refs_enabled() for more details.\n-\t */\n-\tint read_replace_refs;\n-\n-\tstruct fsmonitor_settings *fsmonitor; /* lazily loaded */\n-\n-\tint index_version;\n-\tint index_skip_hash;\n-\tenum untracked_cache_setting core_untracked_cache;\n-\n-\tint pack_use_sparse;\n-\tenum fetch_negotiation_setting fetch_negotiation_algorithm;\n-\n-\tint core_multi_pack_index;\n-};\n-\n struct repo_path_cache {\n \tchar *squash_msg;\n \tchar *merge_msg;\n@@ -273,8 +226,6 @@ int repo_read_index_unmerged(struct repository *);\n  */\n void repo_update_index_if_able(struct repository *, struct lock_file *);\n \n-void prepare_repo_settings(struct repository *r);\n-\n /*\n  * Return 1 if upgrade repository format to target_version succeeded,\n  * 0 if no upgrade is necessary, and -1 when upgrade is not possible.\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501822","messageId":"f1b6807fae32f58aa8243884205bd8df307856bc.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 15/21] branch: stop modifying `log_all_ref_updates` variable","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:39:12Z","receivedAt":"2024-08-29T09:39:15Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In \"branch.c\" we modify the global `log_all_ref_updates` variable to\nforce creation of a reflog entry. Modifying global state like this is\ndiscouraged, as it may have all kinds of consequences in other places of\nour codebase.\n\nStop modifying the variable and pass the `REF_FORCE_CREATE_REFLOG` flag,\nwhich has the same effect.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n branch.c | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/branch.c b/branch.c\nindex c887ea21514..08fa4094d2b 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -601,6 +601,7 @@ void create_branch(struct repository *r,\n \tint forcing = 0;\n \tstruct ref_transaction *transaction;\n \tstruct strbuf err = STRBUF_INIT;\n+\tint flags = 0;\n \tchar *msg;\n \n \tif (track == BRANCH_TRACK_OVERRIDE)\n@@ -619,7 +620,7 @@ void create_branch(struct repository *r,\n \t\tgoto cleanup;\n \n \tif (reflog)\n-\t\tlog_all_ref_updates = LOG_REFS_NORMAL;\n+\t\tflags |= REF_FORCE_CREATE_REFLOG;\n \n \tif (forcing)\n \t\tmsg = xstrfmt(\"branch: Reset to %s\", start_name);\n@@ -630,7 +631,7 @@ void create_branch(struct repository *r,\n \tif (!transaction ||\n \t\tref_transaction_update(transaction, ref.buf,\n \t\t\t\t\t&oid, forcing ? NULL : null_oid(),\n-\t\t\t\t\tNULL, NULL, 0, msg, &err) ||\n+\t\t\t\t\tNULL, NULL, flags, msg, &err) ||\n \t\tref_transaction_commit(transaction, &err))\n \t\tdie(\"%s\", err.buf);\n \tref_transaction_free(transaction);\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501823","messageId":"626e24aac7a3b38b427f91ea18da107452a5193a.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 16/21] refs: stop modifying global `log_all_ref_updates` variable","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:39:15Z","receivedAt":"2024-08-29T09:39:18Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In refs-related code we modify the global `log_all_ref_updates`\nvariable, which is done because `should_autocreate_reflog()` does not\naccept passing an `enum log_refs_config` but instead accesses the global\nvariable. Adapt its interface such that the value is provided by the\ncaller, which allows us to compute the proper value locally without\nhaving to modify global state.\n\nThis change requires us to move the enum to \"repo-settings.h\", or\notherwise we get compilation errors due to include cycles. We're about\nto fully move this setting into the repo-settings subsystem anyway, so\nthis is fine.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/checkout.c      |  2 +-\n environment.h           |  8 ++------\n refs.c                  |  3 ++-\n refs.h                  |  4 +++-\n refs/files-backend.c    | 22 +++++++++++-----------\n refs/reftable-backend.c | 12 +++++++-----\n repo-settings.h         |  7 +++++++\n 7 files changed, 33 insertions(+), 25 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 4cfe6fab505..a0214486471 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -954,7 +954,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,\n \n \t\t\trefname = mkpathdup(\"refs/heads/%s\", opts->new_orphan_branch);\n \t\t\tif (opts->new_branch_log &&\n-\t\t\t    !should_autocreate_reflog(refname)) {\n+\t\t\t    !should_autocreate_reflog(log_all_ref_updates, refname)) {\n \t\t\t\tint ret;\n \t\t\t\tstruct strbuf err = STRBUF_INIT;\n \ndiff --git a/environment.h b/environment.h\nindex 934859e1c59..0b4e5afc36d 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -1,6 +1,8 @@\n #ifndef ENVIRONMENT_H\n #define ENVIRONMENT_H\n \n+#include \"repo-settings.h\"\n+\n /* Double-check local_repo_env below if you add to this list. */\n #define GIT_DIR_ENVIRONMENT \"GIT_DIR\"\n #define GIT_COMMON_DIR_ENVIRONMENT \"GIT_COMMON_DIR\"\n@@ -179,12 +181,6 @@ extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n-enum log_refs_config {\n-\tLOG_REFS_UNSET = -1,\n-\tLOG_REFS_NONE = 0,\n-\tLOG_REFS_NORMAL,\n-\tLOG_REFS_ALWAYS\n-};\n extern enum log_refs_config log_all_ref_updates;\n \n enum rebase_setup_type {\ndiff --git a/refs.c b/refs.c\nindex ceb72d4bd74..822e0063ef6 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -958,7 +958,8 @@ static char *normalize_reflog_message(const char *msg)\n \treturn strbuf_detach(&sb, NULL);\n }\n \n-int should_autocreate_reflog(const char *refname)\n+int should_autocreate_reflog(enum log_refs_config log_all_ref_updates,\n+\t\t\t     const char *refname)\n {\n \tswitch (log_all_ref_updates) {\n \tcase LOG_REFS_ALWAYS:\ndiff --git a/refs.h b/refs.h\nindex f8b919a1388..f2c4ccde611 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -3,6 +3,7 @@\n \n #include \"commit.h\"\n #include \"repository.h\"\n+#include \"repo-settings.h\"\n \n struct fsck_options;\n struct object_id;\n@@ -111,7 +112,8 @@ int refs_verify_refname_available(struct ref_store *refs,\n \n int refs_ref_exists(struct ref_store *refs, const char *refname);\n \n-int should_autocreate_reflog(const char *refname);\n+int should_autocreate_reflog(enum log_refs_config log_all_ref_updates,\n+\t\t\t     const char *refname);\n \n int is_branch(const char *refname);\n \ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 1bbb550f3af..c143cde8aa4 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1443,6 +1443,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs,\n static int commit_ref_update(struct files_ref_store *refs,\n \t\t\t     struct ref_lock *lock,\n \t\t\t     const struct object_id *oid, const char *logmsg,\n+\t\t\t     int flags,\n \t\t\t     struct strbuf *err);\n \n /*\n@@ -1586,7 +1587,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,\n \toidcpy(&lock->old_oid, &orig_oid);\n \n \tif (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) ||\n-\t    commit_ref_update(refs, lock, &orig_oid, logmsg, &err)) {\n+\t    commit_ref_update(refs, lock, &orig_oid, logmsg, 0, &err)) {\n \t\terror(\"unable to write current sha1 into %s: %s\", newrefname, err.buf);\n \t\tstrbuf_release(&err);\n \t\tgoto rollback;\n@@ -1603,14 +1604,11 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,\n \t\tgoto rollbacklog;\n \t}\n \n-\tflag = log_all_ref_updates;\n-\tlog_all_ref_updates = LOG_REFS_NONE;\n \tif (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) ||\n-\t    commit_ref_update(refs, lock, &orig_oid, NULL, &err)) {\n+\t    commit_ref_update(refs, lock, &orig_oid, NULL, REF_SKIP_CREATE_REFLOG, &err)) {\n \t\terror(\"unable to write current sha1 into %s: %s\", oldrefname, err.buf);\n \t\tstrbuf_release(&err);\n \t}\n-\tlog_all_ref_updates = flag;\n \n  rollbacklog:\n \tif (logmoved && rename(sb_newref.buf, sb_oldref.buf))\n@@ -1705,13 +1703,17 @@ static int log_ref_setup(struct files_ref_store *refs,\n \t\t\t const char *refname, int force_create,\n \t\t\t int *logfd, struct strbuf *err)\n {\n+\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n \tstruct strbuf logfile_sb = STRBUF_INIT;\n \tchar *logfile;\n \n+\tif (log_refs_cfg == LOG_REFS_UNSET)\n+\t\tlog_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n+\n \tfiles_reflog_path(refs, &logfile_sb, refname);\n \tlogfile = strbuf_detach(&logfile_sb, NULL);\n \n-\tif (force_create || should_autocreate_reflog(refname)) {\n+\tif (force_create || should_autocreate_reflog(log_refs_cfg, refname)) {\n \t\tif (raceproof_create_file(logfile, open_or_create_logfile, logfd)) {\n \t\t\tif (errno == ENOENT)\n \t\t\t\tstrbuf_addf(err, \"unable to create directory for '%s': \"\n@@ -1800,9 +1802,6 @@ static int files_log_ref_write(struct files_ref_store *refs,\n \tif (flags & REF_SKIP_CREATE_REFLOG)\n \t\treturn 0;\n \n-\tif (log_all_ref_updates == LOG_REFS_UNSET)\n-\t\tlog_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n-\n \tresult = log_ref_setup(refs, refname,\n \t\t\t       flags & REF_FORCE_CREATE_REFLOG,\n \t\t\t       &logfd, err);\n@@ -1891,6 +1890,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs,\n static int commit_ref_update(struct files_ref_store *refs,\n \t\t\t     struct ref_lock *lock,\n \t\t\t     const struct object_id *oid, const char *logmsg,\n+\t\t\t     int flags,\n \t\t\t     struct strbuf *err)\n {\n \tfiles_assert_main_repository(refs, \"commit_ref_update\");\n@@ -1898,7 +1898,7 @@ static int commit_ref_update(struct files_ref_store *refs,\n \tclear_loose_ref_cache(refs);\n \tif (files_log_ref_write(refs, lock->ref_name,\n \t\t\t\t&lock->old_oid, oid,\n-\t\t\t\tlogmsg, 0, err)) {\n+\t\t\t\tlogmsg, flags, err)) {\n \t\tchar *old_msg = strbuf_detach(err, NULL);\n \t\tstrbuf_addf(err, \"cannot update the ref '%s': %s\",\n \t\t\t    lock->ref_name, old_msg);\n@@ -1931,7 +1931,7 @@ static int commit_ref_update(struct files_ref_store *refs,\n \t\t\tstruct strbuf log_err = STRBUF_INIT;\n \t\t\tif (files_log_ref_write(refs, \"HEAD\",\n \t\t\t\t\t\t&lock->old_oid, oid,\n-\t\t\t\t\t\tlogmsg, 0, &log_err)) {\n+\t\t\t\t\t\tlogmsg, flags, &log_err)) {\n \t\t\t\terror(\"%s\", log_err.buf);\n \t\t\t\tstrbuf_release(&log_err);\n \t\t\t}\ndiff --git a/refs/reftable-backend.c b/refs/reftable-backend.c\nindex 1c4b19e737f..c78186423a1 100644\n--- a/refs/reftable-backend.c\n+++ b/refs/reftable-backend.c\n@@ -19,6 +19,7 @@\n #include \"../reftable/reftable-record.h\"\n #include \"../reftable/reftable-error.h\"\n #include \"../reftable/reftable-iterator.h\"\n+#include \"../repo-settings.h\"\n #include \"../setup.h\"\n #include \"../strmap.h\"\n #include \"parse.h\"\n@@ -158,20 +159,21 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store,\n \n static int should_write_log(struct ref_store *refs, const char *refname)\n {\n-\tif (log_all_ref_updates == LOG_REFS_UNSET)\n-\t\tlog_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n+\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n+\tif (log_refs_cfg == LOG_REFS_UNSET)\n+\t\tlog_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n \n-\tswitch (log_all_ref_updates) {\n+\tswitch (log_refs_cfg) {\n \tcase LOG_REFS_NONE:\n \t\treturn refs_reflog_exists(refs, refname);\n \tcase LOG_REFS_ALWAYS:\n \t\treturn 1;\n \tcase LOG_REFS_NORMAL:\n-\t\tif (should_autocreate_reflog(refname))\n+\t\tif (should_autocreate_reflog(log_refs_cfg, refname))\n \t\t\treturn 1;\n \t\treturn refs_reflog_exists(refs, refname);\n \tdefault:\n-\t\tBUG(\"unhandled core.logAllRefUpdates value %d\", log_all_ref_updates);\n+\t\tBUG(\"unhandled core.logAllRefUpdates value %d\", log_refs_cfg);\n \t}\n }\n \ndiff --git a/repo-settings.h b/repo-settings.h\nindex ff20a965373..736968490a3 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -16,6 +16,13 @@ enum fetch_negotiation_setting {\n \tFETCH_NEGOTIATION_NOOP,\n };\n \n+enum log_refs_config {\n+\tLOG_REFS_UNSET = -1,\n+\tLOG_REFS_NONE = 0,\n+\tLOG_REFS_NORMAL,\n+\tLOG_REFS_ALWAYS\n+};\n+\n struct repo_settings {\n \tint initialized;\n \n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501824","messageId":"d22209121ceaa192dc80260838c77343c2d6f124.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 17/21] repo-settings: track defaults close to `struct repo_settings`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:39:18Z","receivedAt":"2024-08-29T09:39:22Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The default values for `struct repo_settings` are set up in\n`prepare_repo_settings()`. This is somewhat different from how we\ntypically do this, namely by providing an `INIT` macro that sets up the\ndefault values for us.\n\nRefactor the code to do the same.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n repo-settings.c | 9 ++++-----\n repo-settings.h | 5 +++++\n 2 files changed, 9 insertions(+), 5 deletions(-)\n\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 6165546e80a..3a76ba276c9 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -20,6 +20,7 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest,\n \n void prepare_repo_settings(struct repository *r)\n {\n+\tconst struct repo_settings defaults = REPO_SETTINGS_INIT;\n \tint experimental;\n \tint value;\n \tconst char *strval;\n@@ -29,13 +30,11 @@ void prepare_repo_settings(struct repository *r)\n \tif (!r->gitdir)\n \t\tBUG(\"Cannot add settings for uninitialized repository\");\n \n-\tif (r->settings.initialized++)\n+\tif (r->settings.initialized)\n \t\treturn;\n \n-\t/* Defaults */\n-\tr->settings.index_version = -1;\n-\tr->settings.core_untracked_cache = UNTRACKED_CACHE_KEEP;\n-\tr->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE;\n+\tmemcpy(&r->settings, &defaults, sizeof(defaults));\n+\tr->settings.initialized++;\n \n \t/* Booleans config or default, cascades to other settings */\n \trepo_cfg_bool(r, \"feature.manyfiles\", &manyfiles, 0);\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 736968490a3..d03b6e57f0c 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -57,6 +57,11 @@ struct repo_settings {\n \n \tint core_multi_pack_index;\n };\n+#define REPO_SETTINGS_INIT { \\\n+\t.index_version = -1, \\\n+\t.core_untracked_cache = UNTRACKED_CACHE_KEEP, \\\n+\t.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \\\n+}\n \n void prepare_repo_settings(struct repository *r);\n \n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501825","messageId":"b6a9eb981eed22298edaf37df01f30d2aeac8685.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 18/21] environment: stop storing \"core.logAllRefUpdates\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:39:22Z","receivedAt":"2024-08-29T09:39:25Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The value of \"core.logAllRefUpdates\" is being stored in the global\nvariable `log_all_ref_updates`. This design is somewhat aged nowadays,\nwhere it is entirely possible to access multiple repositories in the\nsame process which all have different values for this setting. So using\na single global variable to track it is plain wrong.\n\nRemove the global variable. Instead, we now provide a new function part\nof the repo-settings subsystem that parses the value for a specific\nrepository. While that may require us to read the value multiple times,\nwe work around this by reading it once when the ref backends are set up\nand caching the value there.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/checkout.c      |  2 ++\n config.c                | 10 ----------\n environment.c           |  1 -\n environment.h           |  2 --\n refs/files-backend.c    |  4 +++-\n refs/reftable-backend.c | 12 +++++++-----\n repo-settings.c         | 16 ++++++++++++++++\n repo-settings.h         |  3 +++\n setup.c                 |  2 +-\n 9 files changed, 32 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex a0214486471..84a2dbeee79 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -950,6 +950,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts,\n \tconst char *old_desc, *reflog_msg;\n \tif (opts->new_branch) {\n \t\tif (opts->new_orphan_branch) {\n+\t\t\tenum log_refs_config log_all_ref_updates =\n+\t\t\t\trepo_settings_get_log_all_ref_updates(the_repository);\n \t\t\tchar *refname;\n \n \t\t\trefname = mkpathdup(\"refs/heads/%s\", opts->new_orphan_branch);\ndiff --git a/config.c b/config.c\nindex f3066c37477..47101c3e977 100644\n--- a/config.c\n+++ b/config.c\n@@ -1452,16 +1452,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.logallrefupdates\")) {\n-\t\tif (value && !strcasecmp(value, \"always\"))\n-\t\t\tlog_all_ref_updates = LOG_REFS_ALWAYS;\n-\t\telse if (git_config_bool(var, value))\n-\t\t\tlog_all_ref_updates = LOG_REFS_NORMAL;\n-\t\telse\n-\t\t\tlog_all_ref_updates = LOG_REFS_NONE;\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.warnambiguousrefs\")) {\n \t\twarn_ambiguous_refs = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 64ae13ef240..992d87e0d60 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -77,7 +77,6 @@ int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\n int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\n unsigned long pack_size_limit_cfg;\n-enum log_refs_config log_all_ref_updates = LOG_REFS_UNSET;\n int max_allowed_tree_depth =\n #ifdef _MSC_VER\n \t/*\ndiff --git a/environment.h b/environment.h\nindex 0b4e5afc36d..315fd319951 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -181,8 +181,6 @@ extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n-extern enum log_refs_config log_all_ref_updates;\n-\n enum rebase_setup_type {\n \tAUTOREBASE_NEVER = 0,\n \tAUTOREBASE_LOCAL,\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex c143cde8aa4..6ad495744b0 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -74,6 +74,7 @@ struct files_ref_store {\n \tunsigned int store_flags;\n \n \tchar *gitcommondir;\n+\tenum log_refs_config log_all_ref_updates;\n \n \tstruct ref_cache *loose;\n \n@@ -106,6 +107,7 @@ static struct ref_store *files_ref_store_init(struct repository *repo,\n \trefs->gitcommondir = strbuf_detach(&sb, NULL);\n \trefs->packed_ref_store =\n \t\tpacked_ref_store_init(repo, refs->gitcommondir, flags);\n+\trefs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);\n \n \tchdir_notify_reparent(\"files-backend $GIT_DIR\", &refs->base.gitdir);\n \tchdir_notify_reparent(\"files-backend $GIT_COMMONDIR\",\n@@ -1703,7 +1705,7 @@ static int log_ref_setup(struct files_ref_store *refs,\n \t\t\t const char *refname, int force_create,\n \t\t\t int *logfd, struct strbuf *err)\n {\n-\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n+\tenum log_refs_config log_refs_cfg = refs->log_all_ref_updates;\n \tstruct strbuf logfile_sb = STRBUF_INIT;\n \tchar *logfile;\n \ndiff --git a/refs/reftable-backend.c b/refs/reftable-backend.c\nindex c78186423a1..043e19439f6 100644\n--- a/refs/reftable-backend.c\n+++ b/refs/reftable-backend.c\n@@ -52,6 +52,7 @@ struct reftable_ref_store {\n \tstruct reftable_write_options write_options;\n \n \tunsigned int store_flags;\n+\tenum log_refs_config log_all_ref_updates;\n \tint err;\n };\n \n@@ -157,21 +158,21 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store,\n \t}\n }\n \n-static int should_write_log(struct ref_store *refs, const char *refname)\n+static int should_write_log(struct reftable_ref_store *refs, const char *refname)\n {\n-\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n+\tenum log_refs_config log_refs_cfg = refs->log_all_ref_updates;\n \tif (log_refs_cfg == LOG_REFS_UNSET)\n \t\tlog_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n \n \tswitch (log_refs_cfg) {\n \tcase LOG_REFS_NONE:\n-\t\treturn refs_reflog_exists(refs, refname);\n+\t\treturn refs_reflog_exists(&refs->base, refname);\n \tcase LOG_REFS_ALWAYS:\n \t\treturn 1;\n \tcase LOG_REFS_NORMAL:\n \t\tif (should_autocreate_reflog(log_refs_cfg, refname))\n \t\t\treturn 1;\n-\t\treturn refs_reflog_exists(refs, refname);\n+\t\treturn refs_reflog_exists(&refs->base, refname);\n \tdefault:\n \t\tBUG(\"unhandled core.logAllRefUpdates value %d\", log_refs_cfg);\n \t}\n@@ -278,6 +279,7 @@ static struct ref_store *reftable_be_init(struct repository *repo,\n \tbase_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable);\n \tstrmap_init(&refs->worktree_stacks);\n \trefs->store_flags = store_flags;\n+\trefs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);\n \n \trefs->write_options.hash_id = repo->hash_algo->format_id;\n \trefs->write_options.default_permissions = calc_shared_perm(0666 & ~mask);\n@@ -1220,7 +1222,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data\n \t\t} else if (!(u->flags & REF_SKIP_CREATE_REFLOG) &&\n \t\t\t   (u->flags & REF_HAVE_NEW) &&\n \t\t\t   (u->flags & REF_FORCE_CREATE_REFLOG ||\n-\t\t\t    should_write_log(&arg->refs->base, u->refname))) {\n+\t\t\t    should_write_log(arg->refs, u->refname))) {\n \t\t\tstruct reftable_log_record *log;\n \t\t\tint create_reflog = 1;\n \ndiff --git a/repo-settings.c b/repo-settings.c\nindex 3a76ba276c9..1322fd2f972 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -124,3 +124,19 @@ void prepare_repo_settings(struct repository *r)\n \t */\n \tr->settings.command_requires_full_index = 1;\n }\n+\n+enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)\n+{\n+\tconst char *value;\n+\n+\tif (!repo_config_get_string_tmp(repo, \"core.logallrefupdates\", &value)) {\n+\t\tif (value && !strcasecmp(value, \"always\"))\n+\t\t\treturn LOG_REFS_ALWAYS;\n+\t\telse if (git_config_bool(\"core.logallrefupdates\", value))\n+\t\t\treturn LOG_REFS_NORMAL;\n+\t\telse\n+\t\t\treturn LOG_REFS_NONE;\n+\t}\n+\n+\treturn LOG_REFS_UNSET;\n+}\ndiff --git a/repo-settings.h b/repo-settings.h\nindex d03b6e57f0c..76adb96a669 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -65,4 +65,7 @@ struct repo_settings {\n \n void prepare_repo_settings(struct repository *r);\n \n+/* Read the value for \"core.logAllRefUpdates\". */\n+enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo);\n+\n #endif /* REPO_SETTINGS_H */\ndiff --git a/setup.c b/setup.c\nindex a4a9fbb3a2a..c37dc4f7c48 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2354,7 +2354,7 @@ static int create_default_files(const char *template_path,\n \telse {\n \t\tgit_config_set(\"core.bare\", \"false\");\n \t\t/* allow template config file to override the default */\n-\t\tif (log_all_ref_updates == LOG_REFS_UNSET)\n+\t\tif (repo_settings_get_log_all_ref_updates(the_repository) == LOG_REFS_UNSET)\n \t\t\tgit_config_set(\"core.logallrefupdates\", \"true\");\n \t\tif (needs_work_tree_config(original_git_dir, work_tree))\n \t\t\tgit_config_set(\"core.worktree\", work_tree);\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501826","messageId":"ef312f67f76f2563f3fc662cd551930c4b2ea1bd.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 19/21] environment: stop storing \"core.preferSymlinkRefs\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:39:25Z","receivedAt":"2024-08-29T09:39:28Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Same as the preceding commit, storing the \"core.preferSymlinkRefs\" value\nglobally is misdesigned as this setting may be set per repository.\n\nThere is only a single user of this value anyway, namely the \"files\"\nbackend. So let's just remove the global variable and read the value of\nthis setting when initializing the backend.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c             | 5 -----\n environment.c        | 1 -\n environment.h        | 1 -\n refs/files-backend.c | 5 ++++-\n 4 files changed, 4 insertions(+), 8 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 47101c3e977..a59890180a3 100644\n--- a/config.c\n+++ b/config.c\n@@ -1447,11 +1447,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.prefersymlinkrefs\")) {\n-\t\tprefer_symlink_refs = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.warnambiguousrefs\")) {\n \t\twarn_ambiguous_refs = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 992d87e0d60..6805c7b01df 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -34,7 +34,6 @@ int has_symlinks = 1;\n int minimum_abbrev = 4, default_abbrev = -1;\n int ignore_case;\n int assume_unchanged;\n-int prefer_symlink_refs;\n int is_bare_repository_cfg = -1; /* unspecified */\n int warn_ambiguous_refs = 1;\n int warn_on_object_refname_ambiguity = 1;\ndiff --git a/environment.h b/environment.h\nindex 315fd319951..0cab644e2d3 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -156,7 +156,6 @@ extern int has_symlinks;\n extern int minimum_abbrev, default_abbrev;\n extern int ignore_case;\n extern int assume_unchanged;\n-extern int prefer_symlink_refs;\n extern int warn_ambiguous_refs;\n extern int warn_on_object_refname_ambiguity;\n extern char *apply_default_whitespace;\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 6ad495744b0..b8a0b27d24e 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1,6 +1,7 @@\n #define USE_THE_REPOSITORY_VARIABLE\n \n #include \"../git-compat-util.h\"\n+#include \"../config.h\"\n #include \"../copy.h\"\n #include \"../environment.h\"\n #include \"../gettext.h\"\n@@ -75,6 +76,7 @@ struct files_ref_store {\n \n \tchar *gitcommondir;\n \tenum log_refs_config log_all_ref_updates;\n+\tint prefer_symlink_refs;\n \n \tstruct ref_cache *loose;\n \n@@ -108,6 +110,7 @@ static struct ref_store *files_ref_store_init(struct repository *repo,\n \trefs->packed_ref_store =\n \t\tpacked_ref_store_init(repo, refs->gitcommondir, flags);\n \trefs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);\n+\trepo_config_get_bool(repo, \"core.prefersymlinkrefs\", &refs->prefer_symlink_refs);\n \n \tchdir_notify_reparent(\"files-backend $GIT_DIR\", &refs->base.gitdir);\n \tchdir_notify_reparent(\"files-backend $GIT_COMMONDIR\",\n@@ -2941,7 +2944,7 @@ static int files_transaction_finish(struct ref_store *ref_store,\n \t\t * We try creating a symlink, if that succeeds we continue to the\n \t\t * next update. If not, we try and create a regular symref.\n \t\t */\n-\t\tif (update->new_target && prefer_symlink_refs)\n+\t\tif (update->new_target && refs->prefer_symlink_refs)\n \t\t\tif (!create_ref_symlink(lock, update->new_target))\n \t\t\t\tcontinue;\n \n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501827","messageId":"f2a28d38e5d1f314cbe8e890a9fec530152f7dc1.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 20/21] environment: stop storing \"core.warnAmbiguousRefs\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:39:28Z","receivedAt":"2024-08-29T09:39:30Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Same as the preceding commits, storing the \"core.warnAmbiguousRefs\"\nvalue globally is misdesigned as this setting may be set per repository.\n\nMove the logic into the repo-settings subsystem. The usual pattern here\nis that users are expected to call `prepare_repo_settings()` before they\naccess the settings themselves. This seems somewhat fragile though, as\nit is easy to miss and leads to somewhat ugly code patterns at the call\nsites.\n\nInstead, introduce a new function that encapsulates this logic for us.\nThis also allows us to change how exactly the lazy initialization works\nin the future, e.g. by only partially initializing values as requested\nby the caller.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/rev-parse.c | 3 ++-\n config.c            | 5 -----\n environment.c       | 1 -\n environment.h       | 1 -\n object-name.c       | 4 ++--\n ref-filter.c        | 2 +-\n refs.c              | 4 ++--\n repo-settings.c     | 9 +++++++++\n repo-settings.h     | 4 ++++\n 9 files changed, 20 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex 65b0b5e2c0a..bd06f6cc4c4 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -898,7 +898,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t}\n \t\t\tif (opt_with_value(arg, \"--abbrev-ref\", &arg)) {\n \t\t\t\tabbrev_ref = 1;\n-\t\t\t\tabbrev_ref_strict = warn_ambiguous_refs;\n+\t\t\t\tabbrev_ref_strict =\n+\t\t\t\t\trepo_settings_get_warn_ambiguous_refs(the_repository);\n \t\t\t\tif (arg) {\n \t\t\t\t\tif (!strcmp(arg, \"strict\"))\n \t\t\t\t\t\tabbrev_ref_strict = 1;\ndiff --git a/config.c b/config.c\nindex a59890180a3..53c68f3da61 100644\n--- a/config.c\n+++ b/config.c\n@@ -1447,11 +1447,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.warnambiguousrefs\")) {\n-\t\twarn_ambiguous_refs = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.abbrev\")) {\n \t\tif (!value)\n \t\t\treturn config_error_nonbool(var);\ndiff --git a/environment.c b/environment.c\nindex 6805c7b01df..9dd000cda36 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -35,7 +35,6 @@ int minimum_abbrev = 4, default_abbrev = -1;\n int ignore_case;\n int assume_unchanged;\n int is_bare_repository_cfg = -1; /* unspecified */\n-int warn_ambiguous_refs = 1;\n int warn_on_object_refname_ambiguity = 1;\n int repository_format_precious_objects;\n char *git_commit_encoding;\ndiff --git a/environment.h b/environment.h\nindex 0cab644e2d3..aa38133da9c 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -156,7 +156,6 @@ extern int has_symlinks;\n extern int minimum_abbrev, default_abbrev;\n extern int ignore_case;\n extern int assume_unchanged;\n-extern int warn_ambiguous_refs;\n extern int warn_on_object_refname_ambiguity;\n extern char *apply_default_whitespace;\n extern char *apply_default_ignorewhitespace;\ndiff --git a/object-name.c b/object-name.c\nindex 09c1bd93a31..baeed4deeed 100644\n--- a/object-name.c\n+++ b/object-name.c\n@@ -959,7 +959,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,\n \tint fatal = !(flags & GET_OID_QUIETLY);\n \n \tif (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {\n-\t\tif (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {\n+\t\tif (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) {\n \t\t\trefs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);\n \t\t\tif (refs_found > 0) {\n \t\t\t\twarning(warn_msg, len, str);\n@@ -1020,7 +1020,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,\n \tif (!refs_found)\n \t\treturn -1;\n \n-\tif (warn_ambiguous_refs && !(flags & GET_OID_QUIETLY) &&\n+\tif (repo_settings_get_warn_ambiguous_refs(r) && !(flags & GET_OID_QUIETLY) &&\n \t    (refs_found > 1 ||\n \t     !get_short_oid(r, str, len, &tmp_oid, GET_OID_QUIETLY)))\n \t\twarning(warn_msg, len, str);\ndiff --git a/ref-filter.c b/ref-filter.c\nindex b6c6c101276..6a1f4c1ee98 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -2160,7 +2160,7 @@ static const char *show_ref(struct refname_atom *atom, const char *refname)\n \tif (atom->option == R_SHORT)\n \t\treturn refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),\n \t\t\t\t\t\t    refname,\n-\t\t\t\t\t\t    warn_ambiguous_refs);\n+\t\t\t\t\t\t    repo_settings_get_warn_ambiguous_refs(the_repository));\n \telse if (atom->option == R_LSTRIP)\n \t\treturn lstrip_ref_components(refname, atom->lstrip);\n \telse if (atom->option == R_RSTRIP)\ndiff --git a/refs.c b/refs.c\nindex 822e0063ef6..bc348632121 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -730,7 +730,7 @@ int expand_ref(struct repository *repo, const char *str, int len,\n \t\tif (r) {\n \t\t\tif (!refs_found++)\n \t\t\t\t*ref = xstrdup(r);\n-\t\t\tif (!warn_ambiguous_refs)\n+\t\t\tif (!repo_settings_get_warn_ambiguous_refs(repo))\n \t\t\t\tbreak;\n \t\t} else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, \"HEAD\")) {\n \t\t\twarning(_(\"ignoring dangling symref %s\"), fullref.buf);\n@@ -775,7 +775,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len,\n \t\t\tif (oid)\n \t\t\t\toidcpy(oid, &hash);\n \t\t}\n-\t\tif (!warn_ambiguous_refs)\n+\t\tif (!repo_settings_get_warn_ambiguous_refs(r))\n \t\t\tbreak;\n \t}\n \tstrbuf_release(&path);\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 1322fd2f972..4699b4b3650 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -140,3 +140,12 @@ enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *re\n \n \treturn LOG_REFS_UNSET;\n }\n+\n+int repo_settings_get_warn_ambiguous_refs(struct repository *repo)\n+{\n+\tprepare_repo_settings(repo);\n+\tif (repo->settings.warn_ambiguous_refs < 0)\n+\t\trepo_cfg_bool(repo, \"core.warnambiguousrefs\",\n+\t\t\t      &repo->settings.warn_ambiguous_refs, 1);\n+\treturn repo->settings.warn_ambiguous_refs;\n+}\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 76adb96a669..51d6156a117 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -56,16 +56,20 @@ struct repo_settings {\n \tenum fetch_negotiation_setting fetch_negotiation_algorithm;\n \n \tint core_multi_pack_index;\n+\tint warn_ambiguous_refs; /* lazily loaded via accessor */\n };\n #define REPO_SETTINGS_INIT { \\\n \t.index_version = -1, \\\n \t.core_untracked_cache = UNTRACKED_CACHE_KEEP, \\\n \t.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \\\n+\t.warn_ambiguous_refs = -1, \\\n }\n \n void prepare_repo_settings(struct repository *r);\n \n /* Read the value for \"core.logAllRefUpdates\". */\n enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo);\n+/* Read the value for \"core.warnAmbiguousRefs\". */\n+int repo_settings_get_warn_ambiguous_refs(struct repository *repo);\n \n #endif /* REPO_SETTINGS_H */\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501828","messageId":"ecafe1585f8ec9a6862a45b86244305f3e1294ab.1724923648.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH 21/21] environment: stop storing \"core.notesRef\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-29T09:39:31Z","receivedAt":"2024-08-29T09:39:33Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Stop storing the \"core.notesRef\" config value globally. Instead,\nretrieve the value in `default_notes_ref()`. The code is never called in\na hot loop anyway, so doing this on every invocation should be perfectly\nfine.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/notes.c | 22 ++++++++++++++--------\n config.c        |  8 --------\n environment.c   |  1 -\n environment.h   |  2 --\n notes.c         | 21 +++++++++++++--------\n notes.h         |  3 ++-\n 6 files changed, 29 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 04f9dfb7fbd..5d594a07240 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -897,6 +897,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t\t\t      1, PARSE_OPT_NONEG),\n \t\tOPT_END()\n \t};\n+\tchar *notes_ref;\n \n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_notes_merge_usage, 0);\n@@ -924,7 +925,8 @@ static int merge(int argc, const char **argv, const char *prefix)\n \tif (do_commit)\n \t\treturn merge_commit(&o);\n \n-\to.local_ref = default_notes_ref();\n+\tnotes_ref = default_notes_ref(the_repository);\n+\to.local_ref = notes_ref;\n \tstrbuf_addstr(&remote_ref, argv[0]);\n \texpand_loose_notes_ref(&remote_ref);\n \to.remote_ref = remote_ref.buf;\n@@ -953,7 +955,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t}\n \n \tstrbuf_addf(&msg, \"notes: Merged notes from %s into %s\",\n-\t\t    remote_ref.buf, default_notes_ref());\n+\t\t    remote_ref.buf, notes_ref);\n \tstrbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip \"notes: \" */\n \n \tresult = notes_merge(&o, t, &result_oid);\n@@ -961,7 +963,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \tif (result >= 0) /* Merge resulted (trivially) in result_oid */\n \t\t/* Update default notes ref with new commit */\n \t\trefs_update_ref(get_main_ref_store(the_repository), msg.buf,\n-\t\t\t\tdefault_notes_ref(), &result_oid, NULL, 0,\n+\t\t\t\tnotes_ref, &result_oid, NULL, 0,\n \t\t\t\tUPDATE_REFS_DIE_ON_ERR);\n \telse { /* Merge has unresolved conflicts */\n \t\tstruct worktree **worktrees;\n@@ -973,14 +975,14 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t\t/* Store ref-to-be-updated into .git/NOTES_MERGE_REF */\n \t\tworktrees = get_worktrees();\n \t\twt = find_shared_symref(worktrees, \"NOTES_MERGE_REF\",\n-\t\t\t\t\tdefault_notes_ref());\n+\t\t\t\t\tnotes_ref);\n \t\tif (wt)\n \t\t\tdie(_(\"a notes merge into %s is already in-progress at %s\"),\n-\t\t\t    default_notes_ref(), wt->path);\n+\t\t\t    notes_ref, wt->path);\n \t\tfree_worktrees(worktrees);\n-\t\tif (refs_update_symref(get_main_ref_store(the_repository), \"NOTES_MERGE_REF\", default_notes_ref(), NULL))\n+\t\tif (refs_update_symref(get_main_ref_store(the_repository), \"NOTES_MERGE_REF\", notes_ref, NULL))\n \t\t\tdie(_(\"failed to store link to current notes ref (%s)\"),\n-\t\t\t    default_notes_ref());\n+\t\t\t    notes_ref);\n \t\tfprintf(stderr, _(\"Automatic notes merge failed. Fix conflicts in %s \"\n \t\t\t\t  \"and commit the result with 'git notes merge --commit', \"\n \t\t\t\t  \"or abort the merge with 'git notes merge --abort'.\\n\"),\n@@ -988,6 +990,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t}\n \n \tfree_notes(t);\n+\tfree(notes_ref);\n \tstrbuf_release(&remote_ref);\n \tstrbuf_release(&msg);\n \treturn result < 0; /* return non-zero on conflicts */\n@@ -1084,6 +1087,7 @@ static int prune(int argc, const char **argv, const char *prefix)\n static int get_ref(int argc, const char **argv, const char *prefix)\n {\n \tstruct option options[] = { OPT_END() };\n+\tchar *notes_ref;\n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_notes_get_ref_usage, 0);\n \n@@ -1092,7 +1096,9 @@ static int get_ref(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(git_notes_get_ref_usage, options);\n \t}\n \n-\tputs(default_notes_ref());\n+\tnotes_ref = default_notes_ref(the_repository);\n+\tputs(notes_ref);\n+\tfree(notes_ref);\n \treturn 0;\n }\n \ndiff --git a/config.c b/config.c\nindex 53c68f3da61..1266eab0860 100644\n--- a/config.c\n+++ b/config.c\n@@ -1555,14 +1555,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn git_config_string(&check_roundtrip_encoding, var, value);\n \t}\n \n-\tif (!strcmp(var, \"core.notesref\")) {\n-\t\tif (!value)\n-\t\t\treturn config_error_nonbool(var);\n-\t\tfree(notes_ref_name);\n-\t\tnotes_ref_name = xstrdup(value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.editor\")) {\n \t\tFREE_AND_NULL(editor_program);\n \t\treturn git_config_string(&editor_program, var, value);\ndiff --git a/environment.c b/environment.c\nindex 9dd000cda36..a2ce9980818 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -67,7 +67,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n-char *notes_ref_name;\n int grafts_keep_true_parents;\n int core_apply_sparse_checkout;\n int core_sparse_checkout_cone;\ndiff --git a/environment.h b/environment.h\nindex aa38133da9c..923e12661e1 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -203,8 +203,6 @@ enum object_creation_mode {\n };\n extern enum object_creation_mode object_creation_mode;\n \n-extern char *notes_ref_name;\n-\n extern int grafts_keep_true_parents;\n \n extern int repository_format_precious_objects;\ndiff --git a/notes.c b/notes.c\nindex da42df282d5..f4f18daf07e 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -992,15 +992,16 @@ static int notes_display_config(const char *k, const char *v,\n \treturn 0;\n }\n \n-const char *default_notes_ref(void)\n+char *default_notes_ref(struct repository *repo)\n {\n-\tconst char *notes_ref = NULL;\n+\tchar *notes_ref = NULL;\n+\n \tif (!notes_ref)\n-\t\tnotes_ref = getenv(GIT_NOTES_REF_ENVIRONMENT);\n+\t\tnotes_ref = xstrdup_or_null(getenv(GIT_NOTES_REF_ENVIRONMENT));\n \tif (!notes_ref)\n-\t\tnotes_ref = notes_ref_name; /* value of core.notesRef config */\n+\t\trepo_config_get_string(repo, \"core.notesref\", &notes_ref);\n \tif (!notes_ref)\n-\t\tnotes_ref = GIT_NOTES_DEFAULT_REF;\n+\t\tnotes_ref = xstrdup(GIT_NOTES_DEFAULT_REF);\n \treturn notes_ref;\n }\n \n@@ -1010,13 +1011,14 @@ void init_notes(struct notes_tree *t, const char *notes_ref,\n \tstruct object_id oid, object_oid;\n \tunsigned short mode;\n \tstruct leaf_node root_tree;\n+\tchar *to_free = NULL;\n \n \tif (!t)\n \t\tt = &default_notes_tree;\n \tassert(!t->initialized);\n \n \tif (!notes_ref)\n-\t\tnotes_ref = default_notes_ref();\n+\t\tnotes_ref = to_free = default_notes_ref(the_repository);\n \tupdate_ref_namespace(NAMESPACE_NOTES, xstrdup(notes_ref));\n \n \tif (!combine_notes)\n@@ -1033,7 +1035,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,\n \n \tif (flags & NOTES_INIT_EMPTY ||\n \t    repo_get_oid_treeish(the_repository, notes_ref, &object_oid))\n-\t\treturn;\n+\t\tgoto out;\n \tif (flags & NOTES_INIT_WRITABLE && refs_read_ref(get_main_ref_store(the_repository), notes_ref, &object_oid))\n \t\tdie(\"Cannot use notes ref %s\", notes_ref);\n \tif (get_tree_entry(the_repository, &object_oid, \"\", &oid, &mode))\n@@ -1043,6 +1045,9 @@ void init_notes(struct notes_tree *t, const char *notes_ref,\n \toidclr(&root_tree.key_oid, the_repository->hash_algo);\n \toidcpy(&root_tree.val_oid, &oid);\n \tload_subtree(t, &root_tree, t->root, 0);\n+\n+out:\n+\tfree(to_free);\n }\n \n struct notes_tree **load_notes_trees(struct string_list *refs, int flags)\n@@ -1105,7 +1110,7 @@ void load_display_notes(struct display_notes_opt *opt)\n \n \tif (!opt || opt->use_default_notes > 0 ||\n \t    (opt->use_default_notes == -1 && !opt->extra_notes_refs.nr)) {\n-\t\tstring_list_append(&display_notes_refs, default_notes_ref());\n+\t\tstring_list_append_nodup(&display_notes_refs, default_notes_ref(the_repository));\n \t\tdisplay_ref_env = getenv(GIT_NOTES_DISPLAY_REF_ENVIRONMENT);\n \t\tif (display_ref_env) {\n \t\t\tstring_list_add_refs_from_colon_sep(&display_notes_refs,\ndiff --git a/notes.h b/notes.h\nindex 235216944bc..6dc6d7b2654 100644\n--- a/notes.h\n+++ b/notes.h\n@@ -4,6 +4,7 @@\n #include \"string-list.h\"\n \n struct object_id;\n+struct repository;\n struct strbuf;\n \n /*\n@@ -70,7 +71,7 @@ extern struct notes_tree {\n  * 3. The value of the core.notesRef config variable, if set\n  * 4. GIT_NOTES_DEFAULT_REF (i.e. \"refs/notes/commits\")\n  */\n-const char *default_notes_ref(void);\n+char *default_notes_ref(struct repository *repo);\n \n /*\n  * Flags controlling behaviour of notes tree initialization\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501864","messageId":"xmqqle0fuml4.fsf@gitster.g","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"Re: [PATCH 00/21] environment: guard reliance on `the_repository`","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-29T19:59:35Z","receivedAt":"2024-08-29T19:59:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"There may be more, but I know at least of these at the moment from\nhttps://github.com/git/git/actions/runs/10619536685/job/29437358521\n\nPerhaps this can become [0.5/21] of the series, before globals are\nhidden behind the macro.\n\n--- >8 ---\nSubject: [PATCH] win32: mark the sources that depend on the_repository\n\nThese source files still need access to the global variables like\n\"ignore_case\" and \"protect_ntfs\".\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n compat/mingw.c            | 2 ++\n compat/win32/path-utils.c | 2 ++\n 2 files changed, 4 insertions(+)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 29d3f09768..5c2080c04c 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"../git-compat-util.h\"\n #include \"win32.h\"\n #include <aclapi.h>\ndiff --git a/compat/win32/path-utils.c b/compat/win32/path-utils.c\nindex b658ca3f81..966ef779b9 100644\n--- a/compat/win32/path-utils.c\n+++ b/compat/win32/path-utils.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"../../git-compat-util.h\"\n #include \"../../environment.h\"\n \n-- \n2.46.0-567-gbce23f156d\n\n"},{"id":"501868","messageId":"3fvisdomxvcepnfbx2aruzyhqj2ntfjaapk7escwhylxxuq7r4@inhrmm26blg2","threadId":"62019","inReplyTo":"0fe3e3e1cccf2eae7d81ccecf431da623b39fa79.1724923648.git.ps@pks.im","subject":"Re: [PATCH 01/21] environment: make `get_git_dir()` accept a repository","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-29T20:15:36Z","receivedAt":"2024-08-29T20:16:40Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/29 11:38AM, Patrick Steinhardt wrote:\n> The `get_git_dir()` function retrieves the path to the Git directory for\n> `the_repository`. Make it accept a `struct repository` such that it can\n> work on arbitrary repositories and make it part of the repository\n> subsystem. This reduces our reliance on `the_repository` and clarifies\n> scope.\n\nSeems sensible to me. We are simply making it so `the_repository` is no\nlonger implicit to the function.\n\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n[snip]\n> --- a/builtin/commit.c\n> +++ b/builtin/commit.c\n> @@ -407,7 +407,7 @@ static const char *prepare_index(const char **argv, const char *prefix,\n>  \n>  \t\tdiscard_index(the_repository->index);\n>  \t\tread_index_from(the_repository->index, get_lock_file_path(&index_lock),\n> -\t\t\t\tget_git_dir());\n> +\t\t\t\trepo_get_git_dir(the_repository));\n\nNow that the `repo_get_git_dir()` function has been moved to\n\"repository.h\" should we also directly include this header in the c\nfile? Or is the implicit reference sufficent? From our coding guidelines\nis seems we preferred to be direct.\n\nIt looks like there are several other hunks missing direct references to\n\"repository.h\" too.\n\n[snip]\n> diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c\n> index 1593713f4cb..c54e736716a 100644\n> --- a/builtin/fsmonitor--daemon.c\n> +++ b/builtin/fsmonitor--daemon.c\n> @@ -1311,7 +1311,8 @@ static int fsmonitor_run_daemon(void)\n>  \tstrbuf_addstr(&state.path_gitdir_watch, \"/.git\");\n>  \tif (!is_directory(state.path_gitdir_watch.buf)) {\n>  \t\tstrbuf_reset(&state.path_gitdir_watch);\n> -\t\tstrbuf_addstr(&state.path_gitdir_watch, absolute_path(get_git_dir()));\n> +\t\tstrbuf_addstr(&state.path_gitdir_watch,\n> +\t\t\t      absolute_path(repo_get_git_dir(the_repository)));\n\nIn this c file, now that `repo_get_git_dir()` lives in \"repository.h\",\nis the \"environment.h\" header file needed anymore?\n\n-Justin\n"},{"id":"501891","messageId":"ZtFtpjaGFhORNEP4@tanuki","threadId":"62019","inReplyTo":"xmqqle0fuml4.fsf@gitster.g","subject":"Re: [PATCH 00/21] environment: guard reliance on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T06:58:46Z","receivedAt":"2024-08-30T06:58:51Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Aug 29, 2024 at 12:59:35PM -0700, Junio C Hamano wrote:\n> There may be more, but I know at least of these at the moment from\n> https://github.com/git/git/actions/runs/10619536685/job/29437358521\n> \n> Perhaps this can become [0.5/21] of the series, before globals are\n> hidden behind the macro.\n\nThanks, I'll add these. I really need to spend some time to finally get\nWin32 builds set up in GitLab CI.\n\nPatrick\n\n> --- >8 ---\n> Subject: [PATCH] win32: mark the sources that depend on the_repository\n> \n> These source files still need access to the global variables like\n> \"ignore_case\" and \"protect_ntfs\".\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  compat/mingw.c            | 2 ++\n>  compat/win32/path-utils.c | 2 ++\n>  2 files changed, 4 insertions(+)\n> \n> diff --git a/compat/mingw.c b/compat/mingw.c\n> index 29d3f09768..5c2080c04c 100644\n> --- a/compat/mingw.c\n> +++ b/compat/mingw.c\n> @@ -1,3 +1,5 @@\n> +#define USE_THE_REPOSITORY_VARIABLE\n> +\n>  #include \"../git-compat-util.h\"\n>  #include \"win32.h\"\n>  #include <aclapi.h>\n> diff --git a/compat/win32/path-utils.c b/compat/win32/path-utils.c\n> index b658ca3f81..966ef779b9 100644\n> --- a/compat/win32/path-utils.c\n> +++ b/compat/win32/path-utils.c\n> @@ -1,3 +1,5 @@\n> +#define USE_THE_REPOSITORY_VARIABLE\n> +\n>  #include \"../../git-compat-util.h\"\n>  #include \"../../environment.h\"\n>  \n> -- \n> 2.46.0-567-gbce23f156d\n> \n"},{"id":"501892","messageId":"ZtF36wGgltwiBmYC@tanuki","threadId":"62019","inReplyTo":"3fvisdomxvcepnfbx2aruzyhqj2ntfjaapk7escwhylxxuq7r4@inhrmm26blg2","subject":"Re: [PATCH 01/21] environment: make `get_git_dir()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T07:42:41Z","receivedAt":"2024-08-30T07:42:46Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Aug 29, 2024 at 03:15:36PM -0500, Justin Tobler wrote:\n> On 24/08/29 11:38AM, Patrick Steinhardt wrote:\n> [snip]\n> > --- a/builtin/commit.c\n> > +++ b/builtin/commit.c\n> > @@ -407,7 +407,7 @@ static const char *prepare_index(const char **argv, const char *prefix,\n> >  \n> >  \t\tdiscard_index(the_repository->index);\n> >  \t\tread_index_from(the_repository->index, get_lock_file_path(&index_lock),\n> > -\t\t\t\tget_git_dir());\n> > +\t\t\t\trepo_get_git_dir(the_repository));\n> \n> Now that the `repo_get_git_dir()` function has been moved to\n> \"repository.h\" should we also directly include this header in the c\n> file? Or is the implicit reference sufficent? From our coding guidelines\n> is seems we preferred to be direct.\n> \n> It looks like there are several other hunks missing direct references to\n> \"repository.h\" too.\n\nYeah, you're right. Let me go through all the commits and double\ncheck whether includes need to change. Oh, well... sounds like fun\n*sigh*\n\nPatrick\n"},{"id":"501895","messageId":"cover.1725008897.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH v2 00/21] environment: guard reliance on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:08:52Z","receivedAt":"2024-08-30T09:08:57Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis is the second version of my patch series which guards functions and\nvariables in the environment subsystem that rely on `the_repository`\nwith the `USE_THE_REPOSITORY_VARIABLE` define.\n\nChanges compared to v1:\n\n  - Clean up now-unnecessary and add newly-necessary includes.\n\n  - Stop reordering includes in \"setup.c\".\n\n  - Fix missing `USE_THE_REPOSITORY_VARIABLE` defines in Win32 code.\n\nThanks!\n\nPatrick\n\nPatrick Steinhardt (21):\n  environment: make `get_git_dir()` accept a repository\n  environment: make `get_git_common_dir()` accept a repository\n  environment: make `get_object_directory()` accept a repository\n  environment: make `get_index_file()` accept a repository\n  environment: make `get_graft_file()` accept a repository\n  environment: make `get_git_work_tree()` accept a repository\n  config: document `read_early_config()` and `read_very_early_config()`\n  config: make dependency on repo in `read_early_config()` explicit\n  environment: move `odb_mkstemp()` into object layer\n  environment: make `get_git_namespace()` self-contained\n  environment: move `set_git_dir()` and related into setup layer\n  environment: reorder header to split out `the_repository`-free section\n  environment: guard state depending on a repository\n  repo-settings: split out declarations into a standalone header\n  repo-settings: track defaults close to `struct repo_settings`\n  branch: stop modifying `log_all_ref_updates` variable\n  refs: stop modifying global `log_all_ref_updates` variable\n  environment: stop storing \"core.logAllRefUpdates\" globally\n  environment: stop storing \"core.preferSymlinkRefs\" globally\n  environment: stop storing \"core.warnAmbiguousRefs\" globally\n  environment: stop storing \"core.notesRef\" globally\n\n alias.c                     |   6 +-\n apply.c                     |   3 +-\n branch.c                    |   5 +-\n builtin/am.c                |  13 +-\n builtin/blame.c             |   2 +-\n builtin/checkout.c          |   5 +-\n builtin/commit-graph.c      |   5 +-\n builtin/commit.c            |  13 +-\n builtin/config.c            |   4 +-\n builtin/count-objects.c     |   3 +-\n builtin/difftool.c          |   9 +-\n builtin/fsmonitor--daemon.c |   7 +-\n builtin/gc.c                |   2 +-\n builtin/init-db.c           |   4 +-\n builtin/merge.c             |  18 +--\n builtin/multi-pack-index.c  |   4 +-\n builtin/notes.c             |  22 ++--\n builtin/pack-objects.c      |   2 +-\n builtin/prune.c             |   8 +-\n builtin/repack.c            |   7 +-\n builtin/replace.c           |   3 +-\n builtin/reset.c             |   5 +-\n builtin/rev-parse.c         |  11 +-\n builtin/stash.c             |  17 +--\n builtin/submodule--helper.c |   2 +-\n builtin/update-index.c      |   4 +-\n builtin/worktree.c          |   4 +-\n builtin/write-tree.c        |   4 +-\n bulk-checkin.c              |   4 +-\n bundle-uri.c                |   2 +-\n cache-tree.c                |   5 +-\n commit.c                    |   4 +-\n compat/mingw.c              |   2 +\n compat/win32/path-utils.c   |   2 +\n config.c                    |  42 +------\n config.h                    |  13 +-\n dir.c                       |   3 +-\n environment.c               | 237 +++++-------------------------------\n environment.h               | 142 ++++++++++-----------\n fetch-pack.c                |   2 +-\n fsmonitor.c                 |   3 +-\n help.c                      |   2 +-\n http-backend.c              |   2 +-\n name-hash.c                 |   3 +\n notes.c                     |  21 ++--\n notes.h                     |   3 +-\n object-file.c               |  37 +++++-\n object-name.c               |   5 +-\n object-store-ll.h           |  15 +++\n pack-write.c                |   3 +-\n packfile.c                  |   2 +-\n pager.c                     |   7 +-\n path.c                      |   2 +\n pathspec.c                  |   4 +-\n preload-index.c             |   3 +\n prompt.c                    |   2 +\n prune-packed.c              |   6 +-\n read-cache.c                |   6 +-\n ref-filter.c                |   3 +-\n refs.c                      |   9 +-\n refs.h                      |   4 +-\n refs/files-backend.c        |  32 +++--\n refs/reftable-backend.c     |  22 ++--\n repo-settings.c             |  35 +++++-\n repo-settings.h             |  75 ++++++++++++\n repository.c                |  40 ++++++\n repository.h                |  58 ++-------\n server-info.c               |   4 +-\n setup.c                     | 140 ++++++++++++++++++---\n setup.h                     |   5 +-\n sparse-index.c              |   2 +\n statinfo.c                  |   2 +\n submodule.c                 |   2 +-\n t/helper/test-config.c      |   3 +-\n t/helper/test-path-utils.c  |   2 +\n tmp-objdir.c                |   8 +-\n trace.c                     |  10 +-\n trace2/tr2_cfg.c            |   4 +-\n transport-helper.c          |   2 +-\n tree-diff.c                 |   3 +\n userdiff.c                  |   2 +\n worktree.c                  |  12 +-\n wt-status.c                 |   3 +-\n 83 files changed, 698 insertions(+), 560 deletions(-)\n create mode 100644 repo-settings.h\n\nRange-diff against v1:\n 1:  0fe3e3e1ccc !  1:  a1969c5b073 environment: make `get_git_dir()` accept a repository\n    @@ Commit message\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## apply.c ##\n    +@@\n    + #include \"path.h\"\n    + #include \"quote.h\"\n    + #include \"read-cache.h\"\n    ++#include \"repository.h\"\n    + #include \"rerere.h\"\n    + #include \"apply.h\"\n    + #include \"entry.h\"\n     @@ apply.c: static int read_apply_cache(struct apply_state *state)\n      {\n      \tif (state->index_file)\n    @@ builtin/am.c: static int fall_back_threeway(const struct am_state *state, const\n      \t\treturn error(_(\"Repository lacks necessary blobs to fall back on 3-way merge.\"));\n     \n      ## builtin/commit.c ##\n    +@@\n    + #include \"path.h\"\n    + #include \"preload-index.h\"\n    + #include \"read-cache.h\"\n    ++#include \"repository.h\"\n    + #include \"string-list.h\"\n    + #include \"rerere.h\"\n    + #include \"unpack-trees.h\"\n     @@ builtin/commit.c: static const char *prepare_index(const char **argv, const char *prefix,\n      \n      \t\tdiscard_index(the_repository->index);\n    @@ builtin/config.c: static void location_options_init(struct config_location_optio\n      \n     \n      ## builtin/difftool.c ##\n    +@@\n    + #include \"hex.h\"\n    + #include \"parse-options.h\"\n    + #include \"read-cache-ll.h\"\n    ++#include \"repository.h\"\n    + #include \"sparse-index.h\"\n    + #include \"strvec.h\"\n    + #include \"strbuf.h\"\n     @@ builtin/difftool.c: static void changed_files(struct hashmap *result, const char *index_path,\n      \tstruct child_process update_index = CHILD_PROCESS_INIT;\n      \tstruct child_process diff_files = CHILD_PROCESS_INIT;\n    @@ builtin/fsmonitor--daemon.c: static int fsmonitor_run_daemon(void)\n      \n     \n      ## builtin/merge.c ##\n    +@@\n    + #include \"object-name.h\"\n    + #include \"parse-options.h\"\n    + #include \"lockfile.h\"\n    ++#include \"repository.h\"\n    + #include \"run-command.h\"\n    + #include \"hook.h\"\n    + #include \"diff.h\"\n     @@ builtin/merge.c: static void prepare_to_commit(struct commit_list *remoteheads)\n      \t\tif (invoked_hook)\n      \t\t\tdiscard_index(the_repository->index);\n    @@ builtin/merge.c: static void prepare_to_commit(struct commit_list *remoteheads)\n      \t\tBUG(\"the control must not reach here under --squash\");\n     \n      ## builtin/stash.c ##\n    +@@\n    + #include \"entry.h\"\n    + #include \"preload-index.h\"\n    + #include \"read-cache.h\"\n    ++#include \"repository.h\"\n    + #include \"rerere.h\"\n    + #include \"revision.h\"\n    + #include \"setup.h\"\n     @@ builtin/stash.c: static int do_apply_stash(const char *prefix, struct stash_info *info,\n      \t\tstrvec_pushf(&cp.env, GIT_WORK_TREE_ENVIRONMENT\"=%s\",\n      \t\t\t     absolute_path(get_git_work_tree()));\n    @@ builtin/stash.c: static int do_apply_stash(const char *prefix, struct stash_info\n      \t}\n     \n      ## cache-tree.c ##\n    +@@\n    + #define USE_THE_REPOSITORY_VARIABLE\n    + \n    + #include \"git-compat-util.h\"\n    +-#include \"environment.h\"\n    + #include \"hex.h\"\n    + #include \"lockfile.h\"\n    + #include \"tree.h\"\n    +@@\n    + #include \"object-store-ll.h\"\n    + #include \"read-cache-ll.h\"\n    + #include \"replace-object.h\"\n    ++#include \"repository.h\"\n    + #include \"promisor-remote.h\"\n    + #include \"trace.h\"\n    + #include \"trace2.h\"\n     @@ cache-tree.c: int write_index_as_tree(struct object_id *oid, struct index_state *index_state,\n      \n      \thold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);\n    @@ pathspec.c: static void init_pathspec_item(struct pathspec_item *item, unsigned\n      \t\t}\n     \n      ## read-cache.c ##\n    +@@\n    + #include \"path.h\"\n    + #include \"preload-index.h\"\n    + #include \"read-cache.h\"\n    ++#include \"repository.h\"\n    + #include \"resolve-undo.h\"\n    + #include \"revision.h\"\n    + #include \"strbuf.h\"\n     @@ read-cache.c: static int should_delete_shared_index(const char *shared_index_path)\n      static int clean_shared_index_files(const char *current_hex)\n      {\n    @@ trace.c\n      #include \"git-compat-util.h\"\n      #include \"abspath.h\"\n      #include \"environment.h\"\n    ++#include \"repository.h\"\n    + #include \"quote.h\"\n    + #include \"setup.h\"\n    + #include \"trace.h\"\n     @@ trace.c: void trace_repo_setup(void)\n      \tif (!startup_info->prefix)\n      \t\tprefix = \"(null)\";\n 2:  cdd6dd308c3 !  2:  deebf2c5205 environment: make `get_git_common_dir()` accept a repository\n    @@ builtin/gc.c: static int schtasks_schedule_task(const char *exec_path, enum sche\n      \n     \n      ## builtin/rev-parse.c ##\n    +@@\n    + #include \"path.h\"\n    + #include \"diff.h\"\n    + #include \"read-cache-ll.h\"\n    ++#include \"repository.h\"\n    + #include \"revision.h\"\n    + #include \"setup.h\"\n    + #include \"split-index.h\"\n     @@ builtin/rev-parse.c: int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n      \t\t\t\tcontinue;\n      \t\t\t}\n 3:  bb01e4fab9d !  3:  43abfa7b139 environment: make `get_object_directory()` accept a repository\n    @@ Commit message\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## builtin/commit-graph.c ##\n    +@@\n    + #include \"builtin.h\"\n    + #include \"commit.h\"\n    + #include \"config.h\"\n    +-#include \"environment.h\"\n    + #include \"gettext.h\"\n    + #include \"hex.h\"\n    + #include \"parse-options.h\"\n     @@ builtin/commit-graph.c: static int graph_verify(int argc, const char **argv, const char *prefix)\n      \t\tusage_with_options(builtin_commit_graph_verify_usage, options);\n      \n    @@ builtin/commit-graph.c: static int graph_write(int argc, const char **argv, cons\n      \tif (opts.split)\n     \n      ## builtin/count-objects.c ##\n    +@@\n    + #include \"builtin.h\"\n    + #include \"config.h\"\n    + #include \"dir.h\"\n    +-#include \"environment.h\"\n    + #include \"gettext.h\"\n    + #include \"path.h\"\n    + #include \"repository.h\"\n     @@ builtin/count-objects.c: int cmd_count_objects(int argc, const char **argv, const char *prefix)\n      \t\treport_linked_checkout_garbage(the_repository);\n      \t}\n    @@ builtin/count-objects.c: int cmd_count_objects(int argc, const char **argv, cons\n      \tif (verbose) {\n     \n      ## builtin/multi-pack-index.c ##\n    +@@\n    + #include \"builtin.h\"\n    + #include \"abspath.h\"\n    + #include \"config.h\"\n    +-#include \"environment.h\"\n    + #include \"gettext.h\"\n    + #include \"parse-options.h\"\n    + #include \"midx.h\"\n    +@@\n    + #include \"trace2.h\"\n    + #include \"object-store-ll.h\"\n    + #include \"replace-object.h\"\n    ++#include \"repository.h\"\n    + \n    + #define BUILTIN_MIDX_WRITE_USAGE \\\n    + \tN_(\"git multi-pack-index [<options>] write [--preferred-pack=<pack>]\" \\\n     @@ builtin/multi-pack-index.c: static int parse_object_dir(const struct option *opt, const char *arg,\n      \tchar **value = opt->value;\n      \tfree(*value);\n    @@ object-file.c: int stream_loose_object(struct input_stream *in_stream, size_t le\n      \t/*\n     \n      ## pack-write.c ##\n    +@@\n    + #include \"pack-objects.h\"\n    + #include \"pack-revindex.h\"\n    + #include \"path.h\"\n    ++#include \"repository.h\"\n    + #include \"strbuf.h\"\n    + \n    + void reset_pack_idx_option(struct pack_idx_option *opts)\n     @@ pack-write.c: char *index_pack_lockfile(int ip_out, int *is_well_formed)\n      \t\tpackname[len-1] = 0;\n      \t\tif (skip_prefix(packname, \"keep\\t\", &name))\n    @@ prune-packed.c\n     +#define USE_THE_REPOSITORY_VARIABLE\n     +\n      #include \"git-compat-util.h\"\n    - #include \"environment.h\"\n    +-#include \"environment.h\"\n      #include \"gettext.h\"\n    + #include \"object-store-ll.h\"\n    + #include \"packfile.h\"\n    + #include \"progress.h\"\n    + #include \"prune-packed.h\"\n    ++#include \"repository.h\"\n    + \n    + static struct progress *progress;\n    + \n     @@ prune-packed.c: void prune_packed_objects(int opts)\n      \tif (opts & PRUNE_PACKED_VERBOSE)\n      \t\tprogress = start_delayed_progress(_(\"Removing duplicate objects\"), 256);\n    @@ repository.h: extern struct repository *the_repository;\n       * Define a custom repository layout. Any field can be NULL, which\n     \n      ## server-info.c ##\n    +@@\n    + \n    + #include \"git-compat-util.h\"\n    + #include \"dir.h\"\n    +-#include \"environment.h\"\n    + #include \"hex.h\"\n    + #include \"repository.h\"\n    + #include \"refs.h\"\n     @@ server-info.c: static int write_pack_info_file(struct update_info_ctx *uic)\n      \n      static int update_info_packs(int force)\n    @@ setup.c: static void create_object_directory(void)\n      \tsafe_create_dir(path.buf, 1);\n     \n      ## tmp-objdir.c ##\n    +@@\n    + #include \"strvec.h\"\n    + #include \"quote.h\"\n    + #include \"object-store-ll.h\"\n    ++#include \"repository.h\"\n    + \n    + struct tmp_objdir {\n    + \tstruct strbuf path;\n     @@ tmp-objdir.c: struct tmp_objdir *tmp_objdir_create(const char *prefix)\n      \t * can recognize any stale objdirs left behind by a crash and delete\n      \t * them.\n 4:  d857c5fab44 !  4:  d7554cb0fe0 environment: make `get_index_file()` accept a repository\n    @@ builtin/update-index.c: int cmd_update_index(int argc, const char **argv, const\n      \t\t\tdie(\"Unable to write new index file\");\n     \n      ## builtin/write-tree.c ##\n    +@@\n    + \n    + #include \"builtin.h\"\n    + #include \"config.h\"\n    +-#include \"environment.h\"\n    + #include \"gettext.h\"\n    + #include \"hex.h\"\n    + #include \"tree.h\"\n     @@ builtin/write-tree.c: int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix)\n      \tprepare_repo_settings(the_repository);\n      \tthe_repository->settings.command_requires_full_index = 0;\n    @@ repository.h: extern struct repository *the_repository;\n       * Define a custom repository layout. Any field can be NULL, which\n     \n      ## wt-status.c ##\n    +@@\n    + #include \"revision.h\"\n    + #include \"diffcore.h\"\n    + #include \"quote.h\"\n    ++#include \"repository.h\"\n    + #include \"run-command.h\"\n    + #include \"strvec.h\"\n    + #include \"remote.h\"\n     @@ wt-status.c: void wt_status_prepare(struct repository *r, struct wt_status *s)\n      \t\t\t\t\t\"HEAD\", 0, NULL, NULL);\n      \ts->reference = \"HEAD\";\n 5:  ac27d7128a4 !  5:  1cc727e4763 environment: make `get_graft_file()` accept a repository\n    @@ Commit message\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## builtin/replace.c ##\n    +@@\n    + #include \"builtin.h\"\n    + #include \"config.h\"\n    + #include \"editor.h\"\n    +-#include \"environment.h\"\n    + #include \"gettext.h\"\n    + #include \"hex.h\"\n    + #include \"refs.h\"\n     @@ builtin/replace.c: static int create_graft(int argc, const char **argv, int force, int gentle)\n      \n      static int convert_graft_file(int force)\n 6:  7fc346d3bb5 !  6:  22e9dcb28a9 environment: make `get_git_work_tree()` accept a repository\n    @@ builtin/difftool.c: int cmd_difftool(int argc, const char **argv, const char *pr\n      \n     \n      ## builtin/fsmonitor--daemon.c ##\n    +@@\n    + #include \"abspath.h\"\n    + #include \"config.h\"\n    + #include \"dir.h\"\n    +-#include \"environment.h\"\n    + #include \"gettext.h\"\n    + #include \"parse-options.h\"\n    + #include \"fsmonitor-ll.h\"\n     @@ builtin/fsmonitor--daemon.c: static int fsmonitor_run_daemon(void)\n      \n      \t/* Prepare to (recursively) watch the <worktree-root> directory. */\n    @@ builtin/init-db.c: int cmd_init_db(int argc, const char **argv, const char *pref\n      \t\tif (real_git_dir)\n     \n      ## builtin/reset.c ##\n    +@@\n    + #include \"object-name.h\"\n    + #include \"parse-options.h\"\n    + #include \"path.h\"\n    ++#include \"repository.h\"\n    + #include \"unpack-trees.h\"\n    + #include \"cache-tree.h\"\n    + #include \"setup.h\"\n     @@ builtin/reset.c: int cmd_reset(int argc, const char **argv, const char *prefix)\n      \telse\n      \t\ttrace2_cmd_mode(reset_type_names[reset_type]);\n    @@ builtin/update-index.c: int cmd_update_index(int argc, const char **argv, const\n      \t\tBUG(\"bad untracked_cache value: %d\", untracked_cache);\n     \n      ## dir.c ##\n    +@@\n    + #include \"object-store-ll.h\"\n    + #include \"path.h\"\n    + #include \"refs.h\"\n    ++#include \"repository.h\"\n    + #include \"wildmatch.h\"\n    + #include \"pathspec.h\"\n    + #include \"utf8.h\"\n     @@ dir.c: static const char *get_ident_string(void)\n      \t\treturn sb.buf;\n      \tif (uname(&uts) < 0)\n    @@ environment.h: extern char *git_work_tree_cfg;\n      #define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n     \n      ## fsmonitor.c ##\n    +@@\n    + #include \"fsmonitor.h\"\n    + #include \"fsmonitor-ipc.h\"\n    + #include \"name-hash.h\"\n    ++#include \"repository.h\"\n    + #include \"run-command.h\"\n    + #include \"strbuf.h\"\n    + #include \"trace2.h\"\n     @@ fsmonitor.c: static int query_fsmonitor_hook(struct repository *r,\n      \tstrvec_pushf(&cp.args, \"%d\", version);\n      \tstrvec_pushf(&cp.args, \"%s\", last_update);\n    @@ setup.c: static int create_default_files(const char *template_path,\n      \t * First copy the templates -- we might have the default\n     \n      ## trace.c ##\n    +@@\n    + \n    + #include \"git-compat-util.h\"\n    + #include \"abspath.h\"\n    +-#include \"environment.h\"\n    + #include \"repository.h\"\n    + #include \"quote.h\"\n    + #include \"setup.h\"\n     @@ trace.c: void trace_repo_setup(void)\n      \n      \tcwd = xgetcwd();\n 7:  d2f81a540a2 =  7:  ec4804a99bf config: document `read_early_config()` and `read_very_early_config()`\n 8:  85e40696cc9 =  8:  b8aa5dcc0b6 config: make dependency on repo in `read_early_config()` explicit\n 9:  8321454adc8 !  9:  ac2cc4e0371 environment: move `odb_mkstemp()` into object layer\n    @@ Commit message\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## bundle-uri.c ##\n    +@@\n    + #include \"bundle-uri.h\"\n    + #include \"bundle.h\"\n    + #include \"copy.h\"\n    +-#include \"environment.h\"\n    + #include \"gettext.h\"\n    + #include \"refs.h\"\n    + #include \"run-command.h\"\n     @@\n      #include \"config.h\"\n      #include \"fetch-pack.h\"\n10:  0b3916b2d0d = 10:  f0d3794dfc4 environment: make `get_git_namespace()` self-contained\n11:  c20f6c04dfa ! 11:  9e0e2528b94 environment: move `set_git_dir()` and related into setup layer\n    @@ environment.h: int have_git_dir(void);\n     \n      ## setup.c ##\n     @@\n    - \n    - #include \"git-compat-util.h\"\n    - #include \"abspath.h\"\n    -+#include \"chdir-notify.h\"\n    -+#include \"config.h\"\n    - #include \"copy.h\"\n    -+#include \"dir.h\"\n    - #include \"environment.h\"\n      #include \"exec-cmd.h\"\n    -+#include \"exec-cmd.h\"\n      #include \"gettext.h\"\n      #include \"hex.h\"\n     +#include \"object-file.h\"\n      #include \"object-name.h\"\n    -+#include \"path.h\"\n    -+#include \"quote.h\"\n      #include \"refs.h\"\n     +#include \"replace-object.h\"\n      #include \"repository.h\"\n    --#include \"config.h\"\n    --#include \"dir.h\"\n    + #include \"config.h\"\n    + #include \"dir.h\"\n      #include \"setup.h\"\n     +#include \"shallow.h\"\n      #include \"string-list.h\"\n    --#include \"chdir-notify.h\"\n    --#include \"path.h\"\n    --#include \"quote.h\"\n     +#include \"strvec.h\"\n    + #include \"chdir-notify.h\"\n    + #include \"path.h\"\n    + #include \"quote.h\"\n     +#include \"tmp-objdir.h\"\n     +#include \"trace.h\"\n      #include \"trace2.h\"\n      #include \"worktree.h\"\n    --#include \"exec-cmd.h\"\n    - \n    - static int inside_git_dir = -1;\n    - static int inside_work_tree = -1;\n    + #include \"exec-cmd.h\"\n     @@ setup.c: enum discovery_result discover_git_directory_reason(struct strbuf *commondir,\n      \treturn result;\n      }\n12:  a5a78db1697 = 12:  78f77a006a0 environment: reorder header to split out `the_repository`-free section\n13:  27a7d00de78 ! 13:  9a3f466b530 environment: guard state depending on a repository\n    @@ Commit message\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n    + ## compat/mingw.c ##\n    +@@\n    ++#define USE_THE_REPOSITORY_VARIABLE\n    ++\n    + #include \"../git-compat-util.h\"\n    + #include \"win32.h\"\n    + #include <aclapi.h>\n    +\n    + ## compat/win32/path-utils.c ##\n    +@@\n    ++#define USE_THE_REPOSITORY_VARIABLE\n    ++\n    + #include \"../../git-compat-util.h\"\n    + #include \"../../environment.h\"\n    + \n    +\n      ## config.c ##\n     @@\n       *\n14:  b2c11c8e316 = 14:  0d7365c5190 repo-settings: split out declarations into a standalone header\n17:  d22209121ce = 15:  231c52ce82f repo-settings: track defaults close to `struct repo_settings`\n15:  f1b6807fae3 = 16:  fc30365e1f1 branch: stop modifying `log_all_ref_updates` variable\n16:  626e24aac7a ! 17:  9cc8518a02d refs: stop modifying global `log_all_ref_updates` variable\n    @@ Commit message\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## builtin/checkout.c ##\n    +@@\n    + #include \"read-cache.h\"\n    + #include \"refs.h\"\n    + #include \"remote.h\"\n    ++#include \"repo-settings.h\"\n    + #include \"resolve-undo.h\"\n    + #include \"revision.h\"\n    + #include \"setup.h\"\n     @@ builtin/checkout.c: static void update_refs_for_switch(const struct checkout_opts *opts,\n      \n      \t\t\trefname = mkpathdup(\"refs/heads/%s\", opts->new_orphan_branch);\n    @@ environment.h: extern int core_apply_sparse_checkout;\n      enum rebase_setup_type {\n     \n      ## refs.c ##\n    +@@\n    + #include \"submodule.h\"\n    + #include \"worktree.h\"\n    + #include \"strvec.h\"\n    +-#include \"repository.h\"\n    ++#include \"repo-settings.h\"\n    + #include \"setup.h\"\n    + #include \"sigchain.h\"\n    + #include \"date.h\"\n     @@ refs.c: static char *normalize_reflog_message(const char *msg)\n      \treturn strbuf_detach(&sb, NULL);\n      }\n    @@ refs.h: int refs_verify_refname_available(struct ref_store *refs,\n      \n     \n      ## refs/files-backend.c ##\n    +@@\n    + #include \"../hex.h\"\n    + #include \"../fsck.h\"\n    + #include \"../refs.h\"\n    ++#include \"../repo-settings.h\"\n    + #include \"refs-internal.h\"\n    + #include \"ref-cache.h\"\n    + #include \"packed-backend.h\"\n     @@ refs/files-backend.c: static int write_ref_to_lockfile(struct files_ref_store *refs,\n      static int commit_ref_update(struct files_ref_store *refs,\n      \t\t\t     struct ref_lock *lock,\n18:  b6a9eb981ee = 18:  b5ed6928070 environment: stop storing \"core.logAllRefUpdates\" globally\n19:  ef312f67f76 = 19:  194d858877f environment: stop storing \"core.preferSymlinkRefs\" globally\n20:  f2a28d38e5d ! 20:  fc6fcebf7f7 environment: stop storing \"core.warnAmbiguousRefs\" globally\n    @@ Commit message\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## builtin/rev-parse.c ##\n    +@@\n    + #include \"path.h\"\n    + #include \"diff.h\"\n    + #include \"read-cache-ll.h\"\n    ++#include \"repo-settings.h\"\n    + #include \"repository.h\"\n    + #include \"revision.h\"\n    + #include \"setup.h\"\n     @@ builtin/rev-parse.c: int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n      \t\t\t}\n      \t\t\tif (opt_with_value(arg, \"--abbrev-ref\", &arg)) {\n    @@ environment.h: extern int has_symlinks;\n      extern char *apply_default_ignorewhitespace;\n     \n      ## object-name.c ##\n    +@@\n    + #include \"pretty.h\"\n    + #include \"object-store-ll.h\"\n    + #include \"read-cache-ll.h\"\n    ++#include \"repo-settings.h\"\n    + #include \"repository.h\"\n    + #include \"setup.h\"\n    + #include \"midx.h\"\n     @@ object-name.c: static int get_oid_basic(struct repository *r, const char *str, int len,\n      \tint fatal = !(flags & GET_OID_QUIETLY);\n      \n    @@ object-name.c: static int get_oid_basic(struct repository *r, const char *str, i\n      \t\twarning(warn_msg, len, str);\n     \n      ## ref-filter.c ##\n    +@@\n    + #include \"object-name.h\"\n    + #include \"object-store-ll.h\"\n    + #include \"oid-array.h\"\n    ++#include \"repo-settings.h\"\n    + #include \"repository.h\"\n    + #include \"commit.h\"\n    + #include \"mailmap.h\"\n     @@ ref-filter.c: static const char *show_ref(struct refname_atom *atom, const char *refname)\n      \tif (atom->option == R_SHORT)\n      \t\treturn refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),\n21:  ecafe1585f8 = 21:  a0b75c4bc99 environment: stop storing \"core.notesRef\" globally\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501896","messageId":"a1969c5b0734cacd0316c34ef3d3b1939f521cd4.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 01/21] environment: make `get_git_dir()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:08:55Z","receivedAt":"2024-08-30T09:09:01Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_git_dir()` function retrieves the path to the Git directory for\n`the_repository`. Make it accept a `struct repository` such that it can\nwork on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n apply.c                     |  3 ++-\n builtin/am.c                |  5 +++--\n builtin/commit.c            |  7 ++++---\n builtin/config.c            |  2 +-\n builtin/difftool.c          |  5 +++--\n builtin/fsmonitor--daemon.c |  3 ++-\n builtin/merge.c             |  4 +++-\n builtin/stash.c             |  3 ++-\n cache-tree.c                |  5 +++--\n config.c                    |  4 +++-\n environment.c               | 10 ++--------\n environment.h               |  1 -\n pathspec.c                  |  2 +-\n read-cache.c                |  6 ++++--\n repository.c                |  7 +++++++\n repository.h                |  2 ++\n setup.c                     | 12 ++++++------\n setup.h                     |  2 +-\n trace.c                     |  5 ++++-\n transport-helper.c          |  2 +-\n worktree.c                  |  4 ++--\n 21 files changed, 56 insertions(+), 38 deletions(-)\n\ndiff --git a/apply.c b/apply.c\nindex 6e1060a952c..426cec32f8f 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -30,6 +30,7 @@\n #include \"path.h\"\n #include \"quote.h\"\n #include \"read-cache.h\"\n+#include \"repository.h\"\n #include \"rerere.h\"\n #include \"apply.h\"\n #include \"entry.h\"\n@@ -4111,7 +4112,7 @@ static int read_apply_cache(struct apply_state *state)\n {\n \tif (state->index_file)\n \t\treturn read_index_from(state->repo->index, state->index_file,\n-\t\t\t\t       get_git_dir());\n+\t\t\t\t       repo_get_git_dir(the_repository));\n \telse\n \t\treturn repo_read_index(state->repo);\n }\ndiff --git a/builtin/am.c b/builtin/am.c\nindex d8875ad4022..405214e242a 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1544,7 +1544,8 @@ static int run_apply(const struct am_state *state, const char *index_file)\n \tif (index_file) {\n \t\t/* Reload index as apply_all_patches() will have modified it. */\n \t\tdiscard_index(the_repository->index);\n-\t\tread_index_from(the_repository->index, index_file, get_git_dir());\n+\t\tread_index_from(the_repository->index, index_file,\n+\t\t\t\trepo_get_git_dir(the_repository));\n \t}\n \n \treturn 0;\n@@ -1587,7 +1588,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa\n \t\treturn error(\"could not build fake ancestor\");\n \n \tdiscard_index(the_repository->index);\n-\tread_index_from(the_repository->index, index_path, get_git_dir());\n+\tread_index_from(the_repository->index, index_path, repo_get_git_dir(the_repository));\n \n \tif (write_index_as_tree(&bases[0], the_repository->index, index_path, 0, NULL))\n \t\treturn error(_(\"Repository lacks necessary blobs to fall back on 3-way merge.\"));\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex b2033c48877..a1c1d16a099 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -26,6 +26,7 @@\n #include \"path.h\"\n #include \"preload-index.h\"\n #include \"read-cache.h\"\n+#include \"repository.h\"\n #include \"string-list.h\"\n #include \"rerere.h\"\n #include \"unpack-trees.h\"\n@@ -407,7 +408,7 @@ static const char *prepare_index(const char **argv, const char *prefix,\n \n \t\tdiscard_index(the_repository->index);\n \t\tread_index_from(the_repository->index, get_lock_file_path(&index_lock),\n-\t\t\t\tget_git_dir());\n+\t\t\t\trepo_get_git_dir(the_repository));\n \t\tif (cache_tree_update(the_repository->index, WRITE_TREE_SILENT) == 0) {\n \t\t\tif (reopen_lock_file(&index_lock) < 0)\n \t\t\t\tdie(_(\"unable to write index file\"));\n@@ -534,7 +535,7 @@ static const char *prepare_index(const char **argv, const char *prefix,\n \n \tdiscard_index(the_repository->index);\n \tret = get_lock_file_path(&false_lock);\n-\tread_index_from(the_repository->index, ret, get_git_dir());\n+\tread_index_from(the_repository->index, ret, repo_get_git_dir(the_repository));\n out:\n \tstring_list_clear(&partial, 0);\n \tclear_pathspec(&pathspec);\n@@ -1072,7 +1073,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\t */\n \t\tdiscard_index(the_repository->index);\n \t}\n-\tread_index_from(the_repository->index, index_file, get_git_dir());\n+\tread_index_from(the_repository->index, index_file, repo_get_git_dir(the_repository));\n \n \tif (cache_tree_update(the_repository->index, 0)) {\n \t\terror(_(\"Error building trees\"));\ndiff --git a/builtin/config.c b/builtin/config.c\nindex e00d983596b..c10697a2efb 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -808,7 +808,7 @@ static void location_options_init(struct config_location_options *opts,\n \t\topts->options.respect_includes = opts->respect_includes_opt;\n \tif (startup_info->have_repository) {\n \t\topts->options.commondir = get_git_common_dir();\n-\t\topts->options.git_dir = get_git_dir();\n+\t\topts->options.git_dir = repo_get_git_dir(the_repository);\n \t}\n }\n \ndiff --git a/builtin/difftool.c b/builtin/difftool.c\nindex dcc68e190c2..8c59411e6e0 100644\n--- a/builtin/difftool.c\n+++ b/builtin/difftool.c\n@@ -22,6 +22,7 @@\n #include \"hex.h\"\n #include \"parse-options.h\"\n #include \"read-cache-ll.h\"\n+#include \"repository.h\"\n #include \"sparse-index.h\"\n #include \"strvec.h\"\n #include \"strbuf.h\"\n@@ -214,7 +215,7 @@ static void changed_files(struct hashmap *result, const char *index_path,\n \tstruct child_process update_index = CHILD_PROCESS_INIT;\n \tstruct child_process diff_files = CHILD_PROCESS_INIT;\n \tstruct strbuf buf = STRBUF_INIT;\n-\tconst char *git_dir = absolute_path(get_git_dir());\n+\tconst char *git_dir = absolute_path(repo_get_git_dir(the_repository));\n \tFILE *fp;\n \n \tstrvec_pushl(&update_index.args,\n@@ -737,7 +738,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)\n \n \tif (!no_index){\n \t\tsetup_work_tree();\n-\t\tsetenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);\n+\t\tsetenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1);\n \t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);\n \t} else if (dir_diff)\n \t\tdie(_(\"options '%s' and '%s' cannot be used together\"), \"--dir-diff\", \"--no-index\");\ndiff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c\nindex 1593713f4cb..c54e736716a 100644\n--- a/builtin/fsmonitor--daemon.c\n+++ b/builtin/fsmonitor--daemon.c\n@@ -1311,7 +1311,8 @@ static int fsmonitor_run_daemon(void)\n \tstrbuf_addstr(&state.path_gitdir_watch, \"/.git\");\n \tif (!is_directory(state.path_gitdir_watch.buf)) {\n \t\tstrbuf_reset(&state.path_gitdir_watch);\n-\t\tstrbuf_addstr(&state.path_gitdir_watch, absolute_path(get_git_dir()));\n+\t\tstrbuf_addstr(&state.path_gitdir_watch,\n+\t\t\t      absolute_path(repo_get_git_dir(the_repository)));\n \t\tstate.nr_paths_watching = 2;\n \t}\n \ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 662a49a0e8c..a2bae0700b4 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -17,6 +17,7 @@\n #include \"object-name.h\"\n #include \"parse-options.h\"\n #include \"lockfile.h\"\n+#include \"repository.h\"\n #include \"run-command.h\"\n #include \"hook.h\"\n #include \"diff.h\"\n@@ -855,7 +856,8 @@ static void prepare_to_commit(struct commit_list *remoteheads)\n \t\tif (invoked_hook)\n \t\t\tdiscard_index(the_repository->index);\n \t}\n-\tread_index_from(the_repository->index, index_file, get_git_dir());\n+\tread_index_from(the_repository->index, index_file,\n+\t\t\trepo_get_git_dir(the_repository));\n \tstrbuf_addbuf(&msg, &merge_msg);\n \tif (squash)\n \t\tBUG(\"the control must not reach here under --squash\");\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex fcfd97972a4..ad6bcefb770 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -19,6 +19,7 @@\n #include \"entry.h\"\n #include \"preload-index.h\"\n #include \"read-cache.h\"\n+#include \"repository.h\"\n #include \"rerere.h\"\n #include \"revision.h\"\n #include \"setup.h\"\n@@ -642,7 +643,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\tstrvec_pushf(&cp.env, GIT_WORK_TREE_ENVIRONMENT\"=%s\",\n \t\t\t     absolute_path(get_git_work_tree()));\n \t\tstrvec_pushf(&cp.env, GIT_DIR_ENVIRONMENT\"=%s\",\n-\t\t\t     absolute_path(get_git_dir()));\n+\t\t\t     absolute_path(repo_get_git_dir(the_repository)));\n \t\tstrvec_push(&cp.args, \"status\");\n \t\trun_command(&cp);\n \t}\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 50610c3f3cb..b482167a69a 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -1,7 +1,6 @@\n #define USE_THE_REPOSITORY_VARIABLE\n \n #include \"git-compat-util.h\"\n-#include \"environment.h\"\n #include \"hex.h\"\n #include \"lockfile.h\"\n #include \"tree.h\"\n@@ -12,6 +11,7 @@\n #include \"object-store-ll.h\"\n #include \"read-cache-ll.h\"\n #include \"replace-object.h\"\n+#include \"repository.h\"\n #include \"promisor-remote.h\"\n #include \"trace.h\"\n #include \"trace2.h\"\n@@ -725,7 +725,8 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,\n \n \thold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);\n \n-\tentries = read_index_from(index_state, index_path, get_git_dir());\n+\tentries = read_index_from(index_state, index_path,\n+\t\t\t\t  repo_get_git_dir(the_repository));\n \tif (entries < 0) {\n \t\tret = WRITE_TREE_UNREADABLE_INDEX;\n \t\tgoto out;\ndiff --git a/config.c b/config.c\nindex 56b5862e59d..1733ba85dcd 100644\n--- a/config.c\n+++ b/config.c\n@@ -6,6 +6,8 @@\n  *\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"advice.h\"\n@@ -2212,7 +2214,7 @@ void read_early_config(config_fn_t cb, void *data)\n \n \tif (have_git_dir()) {\n \t\topts.commondir = get_git_common_dir();\n-\t\topts.git_dir = get_git_dir();\n+\t\topts.git_dir = repo_get_git_dir(the_repository);\n \t/*\n \t * When setup_git_directory() was not yet asked to discover the\n \t * GIT_DIR, we ask discover_git_directory() to figure out whether there\ndiff --git a/environment.c b/environment.c\nindex 1d6c48b52df..040b1ff1ba8 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -228,13 +228,6 @@ int have_git_dir(void)\n \t\t|| the_repository->gitdir;\n }\n \n-const char *get_git_dir(void)\n-{\n-\tif (!the_repository->gitdir)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->gitdir;\n-}\n-\n const char *get_git_common_dir(void)\n {\n \tif (!the_repository->commondir)\n@@ -352,7 +345,8 @@ static void update_relative_gitdir(const char *name UNUSED,\n \t\t\t\t   const char *new_cwd,\n \t\t\t\t   void *data UNUSED)\n {\n-\tchar *path = reparent_relative_path(old_cwd, new_cwd, get_git_dir());\n+\tchar *path = reparent_relative_path(old_cwd, new_cwd,\n+\t\t\t\t\t    repo_get_git_dir(the_repository));\n \tstruct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();\n \n \ttrace_printf_key(&trace_setup_key,\ndiff --git a/environment.h b/environment.h\nindex 0148738ed63..06d37d5c82b 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_git_dir(void);\n const char *get_git_common_dir(void);\n const char *get_object_directory(void);\n char *get_index_file(void);\ndiff --git a/pathspec.c b/pathspec.c\nindex fe1f0f41af0..416fe1e3dcc 100644\n--- a/pathspec.c\n+++ b/pathspec.c\n@@ -497,7 +497,7 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,\n \t\t\t\t    copyfrom);\n \t\t\thint_path = get_git_work_tree();\n \t\t\tif (!hint_path)\n-\t\t\t\thint_path = get_git_dir();\n+\t\t\t\thint_path = repo_get_git_dir(the_repository);\n \t\t\tdie(_(\"%s: '%s' is outside repository at '%s'\"), elt,\n \t\t\t    copyfrom, absolute_path(hint_path));\n \t\t}\ndiff --git a/read-cache.c b/read-cache.c\nindex 4e67dc182e7..764fdfec465 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -31,6 +31,7 @@\n #include \"path.h\"\n #include \"preload-index.h\"\n #include \"read-cache.h\"\n+#include \"repository.h\"\n #include \"resolve-undo.h\"\n #include \"revision.h\"\n #include \"strbuf.h\"\n@@ -3238,10 +3239,11 @@ static int should_delete_shared_index(const char *shared_index_path)\n static int clean_shared_index_files(const char *current_hex)\n {\n \tstruct dirent *de;\n-\tDIR *dir = opendir(get_git_dir());\n+\tDIR *dir = opendir(repo_get_git_dir(the_repository));\n \n \tif (!dir)\n-\t\treturn error_errno(_(\"unable to open git dir: %s\"), get_git_dir());\n+\t\treturn error_errno(_(\"unable to open git dir: %s\"),\n+\t\t\t\t   repo_get_git_dir(the_repository));\n \n \twhile ((de = readdir(dir)) != NULL) {\n \t\tconst char *sha1_hex;\ndiff --git a/repository.c b/repository.c\nindex 9825a308993..6f43f2e8344 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -91,6 +91,13 @@ static void expand_base_dir(char **out, const char *in,\n \t\t*out = xstrfmt(\"%s/%s\", base_dir, def_in);\n }\n \n+const char *repo_get_git_dir(struct repository *repo)\n+{\n+\tif (!repo->gitdir)\n+\t\tBUG(\"git environment hasn't been setup\");\n+\treturn repo->gitdir;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex af6ea0a62cd..cf2172c0aa5 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -206,6 +206,8 @@ struct repository {\n extern struct repository *the_repository;\n #endif\n \n+const char *repo_get_git_dir(struct repository *repo);\n+\n /*\n  * Define a custom repository layout. Any field can be NULL, which\n  * will default back to the path according to the default layout.\ndiff --git a/setup.c b/setup.c\nindex 29f86739212..4a9c60922e7 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -149,7 +149,7 @@ char *prefix_path(const char *prefix, int len, const char *path)\n \tif (!r) {\n \t\tconst char *hint_path = get_git_work_tree();\n \t\tif (!hint_path)\n-\t\t\thint_path = get_git_dir();\n+\t\t\thint_path = repo_get_git_dir(the_repository);\n \t\tdie(_(\"'%s' is outside repository at '%s'\"), path,\n \t\t    absolute_path(hint_path));\n \t}\n@@ -468,7 +468,7 @@ int is_nonbare_repository_dir(struct strbuf *path)\n int is_inside_git_dir(void)\n {\n \tif (inside_git_dir < 0)\n-\t\tinside_git_dir = is_inside_dir(get_git_dir());\n+\t\tinside_git_dir = is_inside_dir(repo_get_git_dir(the_repository));\n \treturn inside_git_dir;\n }\n \n@@ -1836,7 +1836,7 @@ void check_repository_format(struct repository_format *fmt)\n \tstruct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;\n \tif (!fmt)\n \t\tfmt = &repo_fmt;\n-\tcheck_repository_format_gently(get_git_dir(), fmt, NULL);\n+\tcheck_repository_format_gently(repo_get_git_dir(the_repository), fmt, NULL);\n \tstartup_info->have_repository = 1;\n \trepo_set_hash_algo(the_repository, fmt->hash_algo);\n \trepo_set_compat_hash_algo(the_repository, fmt->compat_hash_algo);\n@@ -2224,7 +2224,7 @@ static int create_default_files(const char *template_path,\n \t * shared-repository settings, we would need to fix them up.\n \t */\n \tif (get_shared_repository()) {\n-\t\tadjust_shared_perm(get_git_dir());\n+\t\tadjust_shared_perm(repo_get_git_dir(the_repository));\n \t}\n \n \tinitialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, 0);\n@@ -2434,12 +2434,12 @@ int init_db(const char *git_dir, const char *real_git_dir,\n \t\t\tdie(_(\"%s already exists\"), real_git_dir);\n \n \t\tset_git_dir(real_git_dir, 1);\n-\t\tgit_dir = get_git_dir();\n+\t\tgit_dir = repo_get_git_dir(the_repository);\n \t\tseparate_git_dir(git_dir, original_git_dir);\n \t}\n \telse {\n \t\tset_git_dir(git_dir, 1);\n-\t\tgit_dir = get_git_dir();\n+\t\tgit_dir = repo_get_git_dir(the_repository);\n \t}\n \tstartup_info->have_repository = 1;\n \ndiff --git a/setup.h b/setup.h\nindex cd8dbc24976..fd2df7cd525 100644\n--- a/setup.h\n+++ b/setup.h\n@@ -176,7 +176,7 @@ int verify_repository_format(const struct repository_format *format,\n \t\t\t     struct strbuf *err);\n \n /*\n- * Check the repository format version in the path found in get_git_dir(),\n+ * Check the repository format version in the path found in repo_get_git_dir(the_repository),\n  * and die if it is a version we don't understand. Generally one would\n  * set_git_dir() before calling this, and use it only for \"are we in a valid\n  * repo?\".\ndiff --git a/trace.c b/trace.c\nindex 8669ddfca25..32c5cda7afd 100644\n--- a/trace.c\n+++ b/trace.c\n@@ -21,9 +21,12 @@\n  *  along with this program; if not, see <https://www.gnu.org/licenses/>.\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"environment.h\"\n+#include \"repository.h\"\n #include \"quote.h\"\n #include \"setup.h\"\n #include \"trace.h\"\n@@ -311,7 +314,7 @@ void trace_repo_setup(void)\n \tif (!startup_info->prefix)\n \t\tprefix = \"(null)\";\n \n-\ttrace_printf_key(&trace_setup_key, \"setup: git_dir: %s\\n\", quote_crnl(get_git_dir()));\n+\ttrace_printf_key(&trace_setup_key, \"setup: git_dir: %s\\n\", quote_crnl(repo_get_git_dir(the_repository)));\n \ttrace_printf_key(&trace_setup_key, \"setup: git_common_dir: %s\\n\", quote_crnl(get_git_common_dir()));\n \ttrace_printf_key(&trace_setup_key, \"setup: worktree: %s\\n\", quote_crnl(git_work_tree));\n \ttrace_printf_key(&trace_setup_key, \"setup: cwd: %s\\n\", quote_crnl(cwd));\ndiff --git a/transport-helper.c b/transport-helper.c\nindex 09b3560ffdc..abe16eea651 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -143,7 +143,7 @@ static struct child_process *get_helper(struct transport *transport)\n \n \tif (have_git_dir())\n \t\tstrvec_pushf(&helper->env, \"%s=%s\",\n-\t\t\t     GIT_DIR_ENVIRONMENT, get_git_dir());\n+\t\t\t     GIT_DIR_ENVIRONMENT, repo_get_git_dir(the_repository));\n \n \thelper->trace2_child_class = helper->args.v[0]; /* \"remote-<name>\" */\n \ndiff --git a/worktree.c b/worktree.c\nindex 30a947426ee..11335c5d9a3 100644\n--- a/worktree.c\n+++ b/worktree.c\n@@ -57,7 +57,7 @@ static void add_head_info(struct worktree *wt)\n \n static int is_current_worktree(struct worktree *wt)\n {\n-\tchar *git_dir = absolute_pathdup(get_git_dir());\n+\tchar *git_dir = absolute_pathdup(repo_get_git_dir(the_repository));\n \tconst char *wt_git_dir = get_worktree_git_dir(wt);\n \tint is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir));\n \tfree(git_dir);\n@@ -171,7 +171,7 @@ struct worktree **get_worktrees(void)\n const char *get_worktree_git_dir(const struct worktree *wt)\n {\n \tif (!wt)\n-\t\treturn get_git_dir();\n+\t\treturn repo_get_git_dir(the_repository);\n \telse if (!wt->id)\n \t\treturn get_git_common_dir();\n \telse\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501897","messageId":"deebf2c520574e268ed51af759b31d850beb423e.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 02/21] environment: make `get_git_common_dir()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:00Z","receivedAt":"2024-08-30T09:09:03Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_git_common_dir()` function retrieves the path to the common\ndirectory for `the_repository`. Make it accept a `struct repository`\nsuch that it can work on arbitrary repositories and make it part of the\nrepository subsystem. This reduces our reliance on `the_repository` and\nclarifies scope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/config.c    | 2 +-\n builtin/gc.c        | 2 +-\n builtin/rev-parse.c | 3 ++-\n builtin/worktree.c  | 4 ++--\n config.c            | 2 +-\n environment.c       | 7 -------\n environment.h       | 1 -\n repository.c        | 7 +++++++\n repository.h        | 1 +\n setup.c             | 2 +-\n submodule.c         | 2 +-\n trace.c             | 2 +-\n worktree.c          | 8 ++++----\n 13 files changed, 22 insertions(+), 21 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex c10697a2efb..34a371414e8 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -807,7 +807,7 @@ static void location_options_init(struct config_location_options *opts,\n \telse\n \t\topts->options.respect_includes = opts->respect_includes_opt;\n \tif (startup_info->have_repository) {\n-\t\topts->options.commondir = get_git_common_dir();\n+\t\topts->options.commondir = repo_get_common_dir(the_repository);\n \t\topts->options.git_dir = repo_get_git_dir(the_repository);\n \t}\n }\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex 427faf1cfe1..0f3d74f8bd0 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -2132,7 +2132,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority\n \tget_schedule_cmd(&cmd, NULL);\n \n \tstrbuf_addf(&tfilename, \"%s/schedule_%s_XXXXXX\",\n-\t\t    get_git_common_dir(), frequency);\n+\t\t    repo_get_common_dir(the_repository), frequency);\n \ttfile = xmks_tempfile(tfilename.buf);\n \tstrbuf_release(&tfilename);\n \ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex 4285dc34a7b..cd85fe57bb0 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -19,6 +19,7 @@\n #include \"path.h\"\n #include \"diff.h\"\n #include \"read-cache-ll.h\"\n+#include \"repository.h\"\n #include \"revision.h\"\n #include \"setup.h\"\n #include \"split-index.h\"\n@@ -1042,7 +1043,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--git-common-dir\")) {\n-\t\t\t\tprint_path(get_git_common_dir(), prefix, format, DEFAULT_RELATIVE_IF_SHARED);\n+\t\t\t\tprint_path(repo_get_common_dir(the_repository), prefix, format, DEFAULT_RELATIVE_IF_SHARED);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--is-inside-git-dir\")) {\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 41e7f6a3271..645b548bf3b 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -219,7 +219,7 @@ static void prune_worktrees(void)\n \t}\n \tclosedir(dir);\n \n-\tstrbuf_add_absolute_path(&main_path, get_git_common_dir());\n+\tstrbuf_add_absolute_path(&main_path, repo_get_common_dir(the_repository));\n \t/* massage main worktree absolute path to match 'gitdir' content */\n \tstrbuf_strip_suffix(&main_path, \"/.\");\n \tstring_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));\n@@ -492,7 +492,7 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/gitdir\", sb_repo.buf);\n \tstrbuf_realpath(&realpath, sb_git.buf, 1);\n \twrite_file(sb.buf, \"%s\", realpath.buf);\n-\tstrbuf_realpath(&realpath, get_git_common_dir(), 1);\n+\tstrbuf_realpath(&realpath, repo_get_common_dir(the_repository), 1);\n \twrite_file(sb_git.buf, \"gitdir: %s/worktrees/%s\",\n \t\t   realpath.buf, name);\n \tstrbuf_reset(&sb);\ndiff --git a/config.c b/config.c\nindex 1733ba85dcd..0b87f0f9050 100644\n--- a/config.c\n+++ b/config.c\n@@ -2213,7 +2213,7 @@ void read_early_config(config_fn_t cb, void *data)\n \topts.respect_includes = 1;\n \n \tif (have_git_dir()) {\n-\t\topts.commondir = get_git_common_dir();\n+\t\topts.commondir = repo_get_common_dir(the_repository);\n \t\topts.git_dir = repo_get_git_dir(the_repository);\n \t/*\n \t * When setup_git_directory() was not yet asked to discover the\ndiff --git a/environment.c b/environment.c\nindex 040b1ff1ba8..7c4a142ca25 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -228,13 +228,6 @@ int have_git_dir(void)\n \t\t|| the_repository->gitdir;\n }\n \n-const char *get_git_common_dir(void)\n-{\n-\tif (!the_repository->commondir)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->commondir;\n-}\n-\n const char *get_git_namespace(void)\n {\n \tif (!git_namespace)\ndiff --git a/environment.h b/environment.h\nindex 06d37d5c82b..d778614158f 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_git_common_dir(void);\n const char *get_object_directory(void);\n char *get_index_file(void);\n char *get_graft_file(struct repository *r);\ndiff --git a/repository.c b/repository.c\nindex 6f43f2e8344..acf654d7ab6 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -98,6 +98,13 @@ const char *repo_get_git_dir(struct repository *repo)\n \treturn repo->gitdir;\n }\n \n+const char *repo_get_common_dir(struct repository *repo)\n+{\n+\tif (!repo->commondir)\n+\t\tBUG(\"git environment hasn't been setup\");\n+\treturn repo->commondir;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex cf2172c0aa5..404435ad029 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -207,6 +207,7 @@ extern struct repository *the_repository;\n #endif\n \n const char *repo_get_git_dir(struct repository *repo);\n+const char *repo_get_common_dir(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/setup.c b/setup.c\nindex 4a9c60922e7..fe4a5dfc43b 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2068,7 +2068,7 @@ static void copy_templates(const char *option_template)\n \t\tgoto close_free_return;\n \t}\n \n-\tstrbuf_addstr(&path, get_git_common_dir());\n+\tstrbuf_addstr(&path, repo_get_common_dir(the_repository));\n \tstrbuf_complete(&path, '/');\n \tcopy_templates_1(&path, &template_path, dir);\n close_free_return:\ndiff --git a/submodule.c b/submodule.c\nindex 97516b0fec1..c7d164a31ab 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -2462,7 +2462,7 @@ void absorb_git_dir_into_superproject(const char *path,\n \t} else {\n \t\t/* Is it already absorbed into the superprojects git dir? */\n \t\tchar *real_sub_git_dir = real_pathdup(sub_git_dir, 1);\n-\t\tchar *real_common_git_dir = real_pathdup(get_git_common_dir(), 1);\n+\t\tchar *real_common_git_dir = real_pathdup(repo_get_common_dir(the_repository), 1);\n \n \t\tif (!starts_with(real_sub_git_dir, real_common_git_dir))\n \t\t\trelocate_single_git_dir_into_superproject(path, super_prefix);\ndiff --git a/trace.c b/trace.c\nindex 32c5cda7afd..e6728c301f3 100644\n--- a/trace.c\n+++ b/trace.c\n@@ -315,7 +315,7 @@ void trace_repo_setup(void)\n \t\tprefix = \"(null)\";\n \n \ttrace_printf_key(&trace_setup_key, \"setup: git_dir: %s\\n\", quote_crnl(repo_get_git_dir(the_repository)));\n-\ttrace_printf_key(&trace_setup_key, \"setup: git_common_dir: %s\\n\", quote_crnl(get_git_common_dir()));\n+\ttrace_printf_key(&trace_setup_key, \"setup: git_common_dir: %s\\n\", quote_crnl(repo_get_common_dir(the_repository)));\n \ttrace_printf_key(&trace_setup_key, \"setup: worktree: %s\\n\", quote_crnl(git_work_tree));\n \ttrace_printf_key(&trace_setup_key, \"setup: cwd: %s\\n\", quote_crnl(cwd));\n \ttrace_printf_key(&trace_setup_key, \"setup: prefix: %s\\n\", quote_crnl(prefix));\ndiff --git a/worktree.c b/worktree.c\nindex 11335c5d9a3..0f032ccedff 100644\n--- a/worktree.c\n+++ b/worktree.c\n@@ -72,7 +72,7 @@ static struct worktree *get_main_worktree(int skip_reading_head)\n \tstruct worktree *worktree = NULL;\n \tstruct strbuf worktree_path = STRBUF_INIT;\n \n-\tstrbuf_add_real_path(&worktree_path, get_git_common_dir());\n+\tstrbuf_add_real_path(&worktree_path, repo_get_common_dir(the_repository));\n \tstrbuf_strip_suffix(&worktree_path, \"/.git\");\n \n \tCALLOC_ARRAY(worktree, 1);\n@@ -143,7 +143,7 @@ static struct worktree **get_worktrees_internal(int skip_reading_head)\n \n \tlist[counter++] = get_main_worktree(skip_reading_head);\n \n-\tstrbuf_addf(&path, \"%s/worktrees\", get_git_common_dir());\n+\tstrbuf_addf(&path, \"%s/worktrees\", repo_get_common_dir(the_repository));\n \tdir = opendir(path.buf);\n \tstrbuf_release(&path);\n \tif (dir) {\n@@ -173,7 +173,7 @@ const char *get_worktree_git_dir(const struct worktree *wt)\n \tif (!wt)\n \t\treturn repo_get_git_dir(the_repository);\n \telse if (!wt->id)\n-\t\treturn get_git_common_dir();\n+\t\treturn repo_get_common_dir(the_repository);\n \telse\n \t\treturn git_common_path(\"worktrees/%s\", wt->id);\n }\n@@ -626,7 +626,7 @@ static int is_main_worktree_path(const char *path)\n \n \tstrbuf_add_real_path(&target, path);\n \tstrbuf_strip_suffix(&target, \"/.git\");\n-\tstrbuf_add_real_path(&maindir, get_git_common_dir());\n+\tstrbuf_add_real_path(&maindir, repo_get_common_dir(the_repository));\n \tstrbuf_strip_suffix(&maindir, \"/.git\");\n \tcmp = fspathcmp(maindir.buf, target.buf);\n \n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501898","messageId":"43abfa7b139f456b83ab58d33aaf1e97a0225c67.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 03/21] environment: make `get_object_directory()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:03Z","receivedAt":"2024-08-30T09:09:06Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_object_directory()` function retrieves the path to the object\ndirectory for `the_repository`. Make it accept a `struct repository`\nsuch that it can work on arbitrary repositories and make it part of the\nrepository subsystem. This reduces our reliance on `the_repository` and\nclarifies scope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/commit-graph.c     | 5 ++---\n builtin/count-objects.c    | 3 +--\n builtin/multi-pack-index.c | 4 ++--\n builtin/pack-objects.c     | 2 +-\n builtin/prune.c            | 8 ++++----\n builtin/repack.c           | 7 ++++---\n bulk-checkin.c             | 4 ++--\n environment.c              | 7 -------\n environment.h              | 1 -\n fetch-pack.c               | 2 +-\n http-backend.c             | 2 +-\n object-file.c              | 4 ++--\n pack-write.c               | 3 ++-\n packfile.c                 | 2 +-\n prune-packed.c             | 6 ++++--\n repository.c               | 7 +++++++\n repository.h               | 1 +\n server-info.c              | 4 ++--\n setup.c                    | 2 +-\n tmp-objdir.c               | 8 +++++---\n 20 files changed, 43 insertions(+), 39 deletions(-)\n\ndiff --git a/builtin/commit-graph.c b/builtin/commit-graph.c\nindex 7102ee90a00..7411e6244f2 100644\n--- a/builtin/commit-graph.c\n+++ b/builtin/commit-graph.c\n@@ -1,7 +1,6 @@\n #include \"builtin.h\"\n #include \"commit.h\"\n #include \"config.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"hex.h\"\n #include \"parse-options.h\"\n@@ -95,7 +94,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(builtin_commit_graph_verify_usage, options);\n \n \tif (!opts.obj_dir)\n-\t\topts.obj_dir = get_object_directory();\n+\t\topts.obj_dir = repo_get_object_directory(the_repository);\n \tif (opts.shallow)\n \t\tflags |= COMMIT_GRAPH_VERIFY_SHALLOW;\n \tif (opts.progress)\n@@ -275,7 +274,7 @@ static int graph_write(int argc, const char **argv, const char *prefix)\n \tif (opts.reachable + opts.stdin_packs + opts.stdin_commits > 1)\n \t\tdie(_(\"use at most one of --reachable, --stdin-commits, or --stdin-packs\"));\n \tif (!opts.obj_dir)\n-\t\topts.obj_dir = get_object_directory();\n+\t\topts.obj_dir = repo_get_object_directory(the_repository);\n \tif (opts.append)\n \t\tflags |= COMMIT_GRAPH_WRITE_APPEND;\n \tif (opts.split)\ndiff --git a/builtin/count-objects.c b/builtin/count-objects.c\nindex ec6098a149d..42275f62d59 100644\n--- a/builtin/count-objects.c\n+++ b/builtin/count-objects.c\n@@ -7,7 +7,6 @@\n #include \"builtin.h\"\n #include \"config.h\"\n #include \"dir.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"path.h\"\n #include \"repository.h\"\n@@ -116,7 +115,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)\n \t\treport_linked_checkout_garbage(the_repository);\n \t}\n \n-\tfor_each_loose_file_in_objdir(get_object_directory(),\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n \t\t\t\t      count_loose, count_cruft, NULL, NULL);\n \n \tif (verbose) {\ndiff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c\nindex 8805cbbeb3b..55289e989df 100644\n--- a/builtin/multi-pack-index.c\n+++ b/builtin/multi-pack-index.c\n@@ -1,7 +1,6 @@\n #include \"builtin.h\"\n #include \"abspath.h\"\n #include \"config.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"parse-options.h\"\n #include \"midx.h\"\n@@ -9,6 +8,7 @@\n #include \"trace2.h\"\n #include \"object-store-ll.h\"\n #include \"replace-object.h\"\n+#include \"repository.h\"\n \n #define BUILTIN_MIDX_WRITE_USAGE \\\n \tN_(\"git multi-pack-index [<options>] write [--preferred-pack=<pack>]\" \\\n@@ -63,7 +63,7 @@ static int parse_object_dir(const struct option *opt, const char *arg,\n \tchar **value = opt->value;\n \tfree(*value);\n \tif (unset)\n-\t\t*value = xstrdup(get_object_directory());\n+\t\t*value = xstrdup(repo_get_object_directory(the_repository));\n \telse\n \t\t*value = real_pathdup(arg, 1);\n \treturn 0;\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 778be80f564..44341b206d4 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -3940,7 +3940,7 @@ static int add_loose_object(const struct object_id *oid, const char *path,\n  */\n static void add_unreachable_loose_objects(void)\n {\n-\tfor_each_loose_file_in_objdir(get_object_directory(),\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n \t\t\t\t      add_loose_object,\n \t\t\t\t      NULL, NULL, NULL);\n }\ndiff --git a/builtin/prune.c b/builtin/prune.c\nindex 57fe31467fe..47eeabbd13a 100644\n--- a/builtin/prune.c\n+++ b/builtin/prune.c\n@@ -193,12 +193,12 @@ int cmd_prune(int argc, const char **argv, const char *prefix)\n \t\trevs.exclude_promisor_objects = 1;\n \t}\n \n-\tfor_each_loose_file_in_objdir(get_object_directory(), prune_object,\n-\t\t\t\t      prune_cruft, prune_subdir, &revs);\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n+\t\t\t\t      prune_object, prune_cruft, prune_subdir, &revs);\n \n \tprune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0);\n-\tremove_temporary_files(get_object_directory());\n-\ts = mkpathdup(\"%s/pack\", get_object_directory());\n+\tremove_temporary_files(repo_get_object_directory(the_repository));\n+\ts = mkpathdup(\"%s/pack\", repo_get_object_directory(the_repository));\n \tremove_temporary_files(s);\n \tfree(s);\n \ndiff --git a/builtin/repack.c b/builtin/repack.c\nindex 62cfa50c50f..40feacb73f8 100644\n--- a/builtin/repack.c\n+++ b/builtin/repack.c\n@@ -1240,7 +1240,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \tif (write_midx && write_bitmaps) {\n \t\tstruct strbuf path = STRBUF_INIT;\n \n-\t\tstrbuf_addf(&path, \"%s/%s_XXXXXX\", get_object_directory(),\n+\t\tstrbuf_addf(&path, \"%s/%s_XXXXXX\", repo_get_object_directory(the_repository),\n \t\t\t    \"bitmap-ref-tips\");\n \n \t\trefs_snapshot = xmks_tempfile(path.buf);\n@@ -1249,7 +1249,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\tstrbuf_release(&path);\n \t}\n \n-\tpackdir = mkpathdup(\"%s/pack\", get_object_directory());\n+\tpackdir = mkpathdup(\"%s/pack\", repo_get_object_directory(the_repository));\n \tpacktmp_name = xstrfmt(\".tmp-%d-pack\", (int)getpid());\n \tpacktmp = mkpathdup(\"%s/%s\", packdir, packtmp_name);\n \n@@ -1519,7 +1519,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\tunsigned flags = 0;\n \t\tif (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL, 0))\n \t\t\tflags |= MIDX_WRITE_INCREMENTAL;\n-\t\twrite_midx_file(get_object_directory(), NULL, NULL, flags);\n+\t\twrite_midx_file(repo_get_object_directory(the_repository),\n+\t\t\t\tNULL, NULL, flags);\n \t}\n \n cleanup:\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex 9089c214fa4..2753d5bbe4a 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -75,7 +75,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state)\n \t\tclose(fd);\n \t}\n \n-\tstrbuf_addf(&packname, \"%s/pack/pack-%s.\", get_object_directory(),\n+\tstrbuf_addf(&packname, \"%s/pack/pack-%s.\", repo_get_object_directory(the_repository),\n \t\t    hash_to_hex(hash));\n \tfinish_tmp_packfile(&packname, state->pack_tmp_name,\n \t\t\t    state->written, state->nr_written,\n@@ -113,7 +113,7 @@ static void flush_batch_fsync(void)\n \t * to ensure that the data in each new object file is durable before\n \t * the final name is visible.\n \t */\n-\tstrbuf_addf(&temp_path, \"%s/bulk_fsync_XXXXXX\", get_object_directory());\n+\tstrbuf_addf(&temp_path, \"%s/bulk_fsync_XXXXXX\", repo_get_object_directory(the_repository));\n \ttemp = xmks_tempfile(temp_path.buf);\n \tfsync_or_die(get_tempfile_fd(temp), get_tempfile_path(temp));\n \tdelete_tempfile(&temp);\ndiff --git a/environment.c b/environment.c\nindex 7c4a142ca25..0a2057399e0 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -273,13 +273,6 @@ const char *get_git_work_tree(void)\n \treturn the_repository->worktree;\n }\n \n-const char *get_object_directory(void)\n-{\n-\tif (!the_repository->objects->odb)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->objects->odb->path;\n-}\n-\n int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n {\n \tint fd;\ndiff --git a/environment.h b/environment.h\nindex d778614158f..91125d82991 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_object_directory(void);\n char *get_index_file(void);\n char *get_graft_file(struct repository *r);\n void set_git_dir(const char *path, int make_realpath);\ndiff --git a/fetch-pack.c b/fetch-pack.c\nindex 58b4581ad80..fddb90f2e78 100644\n--- a/fetch-pack.c\n+++ b/fetch-pack.c\n@@ -1839,7 +1839,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,\n \n \t\tstring_list_append_nodup(pack_lockfiles,\n \t\t\t\t\t xstrfmt(\"%s/pack/pack-%s.keep\",\n-\t\t\t\t\t\t get_object_directory(),\n+\t\t\t\t\t\t repo_get_object_directory(the_repository),\n \t\t\t\t\t\t packname));\n \t}\n \tstring_list_clear(&packfile_uris, 0);\ndiff --git a/http-backend.c b/http-backend.c\nindex 79ce097359b..73eec4ea3d8 100644\n--- a/http-backend.c\n+++ b/http-backend.c\n@@ -601,7 +601,7 @@ static void get_head(struct strbuf *hdr, char *arg UNUSED)\n \n static void get_info_packs(struct strbuf *hdr, char *arg UNUSED)\n {\n-\tsize_t objdirlen = strlen(get_object_directory());\n+\tsize_t objdirlen = strlen(repo_get_object_directory(the_repository));\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct packed_git *p;\n \tsize_t cnt = 0;\ndiff --git a/object-file.c b/object-file.c\nindex c5994202ba0..fa4121b98ad 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2053,7 +2053,7 @@ static int start_loose_object_common(struct strbuf *tmp_file,\n \t\telse if (errno == EACCES)\n \t\t\treturn error(_(\"insufficient permission for adding \"\n \t\t\t\t       \"an object to repository database %s\"),\n-\t\t\t\t     get_object_directory());\n+\t\t\t\t     repo_get_object_directory(the_repository));\n \t\telse\n \t\t\treturn error_errno(\n \t\t\t\t_(\"unable to create temporary file\"));\n@@ -2228,7 +2228,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,\n \t\tprepare_loose_object_bulk_checkin();\n \n \t/* Since oid is not determined, save tmp file to odb path. */\n-\tstrbuf_addf(&filename, \"%s/\", get_object_directory());\n+\tstrbuf_addf(&filename, \"%s/\", repo_get_object_directory(the_repository));\n \thdrlen = format_object_header(hdr, sizeof(hdr), OBJ_BLOB, len);\n \n \t/*\ndiff --git a/pack-write.c b/pack-write.c\nindex d07f03d0ab0..27965672f17 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -12,6 +12,7 @@\n #include \"pack-objects.h\"\n #include \"pack-revindex.h\"\n #include \"path.h\"\n+#include \"repository.h\"\n #include \"strbuf.h\"\n \n void reset_pack_idx_option(struct pack_idx_option *opts)\n@@ -473,7 +474,7 @@ char *index_pack_lockfile(int ip_out, int *is_well_formed)\n \t\tpackname[len-1] = 0;\n \t\tif (skip_prefix(packname, \"keep\\t\", &name))\n \t\t\treturn xstrfmt(\"%s/pack/pack-%s.keep\",\n-\t\t\t\t       get_object_directory(), name);\n+\t\t\t\t       repo_get_object_directory(the_repository), name);\n \t\treturn NULL;\n \t}\n \tif (is_well_formed)\ndiff --git a/packfile.c b/packfile.c\nindex cf12a539eac..df4ba677197 100644\n--- a/packfile.c\n+++ b/packfile.c\n@@ -30,7 +30,7 @@ char *odb_pack_name(struct strbuf *buf,\n \t\t    const char *ext)\n {\n \tstrbuf_reset(buf);\n-\tstrbuf_addf(buf, \"%s/pack/pack-%s.%s\", get_object_directory(),\n+\tstrbuf_addf(buf, \"%s/pack/pack-%s.%s\", repo_get_object_directory(the_repository),\n \t\t    hash_to_hex(hash), ext);\n \treturn buf->buf;\n }\ndiff --git a/prune-packed.c b/prune-packed.c\nindex e54daf740a2..2bb99c29dfb 100644\n--- a/prune-packed.c\n+++ b/prune-packed.c\n@@ -1,10 +1,12 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"object-store-ll.h\"\n #include \"packfile.h\"\n #include \"progress.h\"\n #include \"prune-packed.h\"\n+#include \"repository.h\"\n \n static struct progress *progress;\n \n@@ -37,7 +39,7 @@ void prune_packed_objects(int opts)\n \tif (opts & PRUNE_PACKED_VERBOSE)\n \t\tprogress = start_delayed_progress(_(\"Removing duplicate objects\"), 256);\n \n-\tfor_each_loose_file_in_objdir(get_object_directory(),\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n \t\t\t\t      prune_object, NULL, prune_subdir, &opts);\n \n \t/* Ensure we show 100% before finishing progress */\ndiff --git a/repository.c b/repository.c\nindex acf654d7ab6..914ee25a1f0 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -105,6 +105,13 @@ const char *repo_get_common_dir(struct repository *repo)\n \treturn repo->commondir;\n }\n \n+const char *repo_get_object_directory(struct repository *repo)\n+{\n+\tif (!repo->objects->odb)\n+\t\tBUG(\"git environment hasn't been setup\");\n+\treturn repo->objects->odb->path;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex 404435ad029..778f1511ab1 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -208,6 +208,7 @@ extern struct repository *the_repository;\n \n const char *repo_get_git_dir(struct repository *repo);\n const char *repo_get_common_dir(struct repository *repo);\n+const char *repo_get_object_directory(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/server-info.c b/server-info.c\nindex 1508fa6f825..c5af4cd98a6 100644\n--- a/server-info.c\n+++ b/server-info.c\n@@ -2,7 +2,6 @@\n \n #include \"git-compat-util.h\"\n #include \"dir.h\"\n-#include \"environment.h\"\n #include \"hex.h\"\n #include \"repository.h\"\n #include \"refs.h\"\n@@ -342,7 +341,8 @@ static int write_pack_info_file(struct update_info_ctx *uic)\n \n static int update_info_packs(int force)\n {\n-\tchar *infofile = mkpathdup(\"%s/info/packs\", get_object_directory());\n+\tchar *infofile = mkpathdup(\"%s/info/packs\",\n+\t\t\t\t   repo_get_object_directory(the_repository));\n \tint ret;\n \n \tinit_pack_info(infofile, force);\ndiff --git a/setup.c b/setup.c\nindex fe4a5dfc43b..1ebcab625fe 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2282,7 +2282,7 @@ static void create_object_directory(void)\n \tstruct strbuf path = STRBUF_INIT;\n \tsize_t baselen;\n \n-\tstrbuf_addstr(&path, get_object_directory());\n+\tstrbuf_addstr(&path, repo_get_object_directory(the_repository));\n \tbaselen = path.len;\n \n \tsafe_create_dir(path.buf, 1);\ndiff --git a/tmp-objdir.c b/tmp-objdir.c\nindex a8e4553f274..c2fb9f91930 100644\n--- a/tmp-objdir.c\n+++ b/tmp-objdir.c\n@@ -13,6 +13,7 @@\n #include \"strvec.h\"\n #include \"quote.h\"\n #include \"object-store-ll.h\"\n+#include \"repository.h\"\n \n struct tmp_objdir {\n \tstruct strbuf path;\n@@ -132,7 +133,8 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix)\n \t * can recognize any stale objdirs left behind by a crash and delete\n \t * them.\n \t */\n-\tstrbuf_addf(&t->path, \"%s/tmp_objdir-%s-XXXXXX\", get_object_directory(), prefix);\n+\tstrbuf_addf(&t->path, \"%s/tmp_objdir-%s-XXXXXX\",\n+\t\t    repo_get_object_directory(the_repository), prefix);\n \n \tif (!mkdtemp(t->path.buf)) {\n \t\t/* free, not destroy, as we never touched the filesystem */\n@@ -152,7 +154,7 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix)\n \t}\n \n \tenv_append(&t->env, ALTERNATE_DB_ENVIRONMENT,\n-\t\t   absolute_path(get_object_directory()));\n+\t\t   absolute_path(repo_get_object_directory(the_repository)));\n \tenv_replace(&t->env, DB_ENVIRONMENT, absolute_path(t->path.buf));\n \tenv_replace(&t->env, GIT_QUARANTINE_ENVIRONMENT,\n \t\t    absolute_path(t->path.buf));\n@@ -267,7 +269,7 @@ int tmp_objdir_migrate(struct tmp_objdir *t)\n \t}\n \n \tstrbuf_addbuf(&src, &t->path);\n-\tstrbuf_addstr(&dst, get_object_directory());\n+\tstrbuf_addstr(&dst, repo_get_object_directory(the_repository));\n \n \tret = migrate_paths(&src, &dst);\n \n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501899","messageId":"d7554cb0fe066eea8c752a3dcccb1f5975b7e6f5.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 04/21] environment: make `get_index_file()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:05Z","receivedAt":"2024-08-30T09:09:09Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_index_file()` function retrieves the path to the index file\nof `the_repository`. Make it accept a `struct repository` such that it\ncan work on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/am.c           |  8 ++++++--\n builtin/commit.c       |  6 +++---\n builtin/merge.c        | 14 ++++++++------\n builtin/stash.c        | 12 ++++++------\n builtin/update-index.c |  2 +-\n builtin/write-tree.c   |  4 ++--\n environment.c          |  7 -------\n environment.h          |  1 -\n repository.c           |  7 +++++++\n repository.h           |  1 +\n wt-status.c            |  3 ++-\n 11 files changed, 36 insertions(+), 29 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 405214e242a..5498ddeb6aa 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1668,7 +1668,9 @@ static void do_commit(const struct am_state *state)\n \tif (!state->no_verify && run_hooks(the_repository, \"pre-applypatch\"))\n \t\texit(1);\n \n-\tif (write_index_as_tree(&tree, the_repository->index, get_index_file(), 0, NULL))\n+\tif (write_index_as_tree(&tree, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository),\n+\t\t\t\t0, NULL))\n \t\tdie(_(\"git write-tree failed to write a tree\"));\n \n \tif (!repo_get_oid_commit(the_repository, \"HEAD\", &parent)) {\n@@ -2078,7 +2080,9 @@ static int clean_index(const struct object_id *head, const struct object_id *rem\n \tif (fast_forward_to(head_tree, head_tree, 1))\n \t\treturn -1;\n \n-\tif (write_index_as_tree(&index, the_repository->index, get_index_file(), 0, NULL))\n+\tif (write_index_as_tree(&index, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository),\n+\t\t\t\t0, NULL))\n \t\treturn -1;\n \n \tindex_tree = parse_tree_indirect(&index);\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex a1c1d16a099..b09320f9070 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -473,7 +473,7 @@ static const char *prepare_index(const char **argv, const char *prefix,\n \t\t\t\t       COMMIT_LOCK | SKIP_IF_UNCHANGED))\n \t\t\tdie(_(\"unable to write new index file\"));\n \t\tcommit_style = COMMIT_AS_IS;\n-\t\tret = get_index_file();\n+\t\tret = repo_get_index_file(the_repository);\n \t\tgoto out;\n \t}\n \n@@ -1874,8 +1874,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \n \trepo_rerere(the_repository, 0);\n \trun_auto_maintenance(quiet);\n-\trun_commit_hook(use_editor, get_index_file(), NULL, \"post-commit\",\n-\t\t\tNULL);\n+\trun_commit_hook(use_editor, repo_get_index_file(the_repository),\n+\t\t\tNULL, \"post-commit\", NULL);\n \tif (amend && !no_post_rewrite) {\n \t\tcommit_post_rewrite(the_repository, current_head, &oid);\n \t}\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex a2bae0700b4..7f5475f738c 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -696,7 +696,9 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,\n \n static void write_tree_trivial(struct object_id *oid)\n {\n-\tif (write_index_as_tree(oid, the_repository->index, get_index_file(), 0, NULL))\n+\tif (write_index_as_tree(oid, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository),\n+\t\t\t\t0, NULL))\n \t\tdie(_(\"git write-tree failed to write a tree\"));\n }\n \n@@ -758,7 +760,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,\n \t\t}\n \t\tif (write_locked_index(the_repository->index, &lock,\n \t\t\t\t       COMMIT_LOCK | SKIP_IF_UNCHANGED))\n-\t\t\tdie(_(\"unable to write %s\"), get_index_file());\n+\t\t\tdie(_(\"unable to write %s\"), repo_get_index_file(the_repository));\n \t\treturn clean ? 0 : 1;\n \t} else {\n \t\treturn try_merge_command(the_repository,\n@@ -840,7 +842,7 @@ static void write_merge_heads(struct commit_list *);\n static void prepare_to_commit(struct commit_list *remoteheads)\n {\n \tstruct strbuf msg = STRBUF_INIT;\n-\tconst char *index_file = get_index_file();\n+\tconst char *index_file = repo_get_index_file(the_repository);\n \n \tif (!no_verify) {\n \t\tint invoked_hook;\n@@ -880,8 +882,8 @@ static void prepare_to_commit(struct commit_list *remoteheads)\n \t\tappend_signoff(&msg, ignored_log_message_bytes(msg.buf, msg.len), 0);\n \twrite_merge_heads(remoteheads);\n \twrite_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len);\n-\tif (run_commit_hook(0 < option_edit, get_index_file(), NULL,\n-\t\t\t    \"prepare-commit-msg\",\n+\tif (run_commit_hook(0 < option_edit, repo_get_index_file(the_repository),\n+\t\t\t    NULL, \"prepare-commit-msg\",\n \t\t\t    git_path_merge_msg(the_repository), \"merge\", NULL))\n \t\tabort_commit(remoteheads, NULL);\n \tif (0 < option_edit) {\n@@ -889,7 +891,7 @@ static void prepare_to_commit(struct commit_list *remoteheads)\n \t\t\tabort_commit(remoteheads, NULL);\n \t}\n \n-\tif (!no_verify && run_commit_hook(0 < option_edit, get_index_file(),\n+\tif (!no_verify && run_commit_hook(0 < option_edit, repo_get_index_file(the_repository),\n \t\t\t\t\t  NULL, \"commit-msg\",\n \t\t\t\t\t  git_path_merge_msg(the_repository), NULL))\n \t\tabort_commit(remoteheads, NULL);\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex ad6bcefb770..f2ec9549a47 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -540,8 +540,8 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\t\t\t\t NULL, NULL, NULL))\n \t\treturn error(_(\"could not write index\"));\n \n-\tif (write_index_as_tree(&c_tree, the_repository->index, get_index_file(), 0,\n-\t\t\t\tNULL))\n+\tif (write_index_as_tree(&c_tree, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository), 0, NULL))\n \t\treturn error(_(\"cannot apply a stash in the middle of a merge\"));\n \n \tif (index) {\n@@ -566,7 +566,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\t\tdiscard_index(the_repository->index);\n \t\t\trepo_read_index(the_repository);\n \t\t\tif (write_index_as_tree(&index_tree, the_repository->index,\n-\t\t\t\t\t\tget_index_file(), 0, NULL))\n+\t\t\t\t\t\trepo_get_index_file(the_repository), 0, NULL))\n \t\t\t\treturn error(_(\"could not save index tree\"));\n \n \t\t\treset_head();\n@@ -1406,8 +1406,8 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \n \tstrbuf_addf(&commit_tree_label, \"index on %s\\n\", msg.buf);\n \tcommit_list_insert(head_commit, &parents);\n-\tif (write_index_as_tree(&info->i_tree, the_repository->index, get_index_file(), 0,\n-\t\t\t\tNULL) ||\n+\tif (write_index_as_tree(&info->i_tree, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository), 0, NULL) ||\n \t    commit_tree(commit_tree_label.buf, commit_tree_label.len,\n \t\t\t&info->i_tree, parents, &info->i_commit, NULL, NULL)) {\n \t\tif (!quiet)\n@@ -1905,7 +1905,7 @@ int cmd_stash(int argc, const char **argv, const char *prefix)\n \tprepare_repo_settings(the_repository);\n \tthe_repository->settings.command_requires_full_index = 0;\n \n-\tindex_file = get_index_file();\n+\tindex_file = repo_get_index_file(the_repository);\n \tstrbuf_addf(&stash_index_path, \"%s.stash.%\" PRIuMAX, index_file,\n \t\t    (uintmax_t)pid);\n \ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex 35a1f957adc..86c5d40e400 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -1239,7 +1239,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t\tif (newfd < 0) {\n \t\t\tif (refresh_args.flags & REFRESH_QUIET)\n \t\t\t\texit(128);\n-\t\t\tunable_to_lock_die(get_index_file(), lock_error);\n+\t\t\tunable_to_lock_die(repo_get_index_file(the_repository), lock_error);\n \t\t}\n \t\tif (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))\n \t\t\tdie(\"Unable to write new index file\");\ndiff --git a/builtin/write-tree.c b/builtin/write-tree.c\nindex 8c75b4609b5..9bcc4470ce1 100644\n--- a/builtin/write-tree.c\n+++ b/builtin/write-tree.c\n@@ -6,7 +6,6 @@\n \n #include \"builtin.h\"\n #include \"config.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"hex.h\"\n #include \"tree.h\"\n@@ -44,7 +43,8 @@ int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix)\n \tprepare_repo_settings(the_repository);\n \tthe_repository->settings.command_requires_full_index = 0;\n \n-\tret = write_index_as_tree(&oid, the_repository->index, get_index_file(),\n+\tret = write_index_as_tree(&oid, the_repository->index,\n+\t\t\t\t  repo_get_index_file(the_repository),\n \t\t\t\t  flags, tree_prefix);\n \tswitch (ret) {\n \tcase 0:\ndiff --git a/environment.c b/environment.c\nindex 0a2057399e0..10ef77576c3 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -306,13 +306,6 @@ int odb_pack_keep(const char *name)\n \treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n }\n \n-char *get_index_file(void)\n-{\n-\tif (!the_repository->index_file)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->index_file;\n-}\n-\n char *get_graft_file(struct repository *r)\n {\n \tif (!r->graft_file)\ndiff --git a/environment.h b/environment.h\nindex 91125d82991..ff590cfff73 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-char *get_index_file(void);\n char *get_graft_file(struct repository *r);\n void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\ndiff --git a/repository.c b/repository.c\nindex 914ee25a1f0..a9bbde80b5d 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -112,6 +112,13 @@ const char *repo_get_object_directory(struct repository *repo)\n \treturn repo->objects->odb->path;\n }\n \n+const char *repo_get_index_file(struct repository *repo)\n+{\n+\tif (!repo->index_file)\n+\t\tBUG(\"git environment hasn't been setup\");\n+\treturn repo->index_file;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex 778f1511ab1..15660ac2f19 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -209,6 +209,7 @@ extern struct repository *the_repository;\n const char *repo_get_git_dir(struct repository *repo);\n const char *repo_get_common_dir(struct repository *repo);\n const char *repo_get_object_directory(struct repository *repo);\n+const char *repo_get_index_file(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/wt-status.c b/wt-status.c\nindex b477239039d..b813d3fe1c4 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -16,6 +16,7 @@\n #include \"revision.h\"\n #include \"diffcore.h\"\n #include \"quote.h\"\n+#include \"repository.h\"\n #include \"run-command.h\"\n #include \"strvec.h\"\n #include \"remote.h\"\n@@ -152,7 +153,7 @@ void wt_status_prepare(struct repository *r, struct wt_status *s)\n \t\t\t\t\t\"HEAD\", 0, NULL, NULL);\n \ts->reference = \"HEAD\";\n \ts->fp = stdout;\n-\ts->index_file = get_index_file();\n+\ts->index_file = repo_get_index_file(the_repository);\n \ts->change.strdup_strings = 1;\n \ts->untracked.strdup_strings = 1;\n \ts->ignored.strdup_strings = 1;\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501900","messageId":"1cc727e4763e7989a3a0474faae5fa730539737c.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 05/21] environment: make `get_graft_file()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:08Z","receivedAt":"2024-08-30T09:09:11Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_graft_file()` function retrieves the path to the graft file of\n`the_repository`. Make it accept a `struct repository` such that it can\nwork on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/replace.c | 3 +--\n commit.c          | 4 ++--\n environment.c     | 7 -------\n environment.h     | 2 --\n repository.c      | 7 +++++++\n repository.h      | 1 +\n 6 files changed, 11 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 34cc4672bc1..01161350b1f 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -11,7 +11,6 @@\n #include \"builtin.h\"\n #include \"config.h\"\n #include \"editor.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"hex.h\"\n #include \"refs.h\"\n@@ -514,7 +513,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle)\n \n static int convert_graft_file(int force)\n {\n-\tconst char *graft_file = get_graft_file(the_repository);\n+\tconst char *graft_file = repo_get_graft_file(the_repository);\n \tFILE *fp = fopen_or_warn(graft_file, \"r\");\n \tstruct strbuf buf = STRBUF_INIT, err = STRBUF_INIT;\n \tstruct strvec args = STRVEC_INIT;\ndiff --git a/commit.c b/commit.c\nindex 3238772f521..1f710a92a17 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -292,14 +292,14 @@ static int read_graft_file(struct repository *r, const char *graft_file)\n \n void prepare_commit_graft(struct repository *r)\n {\n-\tchar *graft_file;\n+\tconst char *graft_file;\n \n \tif (r->parsed_objects->commit_graft_prepared)\n \t\treturn;\n \tif (!startup_info->have_repository)\n \t\treturn;\n \n-\tgraft_file = get_graft_file(r);\n+\tgraft_file = repo_get_graft_file(r);\n \tread_graft_file(r, graft_file);\n \t/* make sure shallows are read */\n \tis_repository_shallow(r);\ndiff --git a/environment.c b/environment.c\nindex 10ef77576c3..371f01a705d 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -306,13 +306,6 @@ int odb_pack_keep(const char *name)\n \treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n }\n \n-char *get_graft_file(struct repository *r)\n-{\n-\tif (!r->graft_file)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn r->graft_file;\n-}\n-\n static void set_git_dir_1(const char *path)\n {\n \txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\ndiff --git a/environment.h b/environment.h\nindex ff590cfff73..d12c48481b6 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -1,7 +1,6 @@\n #ifndef ENVIRONMENT_H\n #define ENVIRONMENT_H\n \n-struct repository;\n struct strvec;\n \n /*\n@@ -106,7 +105,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-char *get_graft_file(struct repository *r);\n void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\ndiff --git a/repository.c b/repository.c\nindex a9bbde80b5d..cdefcb4002d 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -119,6 +119,13 @@ const char *repo_get_index_file(struct repository *repo)\n \treturn repo->index_file;\n }\n \n+const char *repo_get_graft_file(struct repository *repo)\n+{\n+\tif (!repo->graft_file)\n+\t\tBUG(\"git environment hasn't been setup\");\n+\treturn repo->graft_file;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex 15660ac2f19..ad0f984b444 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -210,6 +210,7 @@ const char *repo_get_git_dir(struct repository *repo);\n const char *repo_get_common_dir(struct repository *repo);\n const char *repo_get_object_directory(struct repository *repo);\n const char *repo_get_index_file(struct repository *repo);\n+const char *repo_get_graft_file(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501901","messageId":"22e9dcb28a981eaa1a37a8b41e8d061347ed6c2e.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 06/21] environment: make `get_git_work_tree()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:11Z","receivedAt":"2024-08-30T09:09:15Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_git_work_tree()` function retrieves the path of the work tree\nof `the_repository`. Make it accept a `struct repository` such that it\ncan work on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/blame.c             |  2 +-\n builtin/difftool.c          |  4 ++--\n builtin/fsmonitor--daemon.c |  4 ++--\n builtin/init-db.c           |  4 ++--\n builtin/reset.c             |  5 +++--\n builtin/rev-parse.c         |  4 ++--\n builtin/stash.c             |  2 +-\n builtin/submodule--helper.c |  2 +-\n builtin/update-index.c      |  2 +-\n dir.c                       |  3 ++-\n environment.c               |  7 +------\n environment.h               |  1 -\n fsmonitor.c                 |  3 ++-\n pathspec.c                  |  2 +-\n repository.c                |  5 +++++\n repository.h                |  1 +\n setup.c                     | 16 ++++++++--------\n trace.c                     |  3 +--\n 18 files changed, 36 insertions(+), 34 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 35e975fb132..1ffdda50904 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -1081,7 +1081,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t\tpath = add_prefix(prefix, argv[1]);\n \t\t\targv[1] = argv[2];\n \t\t} else {\t/* (2a) */\n-\t\t\tif (argc == 2 && is_a_rev(argv[1]) && !get_git_work_tree())\n+\t\t\tif (argc == 2 && is_a_rev(argv[1]) && !repo_get_work_tree(the_repository))\n \t\t\t\tdie(\"missing <path> to blame\");\n \t\t\tpath = add_prefix(prefix, argv[argc - 1]);\n \t\t}\ndiff --git a/builtin/difftool.c b/builtin/difftool.c\nindex 8c59411e6e0..7f2cbd797ad 100644\n--- a/builtin/difftool.c\n+++ b/builtin/difftool.c\n@@ -378,7 +378,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,\n \tstruct hashmap wt_modified, tmp_modified;\n \tint indices_loaded = 0;\n \n-\tworkdir = get_git_work_tree();\n+\tworkdir = repo_get_work_tree(the_repository);\n \n \t/* Setup temp directories */\n \ttmp = getenv(\"TMPDIR\");\n@@ -739,7 +739,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)\n \tif (!no_index){\n \t\tsetup_work_tree();\n \t\tsetenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1);\n-\t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);\n+\t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(the_repository)), 1);\n \t} else if (dir_diff)\n \t\tdie(_(\"options '%s' and '%s' cannot be used together\"), \"--dir-diff\", \"--no-index\");\n \ndiff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c\nindex c54e736716a..25451d999e9 100644\n--- a/builtin/fsmonitor--daemon.c\n+++ b/builtin/fsmonitor--daemon.c\n@@ -2,7 +2,6 @@\n #include \"abspath.h\"\n #include \"config.h\"\n #include \"dir.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"parse-options.h\"\n #include \"fsmonitor-ll.h\"\n@@ -1291,7 +1290,8 @@ static int fsmonitor_run_daemon(void)\n \n \t/* Prepare to (recursively) watch the <worktree-root> directory. */\n \tstrbuf_init(&state.path_worktree_watch, 0);\n-\tstrbuf_addstr(&state.path_worktree_watch, absolute_path(get_git_work_tree()));\n+\tstrbuf_addstr(&state.path_worktree_watch,\n+\t\t      absolute_path(repo_get_work_tree(the_repository)));\n \tstate.nr_paths_watching = 1;\n \n \tstrbuf_init(&state.alias.alias, 0);\ndiff --git a/builtin/init-db.c b/builtin/init-db.c\nindex 582dcf20f86..fb04962dcea 100644\n--- a/builtin/init-db.c\n+++ b/builtin/init-db.c\n@@ -231,9 +231,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)\n \t\t\tset_git_work_tree(work_tree);\n \t\telse\n \t\t\tset_git_work_tree(git_work_tree_cfg);\n-\t\tif (access(get_git_work_tree(), X_OK))\n+\t\tif (access(repo_get_work_tree(the_repository), X_OK))\n \t\t\tdie_errno (_(\"Cannot access work tree '%s'\"),\n-\t\t\t\t   get_git_work_tree());\n+\t\t\t\t   repo_get_work_tree(the_repository));\n \t}\n \telse {\n \t\tif (real_git_dir)\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 5f941fb3a29..86b2f07d660 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -26,6 +26,7 @@\n #include \"object-name.h\"\n #include \"parse-options.h\"\n #include \"path.h\"\n+#include \"repository.h\"\n #include \"unpack-trees.h\"\n #include \"cache-tree.h\"\n #include \"setup.h\"\n@@ -441,7 +442,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \telse\n \t\ttrace2_cmd_mode(reset_type_names[reset_type]);\n \n-\tif (reset_type != SOFT && (reset_type != MIXED || get_git_work_tree()))\n+\tif (reset_type != SOFT && (reset_type != MIXED || repo_get_work_tree(the_repository)))\n \t\tsetup_work_tree();\n \n \tif (reset_type == MIXED && is_bare_repository())\n@@ -474,7 +475,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\t\t\tgoto cleanup;\n \t\t\t}\n \t\t\tthe_repository->index->updated_skipworktree = 1;\n-\t\t\tif (!no_refresh && get_git_work_tree()) {\n+\t\t\tif (!no_refresh && repo_get_work_tree(the_repository)) {\n \t\t\t\tuint64_t t_begin, t_delta_in_ms;\n \n \t\t\t\tt_begin = getnanotime();\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex cd85fe57bb0..a5108266daf 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -967,7 +967,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--show-toplevel\")) {\n-\t\t\t\tconst char *work_tree = get_git_work_tree();\n+\t\t\t\tconst char *work_tree = repo_get_work_tree(the_repository);\n \t\t\t\tif (work_tree)\n \t\t\t\t\tprint_path(work_tree, prefix, format, DEFAULT_UNMODIFIED);\n \t\t\t\telse\n@@ -992,7 +992,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tconst char *pfx = prefix;\n \t\t\t\tif (!is_inside_work_tree()) {\n \t\t\t\t\tconst char *work_tree =\n-\t\t\t\t\t\tget_git_work_tree();\n+\t\t\t\t\t\trepo_get_work_tree(the_repository);\n \t\t\t\t\tif (work_tree)\n \t\t\t\t\t\tprintf(\"%s\\n\", work_tree);\n \t\t\t\t\tcontinue;\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex f2ec9549a47..354641b3f10 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -641,7 +641,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\tcp.git_cmd = 1;\n \t\tcp.dir = prefix;\n \t\tstrvec_pushf(&cp.env, GIT_WORK_TREE_ENVIRONMENT\"=%s\",\n-\t\t\t     absolute_path(get_git_work_tree()));\n+\t\t\t     absolute_path(repo_get_work_tree(the_repository)));\n \t\tstrvec_pushf(&cp.env, GIT_DIR_ENVIRONMENT\"=%s\",\n \t\t\t     absolute_path(repo_get_git_dir(the_repository)));\n \t\tstrvec_push(&cp.args, \"status\");\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 85fb23dee84..865b454d693 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1709,7 +1709,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,\n \t\texit(128);\n \n \tif (!is_absolute_path(clone_data->path))\n-\t\tclone_data_path = to_free = xstrfmt(\"%s/%s\", get_git_work_tree(),\n+\t\tclone_data_path = to_free = xstrfmt(\"%s/%s\", repo_get_work_tree(the_repository),\n \t\t\t\t\t\t    clone_data->path);\n \n \tif (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)\ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex 86c5d40e400..8baa2256194 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -1194,7 +1194,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t\t\t\t  \"remove or change it, if you really want to \"\n \t\t\t\t  \"enable the untracked cache\"));\n \t\tadd_untracked_cache(the_repository->index);\n-\t\treport(_(\"Untracked cache enabled for '%s'\"), get_git_work_tree());\n+\t\treport(_(\"Untracked cache enabled for '%s'\"), repo_get_work_tree(the_repository));\n \t\tbreak;\n \tdefault:\n \t\tBUG(\"bad untracked_cache value: %d\", untracked_cache);\ndiff --git a/dir.c b/dir.c\nindex 5a23376bdae..c43b5e30813 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -20,6 +20,7 @@\n #include \"object-store-ll.h\"\n #include \"path.h\"\n #include \"refs.h\"\n+#include \"repository.h\"\n #include \"wildmatch.h\"\n #include \"pathspec.h\"\n #include \"utf8.h\"\n@@ -2838,7 +2839,7 @@ static const char *get_ident_string(void)\n \t\treturn sb.buf;\n \tif (uname(&uts) < 0)\n \t\tdie_errno(_(\"failed to get kernel name and information\"));\n-\tstrbuf_addf(&sb, \"Location %s, system %s\", get_git_work_tree(),\n+\tstrbuf_addf(&sb, \"Location %s, system %s\", repo_get_work_tree(the_repository),\n \t\t    uts.sysname);\n \treturn sb.buf;\n }\ndiff --git a/environment.c b/environment.c\nindex 371f01a705d..4d0637b3822 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -219,7 +219,7 @@ void setup_git_env(const char *git_dir)\n int is_bare_repository(void)\n {\n \t/* if core.bare is not 'false', let's see if there is a work tree */\n-\treturn is_bare_repository_cfg && !get_git_work_tree();\n+\treturn is_bare_repository_cfg && !repo_get_work_tree(the_repository);\n }\n \n int have_git_dir(void)\n@@ -268,11 +268,6 @@ void set_git_work_tree(const char *new_work_tree)\n \trepo_set_worktree(the_repository, new_work_tree);\n }\n \n-const char *get_git_work_tree(void)\n-{\n-\treturn the_repository->worktree;\n-}\n-\n int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n {\n \tint fd;\ndiff --git a/environment.h b/environment.h\nindex d12c48481b6..52e1803aba6 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -108,7 +108,6 @@ extern char *git_work_tree_cfg;\n void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\n-const char *get_git_work_tree(void);\n void set_git_work_tree(const char *tree);\n \n #define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\ndiff --git a/fsmonitor.c b/fsmonitor.c\nindex 28130f748f7..237ca59d004 100644\n--- a/fsmonitor.c\n+++ b/fsmonitor.c\n@@ -8,6 +8,7 @@\n #include \"fsmonitor.h\"\n #include \"fsmonitor-ipc.h\"\n #include \"name-hash.h\"\n+#include \"repository.h\"\n #include \"run-command.h\"\n #include \"strbuf.h\"\n #include \"trace2.h\"\n@@ -169,7 +170,7 @@ static int query_fsmonitor_hook(struct repository *r,\n \tstrvec_pushf(&cp.args, \"%d\", version);\n \tstrvec_pushf(&cp.args, \"%s\", last_update);\n \tcp.use_shell = 1;\n-\tcp.dir = get_git_work_tree();\n+\tcp.dir = repo_get_work_tree(the_repository);\n \n \ttrace2_region_enter(\"fsm_hook\", \"query\", NULL);\n \ndiff --git a/pathspec.c b/pathspec.c\nindex 416fe1e3dcc..0fc6f84a6e6 100644\n--- a/pathspec.c\n+++ b/pathspec.c\n@@ -495,7 +495,7 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,\n \t\t\tif (!have_git_dir())\n \t\t\t\tdie(_(\"'%s' is outside the directory tree\"),\n \t\t\t\t    copyfrom);\n-\t\t\thint_path = get_git_work_tree();\n+\t\t\thint_path = repo_get_work_tree(the_repository);\n \t\t\tif (!hint_path)\n \t\t\t\thint_path = repo_get_git_dir(the_repository);\n \t\t\tdie(_(\"%s: '%s' is outside repository at '%s'\"), elt,\ndiff --git a/repository.c b/repository.c\nindex cdefcb4002d..92238da3d9e 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -126,6 +126,11 @@ const char *repo_get_graft_file(struct repository *repo)\n \treturn repo->graft_file;\n }\n \n+const char *repo_get_work_tree(struct repository *repo)\n+{\n+\treturn repo->worktree;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex ad0f984b444..c603e969ae7 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -211,6 +211,7 @@ const char *repo_get_common_dir(struct repository *repo);\n const char *repo_get_object_directory(struct repository *repo);\n const char *repo_get_index_file(struct repository *repo);\n const char *repo_get_graft_file(struct repository *repo);\n+const char *repo_get_work_tree(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/setup.c b/setup.c\nindex 1ebcab625fe..1bfec288ab6 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -51,7 +51,7 @@ static int abspath_part_inside_repo(char *path)\n \tsize_t wtlen;\n \tchar *path0;\n \tint off;\n-\tconst char *work_tree = precompose_string_if_needed(get_git_work_tree());\n+\tconst char *work_tree = precompose_string_if_needed(repo_get_work_tree(the_repository));\n \tstruct strbuf realpath = STRBUF_INIT;\n \n \tif (!work_tree)\n@@ -147,7 +147,7 @@ char *prefix_path(const char *prefix, int len, const char *path)\n {\n \tchar *r = prefix_path_gently(prefix, len, NULL, path);\n \tif (!r) {\n-\t\tconst char *hint_path = get_git_work_tree();\n+\t\tconst char *hint_path = repo_get_work_tree(the_repository);\n \t\tif (!hint_path)\n \t\t\thint_path = repo_get_git_dir(the_repository);\n \t\tdie(_(\"'%s' is outside repository at '%s'\"), path,\n@@ -475,7 +475,7 @@ int is_inside_git_dir(void)\n int is_inside_work_tree(void)\n {\n \tif (inside_work_tree < 0)\n-\t\tinside_work_tree = is_inside_dir(get_git_work_tree());\n+\t\tinside_work_tree = is_inside_dir(repo_get_work_tree(the_repository));\n \treturn inside_work_tree;\n }\n \n@@ -490,7 +490,7 @@ void setup_work_tree(void)\n \tif (work_tree_config_is_bogus)\n \t\tdie(_(\"unable to set up work tree using invalid config\"));\n \n-\twork_tree = get_git_work_tree();\n+\twork_tree = repo_get_work_tree(the_repository);\n \tif (!work_tree || chdir_notify(work_tree))\n \t\tdie(_(\"this operation must be run in a work tree\"));\n \n@@ -547,7 +547,7 @@ static void setup_original_cwd(void)\n \t * Get our worktree; we only protect the current working directory\n \t * if it's in the worktree.\n \t */\n-\tworktree = get_git_work_tree();\n+\tworktree = repo_get_work_tree(the_repository);\n \tif (!worktree)\n \t\tgoto no_prevention_needed;\n \n@@ -1062,9 +1062,9 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,\n \t\tset_git_work_tree(\".\");\n \n \t/* set_git_work_tree() must have been called by now */\n-\tworktree = get_git_work_tree();\n+\tworktree = repo_get_work_tree(the_repository);\n \n-\t/* both get_git_work_tree() and cwd are already normalized */\n+\t/* both repo_get_work_tree() and cwd are already normalized */\n \tif (!strcmp(cwd->buf, worktree)) { /* cwd == worktree */\n \t\tset_git_dir(gitdirenv, 0);\n \t\tfree(gitfile);\n@@ -2192,7 +2192,7 @@ static int create_default_files(const char *template_path,\n \tchar *path;\n \tint reinit;\n \tint filemode;\n-\tconst char *work_tree = get_git_work_tree();\n+\tconst char *work_tree = repo_get_work_tree(the_repository);\n \n \t/*\n \t * First copy the templates -- we might have the default\ndiff --git a/trace.c b/trace.c\nindex e6728c301f3..d8c43773ae8 100644\n--- a/trace.c\n+++ b/trace.c\n@@ -25,7 +25,6 @@\n \n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n-#include \"environment.h\"\n #include \"repository.h\"\n #include \"quote.h\"\n #include \"setup.h\"\n@@ -308,7 +307,7 @@ void trace_repo_setup(void)\n \n \tcwd = xgetcwd();\n \n-\tif (!(git_work_tree = get_git_work_tree()))\n+\tif (!(git_work_tree = repo_get_work_tree(the_repository)))\n \t\tgit_work_tree = \"(null)\";\n \n \tif (!startup_info->prefix)\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501902","messageId":"ec4804a99bf70f9a97d1faea60bd55aaa97d1b80.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 07/21] config: document `read_early_config()` and `read_very_early_config()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:14Z","receivedAt":"2024-08-30T09:09:18Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"It's not clear what `read_early_config()` and `read_very_early_config()`\ndo differently compared to `repo_read_config()` from just looking at\ntheir names. Document both of these in the header file to clarify their\nintent.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c |  4 ----\n config.h | 11 +++++++++++\n 2 files changed, 11 insertions(+), 4 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 0b87f0f9050..a8357ea9544 100644\n--- a/config.c\n+++ b/config.c\n@@ -2234,10 +2234,6 @@ void read_early_config(config_fn_t cb, void *data)\n \tstrbuf_release(&gitdir);\n }\n \n-/*\n- * Read config but only enumerate system and global settings.\n- * Omit any repo-local, worktree-local, or command-line settings.\n- */\n void read_very_early_config(config_fn_t cb, void *data)\n {\n \tstruct config_options opts = { 0 };\ndiff --git a/config.h b/config.h\nindex d0497157c52..f5fa833cb98 100644\n--- a/config.h\n+++ b/config.h\n@@ -192,7 +192,18 @@ int git_config_from_blob_oid(config_fn_t fn, const char *name,\n void git_config_push_parameter(const char *text);\n void git_config_push_env(const char *spec);\n int git_config_from_parameters(config_fn_t fn, void *data);\n+\n+/*\n+ * Read config when the Git directory has not yet been set up. In case\n+ * `the_repository` has not yet been set up, try to discover the Git\n+ * directory to read the configuration from.\n+ */\n void read_early_config(config_fn_t cb, void *data);\n+\n+/*\n+ * Read config but only enumerate system and global settings.\n+ * Omit any repo-local, worktree-local, or command-line settings.\n+ */\n void read_very_early_config(config_fn_t cb, void *data);\n \n /**\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501903","messageId":"b8aa5dcc0b67e3957dc65f38b7dc02a97cc096a7.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 08/21] config: make dependency on repo in `read_early_config()` explicit","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:18Z","receivedAt":"2024-08-30T09:09:22Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `read_early_config()` function can be used to read configuration\nwhere a repository has not yet been set up. As such, it is optional\nwhether or not `the_repository` has already been initialized. If it was\ninitialized we use its commondir and gitdir. If not, the function will\ntry to detect the Git directories by itself and, if found, also parse\ntheir config files.\n\nThis means that we implicitly rely on `the_repository`. Make this\ndependency explicit by passing a `struct repository`. This allows us to\nagain drop the `USE_THE_REPOSITORY_VARIABLE` define in \"config.c\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n alias.c                |  6 ++++--\n config.c               | 10 ++++------\n config.h               |  2 +-\n help.c                 |  2 +-\n pager.c                |  7 +++++--\n t/helper/test-config.c |  3 ++-\n trace2/tr2_cfg.c       |  4 +++-\n 7 files changed, 20 insertions(+), 14 deletions(-)\n\ndiff --git a/alias.c b/alias.c\nindex 4daafd9bdae..1a1a141a0ae 100644\n--- a/alias.c\n+++ b/alias.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"alias.h\"\n #include \"config.h\"\n@@ -37,7 +39,7 @@ char *alias_lookup(const char *alias)\n {\n \tstruct config_alias_data data = { alias, NULL };\n \n-\tread_early_config(config_alias_cb, &data);\n+\tread_early_config(the_repository, config_alias_cb, &data);\n \n \treturn data.v;\n }\n@@ -46,7 +48,7 @@ void list_aliases(struct string_list *list)\n {\n \tstruct config_alias_data data = { NULL, NULL, list };\n \n-\tread_early_config(config_alias_cb, &data);\n+\tread_early_config(the_repository, config_alias_cb, &data);\n }\n \n void quote_cmdline(struct strbuf *buf, const char **argv)\ndiff --git a/config.c b/config.c\nindex a8357ea9544..043e1c8a078 100644\n--- a/config.c\n+++ b/config.c\n@@ -6,8 +6,6 @@\n  *\n  */\n \n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"advice.h\"\n@@ -2204,7 +2202,7 @@ static void configset_iter(struct config_set *set, config_fn_t fn, void *data)\n \t}\n }\n \n-void read_early_config(config_fn_t cb, void *data)\n+void read_early_config(struct repository *repo, config_fn_t cb, void *data)\n {\n \tstruct config_options opts = {0};\n \tstruct strbuf commondir = STRBUF_INIT;\n@@ -2212,9 +2210,9 @@ void read_early_config(config_fn_t cb, void *data)\n \n \topts.respect_includes = 1;\n \n-\tif (have_git_dir()) {\n-\t\topts.commondir = repo_get_common_dir(the_repository);\n-\t\topts.git_dir = repo_get_git_dir(the_repository);\n+\tif (repo && repo->gitdir) {\n+\t\topts.commondir = repo_get_common_dir(repo);\n+\t\topts.git_dir = repo_get_git_dir(repo);\n \t/*\n \t * When setup_git_directory() was not yet asked to discover the\n \t * GIT_DIR, we ask discover_git_directory() to figure out whether there\ndiff --git a/config.h b/config.h\nindex f5fa833cb98..5c730c4f899 100644\n--- a/config.h\n+++ b/config.h\n@@ -198,7 +198,7 @@ int git_config_from_parameters(config_fn_t fn, void *data);\n  * `the_repository` has not yet been set up, try to discover the Git\n  * directory to read the configuration from.\n  */\n-void read_early_config(config_fn_t cb, void *data);\n+void read_early_config(struct repository *repo, config_fn_t cb, void *data);\n \n /*\n  * Read config but only enumerate system and global settings.\ndiff --git a/help.c b/help.c\nindex c03863f2265..413c93edaea 100644\n--- a/help.c\n+++ b/help.c\n@@ -618,7 +618,7 @@ const char *help_unknown_cmd(const char *cmd)\n \tmemset(&other_cmds, 0, sizeof(other_cmds));\n \tmemset(&aliases, 0, sizeof(aliases));\n \n-\tread_early_config(git_unknown_cmd_config, NULL);\n+\tread_early_config(the_repository, git_unknown_cmd_config, NULL);\n \n \t/*\n \t * Disable autocorrection prompt in a non-interactive session\ndiff --git a/pager.c b/pager.c\nindex 9c24ce62633..40b664f893c 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"config.h\"\n #include \"editor.h\"\n@@ -92,7 +94,8 @@ const char *git_pager(int stdout_is_tty)\n \tpager = getenv(\"GIT_PAGER\");\n \tif (!pager) {\n \t\tif (!pager_program)\n-\t\t\tread_early_config(core_pager_config, NULL);\n+\t\t\tread_early_config(the_repository,\n+\t\t\t\t\t  core_pager_config, NULL);\n \t\tpager = pager_program;\n \t}\n \tif (!pager)\n@@ -298,7 +301,7 @@ int check_pager_config(const char *cmd)\n \tdata.want = -1;\n \tdata.value = NULL;\n \n-\tread_early_config(pager_command_config, &data);\n+\tread_early_config(the_repository, pager_command_config, &data);\n \n \tif (data.value)\n \t\tpager_program = data.value;\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex e193079ed54..33247f0e92e 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -96,7 +96,8 @@ int cmd__config(int argc, const char **argv)\n \tstruct config_set cs;\n \n \tif (argc == 3 && !strcmp(argv[1], \"read_early_config\")) {\n-\t\tread_early_config(early_config_cb, (void *)argv[2]);\n+\t\tread_early_config(the_repository, early_config_cb,\n+\t\t\t\t  (void *)argv[2]);\n \t\treturn 0;\n \t}\n \ndiff --git a/trace2/tr2_cfg.c b/trace2/tr2_cfg.c\nindex d96d908bb9d..22a99a0682a 100644\n--- a/trace2/tr2_cfg.c\n+++ b/trace2/tr2_cfg.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"config.h\"\n #include \"strbuf.h\"\n@@ -124,7 +126,7 @@ void tr2_cfg_list_config_fl(const char *file, int line)\n \tstruct tr2_cfg_data data = { file, line };\n \n \tif (tr2_cfg_load_patterns() > 0)\n-\t\tread_early_config(tr2_cfg_cb, &data);\n+\t\tread_early_config(the_repository, tr2_cfg_cb, &data);\n }\n \n void tr2_list_env_vars_fl(const char *file, int line)\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501904","messageId":"ac2cc4e03719ecf6d6a2eb4aacb8a162429addb0.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 09/21] environment: move `odb_mkstemp()` into object layer","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:20Z","receivedAt":"2024-08-30T09:09:24Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `odb_mkstemp()` function is quite clearly tied to the object store,\nbut regardless of that it is located in \"environment.c\". Move it over,\nwhich also helps to get rid of dependencies on `the_repository` in the\nenvironment subsystem.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n bundle-uri.c      |  2 +-\n environment.c     | 34 ----------------------------------\n environment.h     | 15 ---------------\n object-file.c     | 33 +++++++++++++++++++++++++++++++++\n object-store-ll.h | 15 +++++++++++++++\n 5 files changed, 49 insertions(+), 50 deletions(-)\n\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 1e0ee156ba3..eb8eca078bb 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -4,7 +4,6 @@\n #include \"bundle-uri.h\"\n #include \"bundle.h\"\n #include \"copy.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"refs.h\"\n #include \"run-command.h\"\n@@ -13,6 +12,7 @@\n #include \"config.h\"\n #include \"fetch-pack.h\"\n #include \"remote.h\"\n+#include \"object-store-ll.h\"\n \n static struct {\n \tenum bundle_list_heuristic heuristic;\ndiff --git a/environment.c b/environment.c\nindex 4d0637b3822..f337efd1dd5 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -23,7 +23,6 @@\n #include \"commit.h\"\n #include \"strvec.h\"\n #include \"object-file.h\"\n-#include \"object-store-ll.h\"\n #include \"path.h\"\n #include \"replace-object.h\"\n #include \"tmp-objdir.h\"\n@@ -268,39 +267,6 @@ void set_git_work_tree(const char *new_work_tree)\n \trepo_set_worktree(the_repository, new_work_tree);\n }\n \n-int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n-{\n-\tint fd;\n-\t/*\n-\t * we let the umask do its job, don't try to be more\n-\t * restrictive except to remove write permission.\n-\t */\n-\tint mode = 0444;\n-\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n-\tfd = git_mkstemp_mode(temp_filename->buf, mode);\n-\tif (0 <= fd)\n-\t\treturn fd;\n-\n-\t/* slow path */\n-\t/* some mkstemp implementations erase temp_filename on failure */\n-\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n-\tsafe_create_leading_directories(temp_filename->buf);\n-\treturn xmkstemp_mode(temp_filename->buf, mode);\n-}\n-\n-int odb_pack_keep(const char *name)\n-{\n-\tint fd;\n-\n-\tfd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n-\tif (0 <= fd)\n-\t\treturn fd;\n-\n-\t/* slow path */\n-\tsafe_create_leading_directories_const(name);\n-\treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n-}\n-\n static void set_git_dir_1(const char *path)\n {\n \txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\ndiff --git a/environment.h b/environment.h\nindex 52e1803aba6..682d4f2e3b5 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -200,21 +200,6 @@ extern int grafts_keep_true_parents;\n \n extern int repository_format_precious_objects;\n \n-/*\n- * Create a temporary file rooted in the object database directory, or\n- * die on failure. The filename is taken from \"pattern\", which should have the\n- * usual \"XXXXXX\" trailer, and the resulting filename is written into the\n- * \"template\" buffer. Returns the open descriptor.\n- */\n-int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);\n-\n-/*\n- * Create a pack .keep file named \"name\" (which should generally be the output\n- * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on\n- * error.\n- */\n-int odb_pack_keep(const char *name);\n-\n const char *get_log_output_encoding(void);\n const char *get_commit_output_encoding(void);\n \ndiff --git a/object-file.c b/object-file.c\nindex fa4121b98ad..968da27cd41 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -419,6 +419,39 @@ enum scld_error safe_create_leading_directories_const(const char *path)\n \treturn result;\n }\n \n+int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n+{\n+\tint fd;\n+\t/*\n+\t * we let the umask do its job, don't try to be more\n+\t * restrictive except to remove write permission.\n+\t */\n+\tint mode = 0444;\n+\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n+\tfd = git_mkstemp_mode(temp_filename->buf, mode);\n+\tif (0 <= fd)\n+\t\treturn fd;\n+\n+\t/* slow path */\n+\t/* some mkstemp implementations erase temp_filename on failure */\n+\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n+\tsafe_create_leading_directories(temp_filename->buf);\n+\treturn xmkstemp_mode(temp_filename->buf, mode);\n+}\n+\n+int odb_pack_keep(const char *name)\n+{\n+\tint fd;\n+\n+\tfd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n+\tif (0 <= fd)\n+\t\treturn fd;\n+\n+\t/* slow path */\n+\tsafe_create_leading_directories_const(name);\n+\treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n+}\n+\n static void fill_loose_path(struct strbuf *buf, const struct object_id *oid)\n {\n \tint i;\ndiff --git a/object-store-ll.h b/object-store-ll.h\nindex c5f2bb2fc2f..53b8e693b1b 100644\n--- a/object-store-ll.h\n+++ b/object-store-ll.h\n@@ -231,6 +231,21 @@ struct raw_object_store {\n struct raw_object_store *raw_object_store_new(void);\n void raw_object_store_clear(struct raw_object_store *o);\n \n+/*\n+ * Create a temporary file rooted in the object database directory, or\n+ * die on failure. The filename is taken from \"pattern\", which should have the\n+ * usual \"XXXXXX\" trailer, and the resulting filename is written into the\n+ * \"template\" buffer. Returns the open descriptor.\n+ */\n+int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);\n+\n+/*\n+ * Create a pack .keep file named \"name\" (which should generally be the output\n+ * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on\n+ * error.\n+ */\n+int odb_pack_keep(const char *name);\n+\n /*\n  * Put in `buf` the name of the file in the local object database that\n  * would be used to store a loose object with the specified oid.\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501905","messageId":"f0d3794dfc44cd4393fd79fab9f60b73cf33db89.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 10/21] environment: make `get_git_namespace()` self-contained","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:23Z","receivedAt":"2024-08-30T09:09:26Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The logic to set up and retrieve `git_namespace` is distributed across\ndifferent functions which communicate with each other via a global\nenvironment variable. This is rather pointless though, as the value is\nalways derived from an environment variable, and this environment\nvariable does not change after we have parsed global options.\n\nConvert the function to be fully self-contained such that it lazily\npopulates once called.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n environment.c | 57 ++++++++++++++++++++++++++-------------------------\n 1 file changed, 29 insertions(+), 28 deletions(-)\n\ndiff --git a/environment.c b/environment.c\nindex f337efd1dd5..49844418419 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -122,8 +122,6 @@ int core_preload_index = 1;\n /* This is set by setup_git_dir_gently() and/or git_default_config() */\n char *git_work_tree_cfg;\n \n-static char *git_namespace;\n-\n /*\n  * Repository-local GIT_* environment variables; see environment.h for details.\n  */\n@@ -146,27 +144,6 @@ const char * const local_repo_env[] = {\n \tNULL\n };\n \n-static char *expand_namespace(const char *raw_namespace)\n-{\n-\tstruct strbuf buf = STRBUF_INIT;\n-\tstruct strbuf **components, **c;\n-\n-\tif (!raw_namespace || !*raw_namespace)\n-\t\treturn xstrdup(\"\");\n-\n-\tstrbuf_addstr(&buf, raw_namespace);\n-\tcomponents = strbuf_split(&buf, '/');\n-\tstrbuf_reset(&buf);\n-\tfor (c = components; *c; c++)\n-\t\tif (strcmp((*c)->buf, \"/\") != 0)\n-\t\t\tstrbuf_addf(&buf, \"refs/namespaces/%s\", (*c)->buf);\n-\tstrbuf_list_free(components);\n-\tif (check_refname_format(buf.buf, 0))\n-\t\tdie(_(\"bad git namespace path \\\"%s\\\"\"), raw_namespace);\n-\tstrbuf_addch(&buf, '/');\n-\treturn strbuf_detach(&buf, NULL);\n-}\n-\n const char *getenv_safe(struct strvec *argv, const char *name)\n {\n \tconst char *value = getenv(name);\n@@ -205,8 +182,6 @@ void setup_git_env(const char *git_dir)\n \t\t\t\t\t\t\t  : \"refs/replace/\");\n \tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\n \n-\tfree(git_namespace);\n-\tgit_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));\n \tshallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);\n \tif (shallow_file)\n \t\tset_alternate_shallow_file(the_repository, shallow_file, 0);\n@@ -229,9 +204,35 @@ int have_git_dir(void)\n \n const char *get_git_namespace(void)\n {\n-\tif (!git_namespace)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn git_namespace;\n+\tstatic const char *namespace;\n+\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct strbuf **components, **c;\n+\tconst char *raw_namespace;\n+\n+\tif (namespace)\n+\t\treturn namespace;\n+\n+\traw_namespace = getenv(GIT_NAMESPACE_ENVIRONMENT);\n+\tif (!raw_namespace || !*raw_namespace) {\n+\t\tnamespace = \"\";\n+\t\treturn namespace;\n+\t}\n+\n+\tstrbuf_addstr(&buf, raw_namespace);\n+\tcomponents = strbuf_split(&buf, '/');\n+\tstrbuf_reset(&buf);\n+\tfor (c = components; *c; c++)\n+\t\tif (strcmp((*c)->buf, \"/\") != 0)\n+\t\t\tstrbuf_addf(&buf, \"refs/namespaces/%s\", (*c)->buf);\n+\tstrbuf_list_free(components);\n+\tif (check_refname_format(buf.buf, 0))\n+\t\tdie(_(\"bad git namespace path \\\"%s\\\"\"), raw_namespace);\n+\tstrbuf_addch(&buf, '/');\n+\n+\tnamespace = strbuf_detach(&buf, NULL);\n+\n+\treturn namespace;\n }\n \n const char *strip_namespace(const char *namespaced_ref)\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501906","messageId":"9e0e2528b9434fc10d5f4af92e1cc1667959cb42.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 11/21] environment: move `set_git_dir()` and related into setup layer","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:26Z","receivedAt":"2024-08-30T09:09:29Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The functions `set_git_dir()` and friends are used to set up\nrepositories. As such, they are quite clearly part of the setup\nsubsystem, but still live in \"environment.c\". Move them over, which also\nhelps to get rid of dependencies on `the_repository` in the environment\nsubsystem.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n environment.c | 105 -------------------------------------------------\n environment.h |   2 -\n setup.c       | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++\n setup.h       |   3 ++\n 4 files changed, 109 insertions(+), 107 deletions(-)\n\ndiff --git a/environment.c b/environment.c\nindex 49844418419..64ae13ef240 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -22,14 +22,9 @@\n #include \"fmt-merge-msg.h\"\n #include \"commit.h\"\n #include \"strvec.h\"\n-#include \"object-file.h\"\n #include \"path.h\"\n-#include \"replace-object.h\"\n-#include \"tmp-objdir.h\"\n #include \"chdir-notify.h\"\n #include \"setup.h\"\n-#include \"shallow.h\"\n-#include \"trace.h\"\n #include \"write-or-die.h\"\n \n int trust_executable_bit = 1;\n@@ -155,41 +150,6 @@ const char *getenv_safe(struct strvec *argv, const char *name)\n \treturn argv->v[argv->nr - 1];\n }\n \n-void setup_git_env(const char *git_dir)\n-{\n-\tchar *git_replace_ref_base;\n-\tconst char *shallow_file;\n-\tconst char *replace_ref_base;\n-\tstruct set_gitdir_args args = { NULL };\n-\tstruct strvec to_free = STRVEC_INIT;\n-\n-\targs.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);\n-\targs.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);\n-\targs.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);\n-\targs.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);\n-\targs.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);\n-\tif (getenv(GIT_QUARANTINE_ENVIRONMENT)) {\n-\t\targs.disable_ref_updates = 1;\n-\t}\n-\n-\trepo_set_gitdir(the_repository, git_dir, &args);\n-\tstrvec_clear(&to_free);\n-\n-\tif (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))\n-\t\tdisable_replace_refs();\n-\treplace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);\n-\tgit_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base\n-\t\t\t\t\t\t\t  : \"refs/replace/\");\n-\tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\n-\n-\tshallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);\n-\tif (shallow_file)\n-\t\tset_alternate_shallow_file(the_repository, shallow_file, 0);\n-\n-\tif (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))\n-\t\tfetch_if_missing = 0;\n-}\n-\n int is_bare_repository(void)\n {\n \t/* if core.bare is not 'false', let's see if there is a work tree */\n@@ -243,71 +203,6 @@ const char *strip_namespace(const char *namespaced_ref)\n \treturn NULL;\n }\n \n-static int git_work_tree_initialized;\n-\n-/*\n- * Note.  This works only before you used a work tree.  This was added\n- * primarily to support git-clone to work in a new repository it just\n- * created, and is not meant to flip between different work trees.\n- */\n-void set_git_work_tree(const char *new_work_tree)\n-{\n-\tif (git_work_tree_initialized) {\n-\t\tstruct strbuf realpath = STRBUF_INIT;\n-\n-\t\tstrbuf_realpath(&realpath, new_work_tree, 1);\n-\t\tnew_work_tree = realpath.buf;\n-\t\tif (strcmp(new_work_tree, the_repository->worktree))\n-\t\t\tdie(\"internal error: work tree has already been set\\n\"\n-\t\t\t    \"Current worktree: %s\\nNew worktree: %s\",\n-\t\t\t    the_repository->worktree, new_work_tree);\n-\t\tstrbuf_release(&realpath);\n-\t\treturn;\n-\t}\n-\tgit_work_tree_initialized = 1;\n-\trepo_set_worktree(the_repository, new_work_tree);\n-}\n-\n-static void set_git_dir_1(const char *path)\n-{\n-\txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\n-\tsetup_git_env(path);\n-}\n-\n-static void update_relative_gitdir(const char *name UNUSED,\n-\t\t\t\t   const char *old_cwd,\n-\t\t\t\t   const char *new_cwd,\n-\t\t\t\t   void *data UNUSED)\n-{\n-\tchar *path = reparent_relative_path(old_cwd, new_cwd,\n-\t\t\t\t\t    repo_get_git_dir(the_repository));\n-\tstruct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();\n-\n-\ttrace_printf_key(&trace_setup_key,\n-\t\t\t \"setup: move $GIT_DIR to '%s'\",\n-\t\t\t path);\n-\tset_git_dir_1(path);\n-\tif (tmp_objdir)\n-\t\ttmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);\n-\tfree(path);\n-}\n-\n-void set_git_dir(const char *path, int make_realpath)\n-{\n-\tstruct strbuf realpath = STRBUF_INIT;\n-\n-\tif (make_realpath) {\n-\t\tstrbuf_realpath(&realpath, path, 1);\n-\t\tpath = realpath.buf;\n-\t}\n-\n-\tset_git_dir_1(path);\n-\tif (!is_absolute_path(path))\n-\t\tchdir_notify_register(NULL, update_relative_gitdir, NULL);\n-\n-\tstrbuf_release(&realpath);\n-}\n-\n const char *get_log_output_encoding(void)\n {\n \treturn git_log_output_encoding ? git_log_output_encoding\ndiff --git a/environment.h b/environment.h\nindex 682d4f2e3b5..b8460396790 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -105,10 +105,8 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\n-void set_git_work_tree(const char *tree);\n \n #define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n \ndiff --git a/setup.c b/setup.c\nindex 1bfec288ab6..19cce5afa72 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -7,16 +7,22 @@\n #include \"exec-cmd.h\"\n #include \"gettext.h\"\n #include \"hex.h\"\n+#include \"object-file.h\"\n #include \"object-name.h\"\n #include \"refs.h\"\n+#include \"replace-object.h\"\n #include \"repository.h\"\n #include \"config.h\"\n #include \"dir.h\"\n #include \"setup.h\"\n+#include \"shallow.h\"\n #include \"string-list.h\"\n+#include \"strvec.h\"\n #include \"chdir-notify.h\"\n #include \"path.h\"\n #include \"quote.h\"\n+#include \"tmp-objdir.h\"\n+#include \"trace.h\"\n #include \"trace2.h\"\n #include \"worktree.h\"\n #include \"exec-cmd.h\"\n@@ -1613,6 +1619,106 @@ enum discovery_result discover_git_directory_reason(struct strbuf *commondir,\n \treturn result;\n }\n \n+void setup_git_env(const char *git_dir)\n+{\n+\tchar *git_replace_ref_base;\n+\tconst char *shallow_file;\n+\tconst char *replace_ref_base;\n+\tstruct set_gitdir_args args = { NULL };\n+\tstruct strvec to_free = STRVEC_INIT;\n+\n+\targs.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);\n+\targs.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);\n+\targs.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);\n+\targs.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);\n+\targs.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);\n+\tif (getenv(GIT_QUARANTINE_ENVIRONMENT)) {\n+\t\targs.disable_ref_updates = 1;\n+\t}\n+\n+\trepo_set_gitdir(the_repository, git_dir, &args);\n+\tstrvec_clear(&to_free);\n+\n+\tif (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))\n+\t\tdisable_replace_refs();\n+\treplace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);\n+\tgit_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base\n+\t\t\t\t\t\t\t  : \"refs/replace/\");\n+\tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\n+\n+\tshallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);\n+\tif (shallow_file)\n+\t\tset_alternate_shallow_file(the_repository, shallow_file, 0);\n+\n+\tif (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))\n+\t\tfetch_if_missing = 0;\n+}\n+\n+static void set_git_dir_1(const char *path)\n+{\n+\txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\n+\tsetup_git_env(path);\n+}\n+\n+static void update_relative_gitdir(const char *name UNUSED,\n+\t\t\t\t   const char *old_cwd,\n+\t\t\t\t   const char *new_cwd,\n+\t\t\t\t   void *data UNUSED)\n+{\n+\tchar *path = reparent_relative_path(old_cwd, new_cwd,\n+\t\t\t\t\t    repo_get_git_dir(the_repository));\n+\tstruct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();\n+\n+\ttrace_printf_key(&trace_setup_key,\n+\t\t\t \"setup: move $GIT_DIR to '%s'\",\n+\t\t\t path);\n+\tset_git_dir_1(path);\n+\tif (tmp_objdir)\n+\t\ttmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);\n+\tfree(path);\n+}\n+\n+void set_git_dir(const char *path, int make_realpath)\n+{\n+\tstruct strbuf realpath = STRBUF_INIT;\n+\n+\tif (make_realpath) {\n+\t\tstrbuf_realpath(&realpath, path, 1);\n+\t\tpath = realpath.buf;\n+\t}\n+\n+\tset_git_dir_1(path);\n+\tif (!is_absolute_path(path))\n+\t\tchdir_notify_register(NULL, update_relative_gitdir, NULL);\n+\n+\tstrbuf_release(&realpath);\n+}\n+\n+static int git_work_tree_initialized;\n+\n+/*\n+ * Note.  This works only before you used a work tree.  This was added\n+ * primarily to support git-clone to work in a new repository it just\n+ * created, and is not meant to flip between different work trees.\n+ */\n+void set_git_work_tree(const char *new_work_tree)\n+{\n+\tif (git_work_tree_initialized) {\n+\t\tstruct strbuf realpath = STRBUF_INIT;\n+\n+\t\tstrbuf_realpath(&realpath, new_work_tree, 1);\n+\t\tnew_work_tree = realpath.buf;\n+\t\tif (strcmp(new_work_tree, the_repository->worktree))\n+\t\t\tdie(\"internal error: work tree has already been set\\n\"\n+\t\t\t    \"Current worktree: %s\\nNew worktree: %s\",\n+\t\t\t    the_repository->worktree, new_work_tree);\n+\t\tstrbuf_release(&realpath);\n+\t\treturn;\n+\t}\n+\tgit_work_tree_initialized = 1;\n+\trepo_set_worktree(the_repository, new_work_tree);\n+}\n+\n const char *setup_git_directory_gently(int *nongit_ok)\n {\n \tstatic struct strbuf cwd = STRBUF_INIT;\ndiff --git a/setup.h b/setup.h\nindex fd2df7cd525..e496ab3e4de 100644\n--- a/setup.h\n+++ b/setup.h\n@@ -94,6 +94,9 @@ static inline int discover_git_directory(struct strbuf *commondir,\n \treturn 0;\n }\n \n+void set_git_dir(const char *path, int make_realpath);\n+void set_git_work_tree(const char *tree);\n+\n const char *setup_git_directory_gently(int *);\n const char *setup_git_directory(void);\n char *prefix_path(const char *prefix, int len, const char *path);\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501907","messageId":"78f77a006a0d577ffce5d5488042d8db113b37b2.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 12/21] environment: reorder header to split out `the_repository`-free section","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:29Z","receivedAt":"2024-08-30T09:09:32Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Reorder the \"environment.h\" header such that declarations which are free\nfrom `the_repository` come before those which aren't. The new structure\nis now:\n\n    - Defines for environment variable names.\n\n    - Things which do not rely on a repository.\n\n    - Things which do, including those that implicitly rely on a parsed\n      repository. This includes for example variables which get\n      populated when reading repository config.\n\nThis will allow us to guard the last category of declarations with\n`USE_THE_REPOSITORY_VARIABLE`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n environment.h | 81 +++++++++++++++++++++++++--------------------------\n 1 file changed, 40 insertions(+), 41 deletions(-)\n\ndiff --git a/environment.h b/environment.h\nindex b8460396790..f1a7c645db5 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -1,22 +1,6 @@\n #ifndef ENVIRONMENT_H\n #define ENVIRONMENT_H\n \n-struct strvec;\n-\n-/*\n- * The character that begins a commented line in user-editable file\n- * that is subject to stripspace.\n- */\n-extern const char *comment_line_str;\n-extern char *comment_line_str_to_free;\n-extern int auto_comment_line_char;\n-\n-/*\n- * Wrapper of getenv() that returns a strdup value. This value is kept\n- * in argv to be freed later.\n- */\n-const char *getenv_safe(struct strvec *argv, const char *name);\n-\n /* Double-check local_repo_env below if you add to this list. */\n #define GIT_DIR_ENVIRONMENT \"GIT_DIR\"\n #define GIT_COMMON_DIR_ENVIRONMENT \"GIT_COMMON_DIR\"\n@@ -86,6 +70,8 @@ const char *getenv_safe(struct strvec *argv, const char *name);\n  */\n #define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT \"GIT_IMPLICIT_WORK_TREE\"\n \n+#define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n+\n /*\n  * Repository-local GIT_* environment variables; these will be cleared\n  * when git spawns a sub-process that runs inside another repository.\n@@ -94,6 +80,28 @@ const char *getenv_safe(struct strvec *argv, const char *name);\n  */\n extern const char * const local_repo_env[];\n \n+struct strvec;\n+\n+/*\n+ * Wrapper of getenv() that returns a strdup value. This value is kept\n+ * in argv to be freed later.\n+ */\n+const char *getenv_safe(struct strvec *argv, const char *name);\n+\n+/*\n+ * Should we print an ellipsis after an abbreviated SHA-1 value\n+ * when doing diff-raw output or indicating a detached HEAD?\n+ */\n+int print_sha1_ellipsis(void);\n+\n+/*\n+ * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value).\n+ */\n+int use_optional_locks(void);\n+\n+const char *get_git_namespace(void);\n+const char *strip_namespace(const char *namespaced_ref);\n+\n void setup_git_env(const char *git_dir);\n \n /*\n@@ -102,13 +110,19 @@ void setup_git_env(const char *git_dir);\n  */\n int have_git_dir(void);\n \n+/*\n+ * Accessors for the core.sharedrepository config which lazy-load the value\n+ * from the config (if not already set). The \"reset\" function can be\n+ * used to unset \"set\" or cached value, meaning that the value will be loaded\n+ * fresh from the config file on the next call to get_shared_repository().\n+ */\n+void set_shared_repository(int value);\n+int get_shared_repository(void);\n+void reset_shared_repository(void);\n+\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_git_namespace(void);\n-const char *strip_namespace(const char *namespaced_ref);\n-\n-#define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n \n /* Environment bits from configuration mechanism */\n extern int trust_executable_bit;\n@@ -134,16 +148,6 @@ extern unsigned long big_file_threshold;\n extern unsigned long pack_size_limit_cfg;\n extern int max_allowed_tree_depth;\n \n-/*\n- * Accessors for the core.sharedrepository config which lazy-load the value\n- * from the config (if not already set). The \"reset\" function can be\n- * used to unset \"set\" or cached value, meaning that the value will be loaded\n- * fresh from the config file on the next call to get_shared_repository().\n- */\n-void set_shared_repository(int value);\n-int get_shared_repository(void);\n-void reset_shared_repository(void);\n-\n extern int core_preload_index;\n extern int precomposed_unicode;\n extern int protect_hfs;\n@@ -153,11 +157,6 @@ extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n-/*\n- * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value).\n- */\n-int use_optional_locks(void);\n-\n enum log_refs_config {\n \tLOG_REFS_UNSET = -1,\n \tLOG_REFS_NONE = 0,\n@@ -172,6 +171,7 @@ enum rebase_setup_type {\n \tAUTOREBASE_REMOTE,\n \tAUTOREBASE_ALWAYS\n };\n+extern enum rebase_setup_type autorebase;\n \n enum push_default_type {\n \tPUSH_DEFAULT_NOTHING = 0,\n@@ -181,15 +181,12 @@ enum push_default_type {\n \tPUSH_DEFAULT_CURRENT,\n \tPUSH_DEFAULT_UNSPECIFIED\n };\n-\n-extern enum rebase_setup_type autorebase;\n extern enum push_default_type push_default;\n \n enum object_creation_mode {\n \tOBJECT_CREATION_USES_HARDLINKS = 0,\n \tOBJECT_CREATION_USES_RENAMES = 1\n };\n-\n extern enum object_creation_mode object_creation_mode;\n \n extern char *notes_ref_name;\n@@ -209,9 +206,11 @@ extern char *askpass_program;\n extern char *excludes_file;\n \n /*\n- * Should we print an ellipsis after an abbreviated SHA-1 value\n- * when doing diff-raw output or indicating a detached HEAD?\n+ * The character that begins a commented line in user-editable file\n+ * that is subject to stripspace.\n  */\n-int print_sha1_ellipsis(void);\n+extern const char *comment_line_str;\n+extern char *comment_line_str_to_free;\n+extern int auto_comment_line_char;\n \n #endif\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501908","messageId":"9a3f466b53040d693ed9b2c2390d391a5420aad1.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 13/21] environment: guard state depending on a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:32Z","receivedAt":"2024-08-30T09:09:37Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In \"environment.h\" we have quite a lot of functions and variables that\neither explicitly or implicitly depend on `the_repository`.\n\nThe implicit set of stateful declarations includes for example variables\nwhich get populated when parsing a repository's Git configuration. This\nset of variables is broken by design, as their state often depends on\nthe last repository config that has been parsed. So they may or may not\nrepresent the state of `the_repository`.\n\nFixing that is quite a big undertaking, and later patches in this series\nwill demonstrate a solution for a first small set of those variables. So\nfor now, let's guard these with `USE_THE_REPOSITORY_VARIABLE` so that\ncallers are aware of the implicit dependency.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n compat/mingw.c             |  2 ++\n compat/win32/path-utils.c  |  2 ++\n config.c                   |  2 ++\n environment.h              | 25 ++++++++++++++++++++++++-\n name-hash.c                |  3 +++\n path.c                     |  2 ++\n preload-index.c            |  3 +++\n prompt.c                   |  2 ++\n refs/files-backend.c       |  2 ++\n sparse-index.c             |  2 ++\n statinfo.c                 |  2 ++\n t/helper/test-path-utils.c |  2 ++\n tree-diff.c                |  3 +++\n userdiff.c                 |  2 ++\n 14 files changed, 53 insertions(+), 1 deletion(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 29d3f09768c..5c2080c04c1 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"../git-compat-util.h\"\n #include \"win32.h\"\n #include <aclapi.h>\ndiff --git a/compat/win32/path-utils.c b/compat/win32/path-utils.c\nindex b658ca3f811..966ef779b9c 100644\n--- a/compat/win32/path-utils.c\n+++ b/compat/win32/path-utils.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"../../git-compat-util.h\"\n #include \"../../environment.h\"\n \ndiff --git a/config.c b/config.c\nindex 043e1c8a078..f3066c37477 100644\n--- a/config.c\n+++ b/config.c\n@@ -6,6 +6,8 @@\n  *\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"advice.h\"\ndiff --git a/environment.h b/environment.h\nindex f1a7c645db5..934859e1c59 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -102,6 +102,28 @@ int use_optional_locks(void);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\n \n+/*\n+ * TODO: All the below state either explicitly or implicitly relies on\n+ * `the_repository`. We should eventually get rid of these and make the\n+ * dependency on a repository explicit:\n+ *\n+ *   - `setup_git_env()` ideally shouldn't exist as it modifies global state,\n+ *     namely the environment. The current process shouldn't ever access that\n+ *     state via envvars though, but should instead consult a `struct\n+ *     repository`. When spawning new processes, we would ideally also pass a\n+ *     `struct repository` and then set up the environment variables for the\n+ *     child process, only.\n+ *\n+ *   - `have_git_dir()` should not have to exist at all. Instead, we should\n+ *     decide on whether or not we have a `struct repository`.\n+ *\n+ *   - All the global config variables should become tied to a repository. Like\n+ *     this, we'd correctly honor repository-local configuration and be able to\n+ *     distinguish configuration values from different repositories.\n+ *\n+ * Please do not add new global config variables here.\n+ */\n+# ifdef USE_THE_REPOSITORY_VARIABLE\n void setup_git_env(const char *git_dir);\n \n /*\n@@ -213,4 +235,5 @@ extern const char *comment_line_str;\n extern char *comment_line_str_to_free;\n extern int auto_comment_line_char;\n \n-#endif\n+# endif /* USE_THE_REPOSITORY_VARIABLE */\n+#endif /* ENVIRONMENT_H */\ndiff --git a/name-hash.c b/name-hash.c\nindex 3a58ce03d9c..95528e3bcd2 100644\n--- a/name-hash.c\n+++ b/name-hash.c\n@@ -5,6 +5,9 @@\n  *\n  * Copyright (C) 2008 Linus Torvalds\n  */\n+\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\ndiff --git a/path.c b/path.c\nindex a3bf25b7def..93491bab141 100644\n--- a/path.c\n+++ b/path.c\n@@ -2,6 +2,8 @@\n  * Utilities for paths and pathnames\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"environment.h\"\ndiff --git a/preload-index.c b/preload-index.c\nindex 63fd35d64b1..7926eb09a69 100644\n--- a/preload-index.c\n+++ b/preload-index.c\n@@ -1,6 +1,9 @@\n /*\n  * Copyright (C) 2008 Linus Torvalds\n  */\n+\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"pathspec.h\"\n #include \"dir.h\"\ndiff --git a/prompt.c b/prompt.c\nindex 8935fe4dfb9..f21c5bf1c7e 100644\n--- a/prompt.c\n+++ b/prompt.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"parse.h\"\n #include \"environment.h\"\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 1cff65f6ae5..1bbb550f3af 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"../git-compat-util.h\"\n #include \"../copy.h\"\n #include \"../environment.h\"\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 9958656ded1..542ca5f411c 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\ndiff --git a/statinfo.c b/statinfo.c\nindex 3c6bc049c15..30a164b0e68 100644\n--- a/statinfo.c\n+++ b/statinfo.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"statinfo.h\"\ndiff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c\nindex bf0e23ed505..f57c8d706aa 100644\n--- a/t/helper/test-path-utils.c\n+++ b/t/helper/test-path-utils.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"test-tool.h\"\n #include \"abspath.h\"\n #include \"environment.h\"\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 9252481df36..5eab8af631b 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -1,6 +1,9 @@\n /*\n  * Helper functions for tree diff generation\n  */\n+\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"diff.h\"\n #include \"diffcore.h\"\ndiff --git a/userdiff.c b/userdiff.c\nindex 989629149f6..d43d8360d17 100644\n--- a/userdiff.c\n+++ b/userdiff.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"config.h\"\n #include \"userdiff.h\"\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501909","messageId":"0d7365c5190aabdf33990e36154d1807f199ed91.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 14/21] repo-settings: split out declarations into a standalone header","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:36Z","receivedAt":"2024-08-30T09:09:39Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"While we have \"repo-settings.c\", we do not have a corresponding\n\"repo-settings.h\" file. Instead, this functionality is part of the\n\"repository.h\" header, making it hard to discover.\n\nSplit the declarations out of \"repository.h\" and create a standalone\nheader file with them.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n repo-settings.c |  1 +\n repo-settings.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++\n repository.h    | 51 +-------------------------------------------\n 3 files changed, 58 insertions(+), 50 deletions(-)\n create mode 100644 repo-settings.h\n\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 2b4e68731be..6165546e80a 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -1,5 +1,6 @@\n #include \"git-compat-util.h\"\n #include \"config.h\"\n+#include \"repo-settings.h\"\n #include \"repository.h\"\n #include \"midx.h\"\n \ndiff --git a/repo-settings.h b/repo-settings.h\nnew file mode 100644\nindex 00000000000..ff20a965373\n--- /dev/null\n+++ b/repo-settings.h\n@@ -0,0 +1,56 @@\n+#ifndef REPO_SETTINGS_H\n+#define REPO_SETTINGS_H\n+\n+struct fsmonitor_settings;\n+struct repository;\n+\n+enum untracked_cache_setting {\n+\tUNTRACKED_CACHE_KEEP,\n+\tUNTRACKED_CACHE_REMOVE,\n+\tUNTRACKED_CACHE_WRITE,\n+};\n+\n+enum fetch_negotiation_setting {\n+\tFETCH_NEGOTIATION_CONSECUTIVE,\n+\tFETCH_NEGOTIATION_SKIPPING,\n+\tFETCH_NEGOTIATION_NOOP,\n+};\n+\n+struct repo_settings {\n+\tint initialized;\n+\n+\tint core_commit_graph;\n+\tint commit_graph_generation_version;\n+\tint commit_graph_changed_paths_version;\n+\tint gc_write_commit_graph;\n+\tint fetch_write_commit_graph;\n+\tint command_requires_full_index;\n+\tint sparse_index;\n+\tint pack_read_reverse_index;\n+\tint pack_use_bitmap_boundary_traversal;\n+\tint pack_use_multi_pack_reuse;\n+\n+\t/*\n+\t * Does this repository have core.useReplaceRefs=true (on by\n+\t * default)? This provides a repository-scoped version of this\n+\t * config, though it could be disabled process-wide via some Git\n+\t * builtins or the --no-replace-objects option. See\n+\t * replace_refs_enabled() for more details.\n+\t */\n+\tint read_replace_refs;\n+\n+\tstruct fsmonitor_settings *fsmonitor; /* lazily loaded */\n+\n+\tint index_version;\n+\tint index_skip_hash;\n+\tenum untracked_cache_setting core_untracked_cache;\n+\n+\tint pack_use_sparse;\n+\tenum fetch_negotiation_setting fetch_negotiation_algorithm;\n+\n+\tint core_multi_pack_index;\n+};\n+\n+void prepare_repo_settings(struct repository *r);\n+\n+#endif /* REPO_SETTINGS_H */\ndiff --git a/repository.h b/repository.h\nindex c603e969ae7..24a66a496a6 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -2,9 +2,9 @@\n #define REPOSITORY_H\n \n #include \"strmap.h\"\n+#include \"repo-settings.h\"\n \n struct config_set;\n-struct fsmonitor_settings;\n struct git_hash_algo;\n struct index_state;\n struct lock_file;\n@@ -14,59 +14,12 @@ struct submodule_cache;\n struct promisor_remote_config;\n struct remote_state;\n \n-enum untracked_cache_setting {\n-\tUNTRACKED_CACHE_KEEP,\n-\tUNTRACKED_CACHE_REMOVE,\n-\tUNTRACKED_CACHE_WRITE,\n-};\n-\n-enum fetch_negotiation_setting {\n-\tFETCH_NEGOTIATION_CONSECUTIVE,\n-\tFETCH_NEGOTIATION_SKIPPING,\n-\tFETCH_NEGOTIATION_NOOP,\n-};\n-\n enum ref_storage_format {\n \tREF_STORAGE_FORMAT_UNKNOWN,\n \tREF_STORAGE_FORMAT_FILES,\n \tREF_STORAGE_FORMAT_REFTABLE,\n };\n \n-struct repo_settings {\n-\tint initialized;\n-\n-\tint core_commit_graph;\n-\tint commit_graph_generation_version;\n-\tint commit_graph_changed_paths_version;\n-\tint gc_write_commit_graph;\n-\tint fetch_write_commit_graph;\n-\tint command_requires_full_index;\n-\tint sparse_index;\n-\tint pack_read_reverse_index;\n-\tint pack_use_bitmap_boundary_traversal;\n-\tint pack_use_multi_pack_reuse;\n-\n-\t/*\n-\t * Does this repository have core.useReplaceRefs=true (on by\n-\t * default)? This provides a repository-scoped version of this\n-\t * config, though it could be disabled process-wide via some Git\n-\t * builtins or the --no-replace-objects option. See\n-\t * replace_refs_enabled() for more details.\n-\t */\n-\tint read_replace_refs;\n-\n-\tstruct fsmonitor_settings *fsmonitor; /* lazily loaded */\n-\n-\tint index_version;\n-\tint index_skip_hash;\n-\tenum untracked_cache_setting core_untracked_cache;\n-\n-\tint pack_use_sparse;\n-\tenum fetch_negotiation_setting fetch_negotiation_algorithm;\n-\n-\tint core_multi_pack_index;\n-};\n-\n struct repo_path_cache {\n \tchar *squash_msg;\n \tchar *merge_msg;\n@@ -273,8 +226,6 @@ int repo_read_index_unmerged(struct repository *);\n  */\n void repo_update_index_if_able(struct repository *, struct lock_file *);\n \n-void prepare_repo_settings(struct repository *r);\n-\n /*\n  * Return 1 if upgrade repository format to target_version succeeded,\n  * 0 if no upgrade is necessary, and -1 when upgrade is not possible.\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501910","messageId":"231c52ce82f8339f4e27b59bdc76e402572e91f8.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 15/21] repo-settings: track defaults close to `struct repo_settings`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:39Z","receivedAt":"2024-08-30T09:09:42Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The default values for `struct repo_settings` are set up in\n`prepare_repo_settings()`. This is somewhat different from how we\ntypically do this, namely by providing an `INIT` macro that sets up the\ndefault values for us.\n\nRefactor the code to do the same.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n repo-settings.c | 9 ++++-----\n repo-settings.h | 5 +++++\n 2 files changed, 9 insertions(+), 5 deletions(-)\n\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 6165546e80a..3a76ba276c9 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -20,6 +20,7 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest,\n \n void prepare_repo_settings(struct repository *r)\n {\n+\tconst struct repo_settings defaults = REPO_SETTINGS_INIT;\n \tint experimental;\n \tint value;\n \tconst char *strval;\n@@ -29,13 +30,11 @@ void prepare_repo_settings(struct repository *r)\n \tif (!r->gitdir)\n \t\tBUG(\"Cannot add settings for uninitialized repository\");\n \n-\tif (r->settings.initialized++)\n+\tif (r->settings.initialized)\n \t\treturn;\n \n-\t/* Defaults */\n-\tr->settings.index_version = -1;\n-\tr->settings.core_untracked_cache = UNTRACKED_CACHE_KEEP;\n-\tr->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE;\n+\tmemcpy(&r->settings, &defaults, sizeof(defaults));\n+\tr->settings.initialized++;\n \n \t/* Booleans config or default, cascades to other settings */\n \trepo_cfg_bool(r, \"feature.manyfiles\", &manyfiles, 0);\ndiff --git a/repo-settings.h b/repo-settings.h\nindex ff20a965373..28f95695b3a 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -50,6 +50,11 @@ struct repo_settings {\n \n \tint core_multi_pack_index;\n };\n+#define REPO_SETTINGS_INIT { \\\n+\t.index_version = -1, \\\n+\t.core_untracked_cache = UNTRACKED_CACHE_KEEP, \\\n+\t.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \\\n+}\n \n void prepare_repo_settings(struct repository *r);\n \n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501911","messageId":"fc30365e1f13d47eb89339603f6a4744525b3967.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 16/21] branch: stop modifying `log_all_ref_updates` variable","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:42Z","receivedAt":"2024-08-30T09:09:45Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In \"branch.c\" we modify the global `log_all_ref_updates` variable to\nforce creation of a reflog entry. Modifying global state like this is\ndiscouraged, as it may have all kinds of consequences in other places of\nour codebase.\n\nStop modifying the variable and pass the `REF_FORCE_CREATE_REFLOG` flag,\nwhich has the same effect.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n branch.c | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/branch.c b/branch.c\nindex c887ea21514..08fa4094d2b 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -601,6 +601,7 @@ void create_branch(struct repository *r,\n \tint forcing = 0;\n \tstruct ref_transaction *transaction;\n \tstruct strbuf err = STRBUF_INIT;\n+\tint flags = 0;\n \tchar *msg;\n \n \tif (track == BRANCH_TRACK_OVERRIDE)\n@@ -619,7 +620,7 @@ void create_branch(struct repository *r,\n \t\tgoto cleanup;\n \n \tif (reflog)\n-\t\tlog_all_ref_updates = LOG_REFS_NORMAL;\n+\t\tflags |= REF_FORCE_CREATE_REFLOG;\n \n \tif (forcing)\n \t\tmsg = xstrfmt(\"branch: Reset to %s\", start_name);\n@@ -630,7 +631,7 @@ void create_branch(struct repository *r,\n \tif (!transaction ||\n \t\tref_transaction_update(transaction, ref.buf,\n \t\t\t\t\t&oid, forcing ? NULL : null_oid(),\n-\t\t\t\t\tNULL, NULL, 0, msg, &err) ||\n+\t\t\t\t\tNULL, NULL, flags, msg, &err) ||\n \t\tref_transaction_commit(transaction, &err))\n \t\tdie(\"%s\", err.buf);\n \tref_transaction_free(transaction);\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501912","messageId":"9cc8518a02d6bacfc11caa30c37f6bffaad69cfe.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 17/21] refs: stop modifying global `log_all_ref_updates` variable","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:44Z","receivedAt":"2024-08-30T09:09:48Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In refs-related code we modify the global `log_all_ref_updates`\nvariable, which is done because `should_autocreate_reflog()` does not\naccept passing an `enum log_refs_config` but instead accesses the global\nvariable. Adapt its interface such that the value is provided by the\ncaller, which allows us to compute the proper value locally without\nhaving to modify global state.\n\nThis change requires us to move the enum to \"repo-settings.h\", or\notherwise we get compilation errors due to include cycles. We're about\nto fully move this setting into the repo-settings subsystem anyway, so\nthis is fine.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/checkout.c      |  3 ++-\n environment.h           |  8 ++------\n refs.c                  |  5 +++--\n refs.h                  |  4 +++-\n refs/files-backend.c    | 23 ++++++++++++-----------\n refs/reftable-backend.c | 12 +++++++-----\n repo-settings.h         |  7 +++++++\n 7 files changed, 36 insertions(+), 26 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 4cfe6fab505..6db7f39492e 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -23,6 +23,7 @@\n #include \"read-cache.h\"\n #include \"refs.h\"\n #include \"remote.h\"\n+#include \"repo-settings.h\"\n #include \"resolve-undo.h\"\n #include \"revision.h\"\n #include \"setup.h\"\n@@ -954,7 +955,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,\n \n \t\t\trefname = mkpathdup(\"refs/heads/%s\", opts->new_orphan_branch);\n \t\t\tif (opts->new_branch_log &&\n-\t\t\t    !should_autocreate_reflog(refname)) {\n+\t\t\t    !should_autocreate_reflog(log_all_ref_updates, refname)) {\n \t\t\t\tint ret;\n \t\t\t\tstruct strbuf err = STRBUF_INIT;\n \ndiff --git a/environment.h b/environment.h\nindex 934859e1c59..0b4e5afc36d 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -1,6 +1,8 @@\n #ifndef ENVIRONMENT_H\n #define ENVIRONMENT_H\n \n+#include \"repo-settings.h\"\n+\n /* Double-check local_repo_env below if you add to this list. */\n #define GIT_DIR_ENVIRONMENT \"GIT_DIR\"\n #define GIT_COMMON_DIR_ENVIRONMENT \"GIT_COMMON_DIR\"\n@@ -179,12 +181,6 @@ extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n-enum log_refs_config {\n-\tLOG_REFS_UNSET = -1,\n-\tLOG_REFS_NONE = 0,\n-\tLOG_REFS_NORMAL,\n-\tLOG_REFS_ALWAYS\n-};\n extern enum log_refs_config log_all_ref_updates;\n \n enum rebase_setup_type {\ndiff --git a/refs.c b/refs.c\nindex ceb72d4bd74..d7402bcd196 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -24,7 +24,7 @@\n #include \"submodule.h\"\n #include \"worktree.h\"\n #include \"strvec.h\"\n-#include \"repository.h\"\n+#include \"repo-settings.h\"\n #include \"setup.h\"\n #include \"sigchain.h\"\n #include \"date.h\"\n@@ -958,7 +958,8 @@ static char *normalize_reflog_message(const char *msg)\n \treturn strbuf_detach(&sb, NULL);\n }\n \n-int should_autocreate_reflog(const char *refname)\n+int should_autocreate_reflog(enum log_refs_config log_all_ref_updates,\n+\t\t\t     const char *refname)\n {\n \tswitch (log_all_ref_updates) {\n \tcase LOG_REFS_ALWAYS:\ndiff --git a/refs.h b/refs.h\nindex f8b919a1388..f2c4ccde611 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -3,6 +3,7 @@\n \n #include \"commit.h\"\n #include \"repository.h\"\n+#include \"repo-settings.h\"\n \n struct fsck_options;\n struct object_id;\n@@ -111,7 +112,8 @@ int refs_verify_refname_available(struct ref_store *refs,\n \n int refs_ref_exists(struct ref_store *refs, const char *refname);\n \n-int should_autocreate_reflog(const char *refname);\n+int should_autocreate_reflog(enum log_refs_config log_all_ref_updates,\n+\t\t\t     const char *refname);\n \n int is_branch(const char *refname);\n \ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 1bbb550f3af..f5871abcf75 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -8,6 +8,7 @@\n #include \"../hex.h\"\n #include \"../fsck.h\"\n #include \"../refs.h\"\n+#include \"../repo-settings.h\"\n #include \"refs-internal.h\"\n #include \"ref-cache.h\"\n #include \"packed-backend.h\"\n@@ -1443,6 +1444,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs,\n static int commit_ref_update(struct files_ref_store *refs,\n \t\t\t     struct ref_lock *lock,\n \t\t\t     const struct object_id *oid, const char *logmsg,\n+\t\t\t     int flags,\n \t\t\t     struct strbuf *err);\n \n /*\n@@ -1586,7 +1588,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,\n \toidcpy(&lock->old_oid, &orig_oid);\n \n \tif (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) ||\n-\t    commit_ref_update(refs, lock, &orig_oid, logmsg, &err)) {\n+\t    commit_ref_update(refs, lock, &orig_oid, logmsg, 0, &err)) {\n \t\terror(\"unable to write current sha1 into %s: %s\", newrefname, err.buf);\n \t\tstrbuf_release(&err);\n \t\tgoto rollback;\n@@ -1603,14 +1605,11 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,\n \t\tgoto rollbacklog;\n \t}\n \n-\tflag = log_all_ref_updates;\n-\tlog_all_ref_updates = LOG_REFS_NONE;\n \tif (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) ||\n-\t    commit_ref_update(refs, lock, &orig_oid, NULL, &err)) {\n+\t    commit_ref_update(refs, lock, &orig_oid, NULL, REF_SKIP_CREATE_REFLOG, &err)) {\n \t\terror(\"unable to write current sha1 into %s: %s\", oldrefname, err.buf);\n \t\tstrbuf_release(&err);\n \t}\n-\tlog_all_ref_updates = flag;\n \n  rollbacklog:\n \tif (logmoved && rename(sb_newref.buf, sb_oldref.buf))\n@@ -1705,13 +1704,17 @@ static int log_ref_setup(struct files_ref_store *refs,\n \t\t\t const char *refname, int force_create,\n \t\t\t int *logfd, struct strbuf *err)\n {\n+\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n \tstruct strbuf logfile_sb = STRBUF_INIT;\n \tchar *logfile;\n \n+\tif (log_refs_cfg == LOG_REFS_UNSET)\n+\t\tlog_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n+\n \tfiles_reflog_path(refs, &logfile_sb, refname);\n \tlogfile = strbuf_detach(&logfile_sb, NULL);\n \n-\tif (force_create || should_autocreate_reflog(refname)) {\n+\tif (force_create || should_autocreate_reflog(log_refs_cfg, refname)) {\n \t\tif (raceproof_create_file(logfile, open_or_create_logfile, logfd)) {\n \t\t\tif (errno == ENOENT)\n \t\t\t\tstrbuf_addf(err, \"unable to create directory for '%s': \"\n@@ -1800,9 +1803,6 @@ static int files_log_ref_write(struct files_ref_store *refs,\n \tif (flags & REF_SKIP_CREATE_REFLOG)\n \t\treturn 0;\n \n-\tif (log_all_ref_updates == LOG_REFS_UNSET)\n-\t\tlog_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n-\n \tresult = log_ref_setup(refs, refname,\n \t\t\t       flags & REF_FORCE_CREATE_REFLOG,\n \t\t\t       &logfd, err);\n@@ -1891,6 +1891,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs,\n static int commit_ref_update(struct files_ref_store *refs,\n \t\t\t     struct ref_lock *lock,\n \t\t\t     const struct object_id *oid, const char *logmsg,\n+\t\t\t     int flags,\n \t\t\t     struct strbuf *err)\n {\n \tfiles_assert_main_repository(refs, \"commit_ref_update\");\n@@ -1898,7 +1899,7 @@ static int commit_ref_update(struct files_ref_store *refs,\n \tclear_loose_ref_cache(refs);\n \tif (files_log_ref_write(refs, lock->ref_name,\n \t\t\t\t&lock->old_oid, oid,\n-\t\t\t\tlogmsg, 0, err)) {\n+\t\t\t\tlogmsg, flags, err)) {\n \t\tchar *old_msg = strbuf_detach(err, NULL);\n \t\tstrbuf_addf(err, \"cannot update the ref '%s': %s\",\n \t\t\t    lock->ref_name, old_msg);\n@@ -1931,7 +1932,7 @@ static int commit_ref_update(struct files_ref_store *refs,\n \t\t\tstruct strbuf log_err = STRBUF_INIT;\n \t\t\tif (files_log_ref_write(refs, \"HEAD\",\n \t\t\t\t\t\t&lock->old_oid, oid,\n-\t\t\t\t\t\tlogmsg, 0, &log_err)) {\n+\t\t\t\t\t\tlogmsg, flags, &log_err)) {\n \t\t\t\terror(\"%s\", log_err.buf);\n \t\t\t\tstrbuf_release(&log_err);\n \t\t\t}\ndiff --git a/refs/reftable-backend.c b/refs/reftable-backend.c\nindex 1c4b19e737f..c78186423a1 100644\n--- a/refs/reftable-backend.c\n+++ b/refs/reftable-backend.c\n@@ -19,6 +19,7 @@\n #include \"../reftable/reftable-record.h\"\n #include \"../reftable/reftable-error.h\"\n #include \"../reftable/reftable-iterator.h\"\n+#include \"../repo-settings.h\"\n #include \"../setup.h\"\n #include \"../strmap.h\"\n #include \"parse.h\"\n@@ -158,20 +159,21 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store,\n \n static int should_write_log(struct ref_store *refs, const char *refname)\n {\n-\tif (log_all_ref_updates == LOG_REFS_UNSET)\n-\t\tlog_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n+\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n+\tif (log_refs_cfg == LOG_REFS_UNSET)\n+\t\tlog_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n \n-\tswitch (log_all_ref_updates) {\n+\tswitch (log_refs_cfg) {\n \tcase LOG_REFS_NONE:\n \t\treturn refs_reflog_exists(refs, refname);\n \tcase LOG_REFS_ALWAYS:\n \t\treturn 1;\n \tcase LOG_REFS_NORMAL:\n-\t\tif (should_autocreate_reflog(refname))\n+\t\tif (should_autocreate_reflog(log_refs_cfg, refname))\n \t\t\treturn 1;\n \t\treturn refs_reflog_exists(refs, refname);\n \tdefault:\n-\t\tBUG(\"unhandled core.logAllRefUpdates value %d\", log_all_ref_updates);\n+\t\tBUG(\"unhandled core.logAllRefUpdates value %d\", log_refs_cfg);\n \t}\n }\n \ndiff --git a/repo-settings.h b/repo-settings.h\nindex 28f95695b3a..d03b6e57f0c 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -16,6 +16,13 @@ enum fetch_negotiation_setting {\n \tFETCH_NEGOTIATION_NOOP,\n };\n \n+enum log_refs_config {\n+\tLOG_REFS_UNSET = -1,\n+\tLOG_REFS_NONE = 0,\n+\tLOG_REFS_NORMAL,\n+\tLOG_REFS_ALWAYS\n+};\n+\n struct repo_settings {\n \tint initialized;\n \n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501913","messageId":"b5ed6928070ca02463bf53d339aba47bbf25e86a.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 18/21] environment: stop storing \"core.logAllRefUpdates\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:50Z","receivedAt":"2024-08-30T09:09:55Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The value of \"core.logAllRefUpdates\" is being stored in the global\nvariable `log_all_ref_updates`. This design is somewhat aged nowadays,\nwhere it is entirely possible to access multiple repositories in the\nsame process which all have different values for this setting. So using\na single global variable to track it is plain wrong.\n\nRemove the global variable. Instead, we now provide a new function part\nof the repo-settings subsystem that parses the value for a specific\nrepository. While that may require us to read the value multiple times,\nwe work around this by reading it once when the ref backends are set up\nand caching the value there.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/checkout.c      |  2 ++\n config.c                | 10 ----------\n environment.c           |  1 -\n environment.h           |  2 --\n refs/files-backend.c    |  4 +++-\n refs/reftable-backend.c | 12 +++++++-----\n repo-settings.c         | 16 ++++++++++++++++\n repo-settings.h         |  3 +++\n setup.c                 |  2 +-\n 9 files changed, 32 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 6db7f39492e..7e18b87c7a4 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -951,6 +951,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts,\n \tconst char *old_desc, *reflog_msg;\n \tif (opts->new_branch) {\n \t\tif (opts->new_orphan_branch) {\n+\t\t\tenum log_refs_config log_all_ref_updates =\n+\t\t\t\trepo_settings_get_log_all_ref_updates(the_repository);\n \t\t\tchar *refname;\n \n \t\t\trefname = mkpathdup(\"refs/heads/%s\", opts->new_orphan_branch);\ndiff --git a/config.c b/config.c\nindex f3066c37477..47101c3e977 100644\n--- a/config.c\n+++ b/config.c\n@@ -1452,16 +1452,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.logallrefupdates\")) {\n-\t\tif (value && !strcasecmp(value, \"always\"))\n-\t\t\tlog_all_ref_updates = LOG_REFS_ALWAYS;\n-\t\telse if (git_config_bool(var, value))\n-\t\t\tlog_all_ref_updates = LOG_REFS_NORMAL;\n-\t\telse\n-\t\t\tlog_all_ref_updates = LOG_REFS_NONE;\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.warnambiguousrefs\")) {\n \t\twarn_ambiguous_refs = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 64ae13ef240..992d87e0d60 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -77,7 +77,6 @@ int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\n int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\n unsigned long pack_size_limit_cfg;\n-enum log_refs_config log_all_ref_updates = LOG_REFS_UNSET;\n int max_allowed_tree_depth =\n #ifdef _MSC_VER\n \t/*\ndiff --git a/environment.h b/environment.h\nindex 0b4e5afc36d..315fd319951 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -181,8 +181,6 @@ extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n-extern enum log_refs_config log_all_ref_updates;\n-\n enum rebase_setup_type {\n \tAUTOREBASE_NEVER = 0,\n \tAUTOREBASE_LOCAL,\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex f5871abcf75..a536d7d1b57 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -75,6 +75,7 @@ struct files_ref_store {\n \tunsigned int store_flags;\n \n \tchar *gitcommondir;\n+\tenum log_refs_config log_all_ref_updates;\n \n \tstruct ref_cache *loose;\n \n@@ -107,6 +108,7 @@ static struct ref_store *files_ref_store_init(struct repository *repo,\n \trefs->gitcommondir = strbuf_detach(&sb, NULL);\n \trefs->packed_ref_store =\n \t\tpacked_ref_store_init(repo, refs->gitcommondir, flags);\n+\trefs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);\n \n \tchdir_notify_reparent(\"files-backend $GIT_DIR\", &refs->base.gitdir);\n \tchdir_notify_reparent(\"files-backend $GIT_COMMONDIR\",\n@@ -1704,7 +1706,7 @@ static int log_ref_setup(struct files_ref_store *refs,\n \t\t\t const char *refname, int force_create,\n \t\t\t int *logfd, struct strbuf *err)\n {\n-\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n+\tenum log_refs_config log_refs_cfg = refs->log_all_ref_updates;\n \tstruct strbuf logfile_sb = STRBUF_INIT;\n \tchar *logfile;\n \ndiff --git a/refs/reftable-backend.c b/refs/reftable-backend.c\nindex c78186423a1..043e19439f6 100644\n--- a/refs/reftable-backend.c\n+++ b/refs/reftable-backend.c\n@@ -52,6 +52,7 @@ struct reftable_ref_store {\n \tstruct reftable_write_options write_options;\n \n \tunsigned int store_flags;\n+\tenum log_refs_config log_all_ref_updates;\n \tint err;\n };\n \n@@ -157,21 +158,21 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store,\n \t}\n }\n \n-static int should_write_log(struct ref_store *refs, const char *refname)\n+static int should_write_log(struct reftable_ref_store *refs, const char *refname)\n {\n-\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n+\tenum log_refs_config log_refs_cfg = refs->log_all_ref_updates;\n \tif (log_refs_cfg == LOG_REFS_UNSET)\n \t\tlog_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n \n \tswitch (log_refs_cfg) {\n \tcase LOG_REFS_NONE:\n-\t\treturn refs_reflog_exists(refs, refname);\n+\t\treturn refs_reflog_exists(&refs->base, refname);\n \tcase LOG_REFS_ALWAYS:\n \t\treturn 1;\n \tcase LOG_REFS_NORMAL:\n \t\tif (should_autocreate_reflog(log_refs_cfg, refname))\n \t\t\treturn 1;\n-\t\treturn refs_reflog_exists(refs, refname);\n+\t\treturn refs_reflog_exists(&refs->base, refname);\n \tdefault:\n \t\tBUG(\"unhandled core.logAllRefUpdates value %d\", log_refs_cfg);\n \t}\n@@ -278,6 +279,7 @@ static struct ref_store *reftable_be_init(struct repository *repo,\n \tbase_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable);\n \tstrmap_init(&refs->worktree_stacks);\n \trefs->store_flags = store_flags;\n+\trefs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);\n \n \trefs->write_options.hash_id = repo->hash_algo->format_id;\n \trefs->write_options.default_permissions = calc_shared_perm(0666 & ~mask);\n@@ -1220,7 +1222,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data\n \t\t} else if (!(u->flags & REF_SKIP_CREATE_REFLOG) &&\n \t\t\t   (u->flags & REF_HAVE_NEW) &&\n \t\t\t   (u->flags & REF_FORCE_CREATE_REFLOG ||\n-\t\t\t    should_write_log(&arg->refs->base, u->refname))) {\n+\t\t\t    should_write_log(arg->refs, u->refname))) {\n \t\t\tstruct reftable_log_record *log;\n \t\t\tint create_reflog = 1;\n \ndiff --git a/repo-settings.c b/repo-settings.c\nindex 3a76ba276c9..1322fd2f972 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -124,3 +124,19 @@ void prepare_repo_settings(struct repository *r)\n \t */\n \tr->settings.command_requires_full_index = 1;\n }\n+\n+enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)\n+{\n+\tconst char *value;\n+\n+\tif (!repo_config_get_string_tmp(repo, \"core.logallrefupdates\", &value)) {\n+\t\tif (value && !strcasecmp(value, \"always\"))\n+\t\t\treturn LOG_REFS_ALWAYS;\n+\t\telse if (git_config_bool(\"core.logallrefupdates\", value))\n+\t\t\treturn LOG_REFS_NORMAL;\n+\t\telse\n+\t\t\treturn LOG_REFS_NONE;\n+\t}\n+\n+\treturn LOG_REFS_UNSET;\n+}\ndiff --git a/repo-settings.h b/repo-settings.h\nindex d03b6e57f0c..76adb96a669 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -65,4 +65,7 @@ struct repo_settings {\n \n void prepare_repo_settings(struct repository *r);\n \n+/* Read the value for \"core.logAllRefUpdates\". */\n+enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo);\n+\n #endif /* REPO_SETTINGS_H */\ndiff --git a/setup.c b/setup.c\nindex 19cce5afa72..74991914726 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2354,7 +2354,7 @@ static int create_default_files(const char *template_path,\n \telse {\n \t\tgit_config_set(\"core.bare\", \"false\");\n \t\t/* allow template config file to override the default */\n-\t\tif (log_all_ref_updates == LOG_REFS_UNSET)\n+\t\tif (repo_settings_get_log_all_ref_updates(the_repository) == LOG_REFS_UNSET)\n \t\t\tgit_config_set(\"core.logallrefupdates\", \"true\");\n \t\tif (needs_work_tree_config(original_git_dir, work_tree))\n \t\t\tgit_config_set(\"core.worktree\", work_tree);\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501914","messageId":"194d858877f9954059800e9a9b698e8c04447946.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 19/21] environment: stop storing \"core.preferSymlinkRefs\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:55Z","receivedAt":"2024-08-30T09:09:59Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Same as the preceding commit, storing the \"core.preferSymlinkRefs\" value\nglobally is misdesigned as this setting may be set per repository.\n\nThere is only a single user of this value anyway, namely the \"files\"\nbackend. So let's just remove the global variable and read the value of\nthis setting when initializing the backend.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c             | 5 -----\n environment.c        | 1 -\n environment.h        | 1 -\n refs/files-backend.c | 5 ++++-\n 4 files changed, 4 insertions(+), 8 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 47101c3e977..a59890180a3 100644\n--- a/config.c\n+++ b/config.c\n@@ -1447,11 +1447,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.prefersymlinkrefs\")) {\n-\t\tprefer_symlink_refs = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.warnambiguousrefs\")) {\n \t\twarn_ambiguous_refs = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 992d87e0d60..6805c7b01df 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -34,7 +34,6 @@ int has_symlinks = 1;\n int minimum_abbrev = 4, default_abbrev = -1;\n int ignore_case;\n int assume_unchanged;\n-int prefer_symlink_refs;\n int is_bare_repository_cfg = -1; /* unspecified */\n int warn_ambiguous_refs = 1;\n int warn_on_object_refname_ambiguity = 1;\ndiff --git a/environment.h b/environment.h\nindex 315fd319951..0cab644e2d3 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -156,7 +156,6 @@ extern int has_symlinks;\n extern int minimum_abbrev, default_abbrev;\n extern int ignore_case;\n extern int assume_unchanged;\n-extern int prefer_symlink_refs;\n extern int warn_ambiguous_refs;\n extern int warn_on_object_refname_ambiguity;\n extern char *apply_default_whitespace;\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex a536d7d1b57..e5b0aff00dc 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1,6 +1,7 @@\n #define USE_THE_REPOSITORY_VARIABLE\n \n #include \"../git-compat-util.h\"\n+#include \"../config.h\"\n #include \"../copy.h\"\n #include \"../environment.h\"\n #include \"../gettext.h\"\n@@ -76,6 +77,7 @@ struct files_ref_store {\n \n \tchar *gitcommondir;\n \tenum log_refs_config log_all_ref_updates;\n+\tint prefer_symlink_refs;\n \n \tstruct ref_cache *loose;\n \n@@ -109,6 +111,7 @@ static struct ref_store *files_ref_store_init(struct repository *repo,\n \trefs->packed_ref_store =\n \t\tpacked_ref_store_init(repo, refs->gitcommondir, flags);\n \trefs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);\n+\trepo_config_get_bool(repo, \"core.prefersymlinkrefs\", &refs->prefer_symlink_refs);\n \n \tchdir_notify_reparent(\"files-backend $GIT_DIR\", &refs->base.gitdir);\n \tchdir_notify_reparent(\"files-backend $GIT_COMMONDIR\",\n@@ -2942,7 +2945,7 @@ static int files_transaction_finish(struct ref_store *ref_store,\n \t\t * We try creating a symlink, if that succeeds we continue to the\n \t\t * next update. If not, we try and create a regular symref.\n \t\t */\n-\t\tif (update->new_target && prefer_symlink_refs)\n+\t\tif (update->new_target && refs->prefer_symlink_refs)\n \t\t\tif (!create_ref_symlink(lock, update->new_target))\n \t\t\t\tcontinue;\n \n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501915","messageId":"fc6fcebf7f737617c635b338e3c0dce10e77881c.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 20/21] environment: stop storing \"core.warnAmbiguousRefs\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:09:58Z","receivedAt":"2024-08-30T09:10:01Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Same as the preceding commits, storing the \"core.warnAmbiguousRefs\"\nvalue globally is misdesigned as this setting may be set per repository.\n\nMove the logic into the repo-settings subsystem. The usual pattern here\nis that users are expected to call `prepare_repo_settings()` before they\naccess the settings themselves. This seems somewhat fragile though, as\nit is easy to miss and leads to somewhat ugly code patterns at the call\nsites.\n\nInstead, introduce a new function that encapsulates this logic for us.\nThis also allows us to change how exactly the lazy initialization works\nin the future, e.g. by only partially initializing values as requested\nby the caller.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/rev-parse.c | 4 +++-\n config.c            | 5 -----\n environment.c       | 1 -\n environment.h       | 1 -\n object-name.c       | 5 +++--\n ref-filter.c        | 3 ++-\n refs.c              | 4 ++--\n repo-settings.c     | 9 +++++++++\n repo-settings.h     | 4 ++++\n 9 files changed, 23 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex a5108266daf..34b46754426 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -19,6 +19,7 @@\n #include \"path.h\"\n #include \"diff.h\"\n #include \"read-cache-ll.h\"\n+#include \"repo-settings.h\"\n #include \"repository.h\"\n #include \"revision.h\"\n #include \"setup.h\"\n@@ -899,7 +900,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t}\n \t\t\tif (opt_with_value(arg, \"--abbrev-ref\", &arg)) {\n \t\t\t\tabbrev_ref = 1;\n-\t\t\t\tabbrev_ref_strict = warn_ambiguous_refs;\n+\t\t\t\tabbrev_ref_strict =\n+\t\t\t\t\trepo_settings_get_warn_ambiguous_refs(the_repository);\n \t\t\t\tif (arg) {\n \t\t\t\t\tif (!strcmp(arg, \"strict\"))\n \t\t\t\t\t\tabbrev_ref_strict = 1;\ndiff --git a/config.c b/config.c\nindex a59890180a3..53c68f3da61 100644\n--- a/config.c\n+++ b/config.c\n@@ -1447,11 +1447,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.warnambiguousrefs\")) {\n-\t\twarn_ambiguous_refs = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.abbrev\")) {\n \t\tif (!value)\n \t\t\treturn config_error_nonbool(var);\ndiff --git a/environment.c b/environment.c\nindex 6805c7b01df..9dd000cda36 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -35,7 +35,6 @@ int minimum_abbrev = 4, default_abbrev = -1;\n int ignore_case;\n int assume_unchanged;\n int is_bare_repository_cfg = -1; /* unspecified */\n-int warn_ambiguous_refs = 1;\n int warn_on_object_refname_ambiguity = 1;\n int repository_format_precious_objects;\n char *git_commit_encoding;\ndiff --git a/environment.h b/environment.h\nindex 0cab644e2d3..aa38133da9c 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -156,7 +156,6 @@ extern int has_symlinks;\n extern int minimum_abbrev, default_abbrev;\n extern int ignore_case;\n extern int assume_unchanged;\n-extern int warn_ambiguous_refs;\n extern int warn_on_object_refname_ambiguity;\n extern char *apply_default_whitespace;\n extern char *apply_default_ignorewhitespace;\ndiff --git a/object-name.c b/object-name.c\nindex 09c1bd93a31..c892fbe80aa 100644\n--- a/object-name.c\n+++ b/object-name.c\n@@ -20,6 +20,7 @@\n #include \"pretty.h\"\n #include \"object-store-ll.h\"\n #include \"read-cache-ll.h\"\n+#include \"repo-settings.h\"\n #include \"repository.h\"\n #include \"setup.h\"\n #include \"midx.h\"\n@@ -959,7 +960,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,\n \tint fatal = !(flags & GET_OID_QUIETLY);\n \n \tif (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {\n-\t\tif (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {\n+\t\tif (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) {\n \t\t\trefs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);\n \t\t\tif (refs_found > 0) {\n \t\t\t\twarning(warn_msg, len, str);\n@@ -1020,7 +1021,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,\n \tif (!refs_found)\n \t\treturn -1;\n \n-\tif (warn_ambiguous_refs && !(flags & GET_OID_QUIETLY) &&\n+\tif (repo_settings_get_warn_ambiguous_refs(r) && !(flags & GET_OID_QUIETLY) &&\n \t    (refs_found > 1 ||\n \t     !get_short_oid(r, str, len, &tmp_oid, GET_OID_QUIETLY)))\n \t\twarning(warn_msg, len, str);\ndiff --git a/ref-filter.c b/ref-filter.c\nindex b6c6c101276..7f5cf5a1269 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -13,6 +13,7 @@\n #include \"object-name.h\"\n #include \"object-store-ll.h\"\n #include \"oid-array.h\"\n+#include \"repo-settings.h\"\n #include \"repository.h\"\n #include \"commit.h\"\n #include \"mailmap.h\"\n@@ -2160,7 +2161,7 @@ static const char *show_ref(struct refname_atom *atom, const char *refname)\n \tif (atom->option == R_SHORT)\n \t\treturn refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),\n \t\t\t\t\t\t    refname,\n-\t\t\t\t\t\t    warn_ambiguous_refs);\n+\t\t\t\t\t\t    repo_settings_get_warn_ambiguous_refs(the_repository));\n \telse if (atom->option == R_LSTRIP)\n \t\treturn lstrip_ref_components(refname, atom->lstrip);\n \telse if (atom->option == R_RSTRIP)\ndiff --git a/refs.c b/refs.c\nindex d7402bcd196..3bee3e78299 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -730,7 +730,7 @@ int expand_ref(struct repository *repo, const char *str, int len,\n \t\tif (r) {\n \t\t\tif (!refs_found++)\n \t\t\t\t*ref = xstrdup(r);\n-\t\t\tif (!warn_ambiguous_refs)\n+\t\t\tif (!repo_settings_get_warn_ambiguous_refs(repo))\n \t\t\t\tbreak;\n \t\t} else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, \"HEAD\")) {\n \t\t\twarning(_(\"ignoring dangling symref %s\"), fullref.buf);\n@@ -775,7 +775,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len,\n \t\t\tif (oid)\n \t\t\t\toidcpy(oid, &hash);\n \t\t}\n-\t\tif (!warn_ambiguous_refs)\n+\t\tif (!repo_settings_get_warn_ambiguous_refs(r))\n \t\t\tbreak;\n \t}\n \tstrbuf_release(&path);\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 1322fd2f972..4699b4b3650 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -140,3 +140,12 @@ enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *re\n \n \treturn LOG_REFS_UNSET;\n }\n+\n+int repo_settings_get_warn_ambiguous_refs(struct repository *repo)\n+{\n+\tprepare_repo_settings(repo);\n+\tif (repo->settings.warn_ambiguous_refs < 0)\n+\t\trepo_cfg_bool(repo, \"core.warnambiguousrefs\",\n+\t\t\t      &repo->settings.warn_ambiguous_refs, 1);\n+\treturn repo->settings.warn_ambiguous_refs;\n+}\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 76adb96a669..51d6156a117 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -56,16 +56,20 @@ struct repo_settings {\n \tenum fetch_negotiation_setting fetch_negotiation_algorithm;\n \n \tint core_multi_pack_index;\n+\tint warn_ambiguous_refs; /* lazily loaded via accessor */\n };\n #define REPO_SETTINGS_INIT { \\\n \t.index_version = -1, \\\n \t.core_untracked_cache = UNTRACKED_CACHE_KEEP, \\\n \t.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \\\n+\t.warn_ambiguous_refs = -1, \\\n }\n \n void prepare_repo_settings(struct repository *r);\n \n /* Read the value for \"core.logAllRefUpdates\". */\n enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo);\n+/* Read the value for \"core.warnAmbiguousRefs\". */\n+int repo_settings_get_warn_ambiguous_refs(struct repository *repo);\n \n #endif /* REPO_SETTINGS_H */\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501916","messageId":"a0b75c4bc99c83748d793d311764535fc193a470.1725008898.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"[PATCH v2 21/21] environment: stop storing \"core.notesRef\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-30T09:10:00Z","receivedAt":"2024-08-30T09:10:03Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Stop storing the \"core.notesRef\" config value globally. Instead,\nretrieve the value in `default_notes_ref()`. The code is never called in\na hot loop anyway, so doing this on every invocation should be perfectly\nfine.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/notes.c | 22 ++++++++++++++--------\n config.c        |  8 --------\n environment.c   |  1 -\n environment.h   |  2 --\n notes.c         | 21 +++++++++++++--------\n notes.h         |  3 ++-\n 6 files changed, 29 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 04f9dfb7fbd..5d594a07240 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -897,6 +897,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t\t\t      1, PARSE_OPT_NONEG),\n \t\tOPT_END()\n \t};\n+\tchar *notes_ref;\n \n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_notes_merge_usage, 0);\n@@ -924,7 +925,8 @@ static int merge(int argc, const char **argv, const char *prefix)\n \tif (do_commit)\n \t\treturn merge_commit(&o);\n \n-\to.local_ref = default_notes_ref();\n+\tnotes_ref = default_notes_ref(the_repository);\n+\to.local_ref = notes_ref;\n \tstrbuf_addstr(&remote_ref, argv[0]);\n \texpand_loose_notes_ref(&remote_ref);\n \to.remote_ref = remote_ref.buf;\n@@ -953,7 +955,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t}\n \n \tstrbuf_addf(&msg, \"notes: Merged notes from %s into %s\",\n-\t\t    remote_ref.buf, default_notes_ref());\n+\t\t    remote_ref.buf, notes_ref);\n \tstrbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip \"notes: \" */\n \n \tresult = notes_merge(&o, t, &result_oid);\n@@ -961,7 +963,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \tif (result >= 0) /* Merge resulted (trivially) in result_oid */\n \t\t/* Update default notes ref with new commit */\n \t\trefs_update_ref(get_main_ref_store(the_repository), msg.buf,\n-\t\t\t\tdefault_notes_ref(), &result_oid, NULL, 0,\n+\t\t\t\tnotes_ref, &result_oid, NULL, 0,\n \t\t\t\tUPDATE_REFS_DIE_ON_ERR);\n \telse { /* Merge has unresolved conflicts */\n \t\tstruct worktree **worktrees;\n@@ -973,14 +975,14 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t\t/* Store ref-to-be-updated into .git/NOTES_MERGE_REF */\n \t\tworktrees = get_worktrees();\n \t\twt = find_shared_symref(worktrees, \"NOTES_MERGE_REF\",\n-\t\t\t\t\tdefault_notes_ref());\n+\t\t\t\t\tnotes_ref);\n \t\tif (wt)\n \t\t\tdie(_(\"a notes merge into %s is already in-progress at %s\"),\n-\t\t\t    default_notes_ref(), wt->path);\n+\t\t\t    notes_ref, wt->path);\n \t\tfree_worktrees(worktrees);\n-\t\tif (refs_update_symref(get_main_ref_store(the_repository), \"NOTES_MERGE_REF\", default_notes_ref(), NULL))\n+\t\tif (refs_update_symref(get_main_ref_store(the_repository), \"NOTES_MERGE_REF\", notes_ref, NULL))\n \t\t\tdie(_(\"failed to store link to current notes ref (%s)\"),\n-\t\t\t    default_notes_ref());\n+\t\t\t    notes_ref);\n \t\tfprintf(stderr, _(\"Automatic notes merge failed. Fix conflicts in %s \"\n \t\t\t\t  \"and commit the result with 'git notes merge --commit', \"\n \t\t\t\t  \"or abort the merge with 'git notes merge --abort'.\\n\"),\n@@ -988,6 +990,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t}\n \n \tfree_notes(t);\n+\tfree(notes_ref);\n \tstrbuf_release(&remote_ref);\n \tstrbuf_release(&msg);\n \treturn result < 0; /* return non-zero on conflicts */\n@@ -1084,6 +1087,7 @@ static int prune(int argc, const char **argv, const char *prefix)\n static int get_ref(int argc, const char **argv, const char *prefix)\n {\n \tstruct option options[] = { OPT_END() };\n+\tchar *notes_ref;\n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_notes_get_ref_usage, 0);\n \n@@ -1092,7 +1096,9 @@ static int get_ref(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(git_notes_get_ref_usage, options);\n \t}\n \n-\tputs(default_notes_ref());\n+\tnotes_ref = default_notes_ref(the_repository);\n+\tputs(notes_ref);\n+\tfree(notes_ref);\n \treturn 0;\n }\n \ndiff --git a/config.c b/config.c\nindex 53c68f3da61..1266eab0860 100644\n--- a/config.c\n+++ b/config.c\n@@ -1555,14 +1555,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn git_config_string(&check_roundtrip_encoding, var, value);\n \t}\n \n-\tif (!strcmp(var, \"core.notesref\")) {\n-\t\tif (!value)\n-\t\t\treturn config_error_nonbool(var);\n-\t\tfree(notes_ref_name);\n-\t\tnotes_ref_name = xstrdup(value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.editor\")) {\n \t\tFREE_AND_NULL(editor_program);\n \t\treturn git_config_string(&editor_program, var, value);\ndiff --git a/environment.c b/environment.c\nindex 9dd000cda36..a2ce9980818 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -67,7 +67,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n-char *notes_ref_name;\n int grafts_keep_true_parents;\n int core_apply_sparse_checkout;\n int core_sparse_checkout_cone;\ndiff --git a/environment.h b/environment.h\nindex aa38133da9c..923e12661e1 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -203,8 +203,6 @@ enum object_creation_mode {\n };\n extern enum object_creation_mode object_creation_mode;\n \n-extern char *notes_ref_name;\n-\n extern int grafts_keep_true_parents;\n \n extern int repository_format_precious_objects;\ndiff --git a/notes.c b/notes.c\nindex da42df282d5..f4f18daf07e 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -992,15 +992,16 @@ static int notes_display_config(const char *k, const char *v,\n \treturn 0;\n }\n \n-const char *default_notes_ref(void)\n+char *default_notes_ref(struct repository *repo)\n {\n-\tconst char *notes_ref = NULL;\n+\tchar *notes_ref = NULL;\n+\n \tif (!notes_ref)\n-\t\tnotes_ref = getenv(GIT_NOTES_REF_ENVIRONMENT);\n+\t\tnotes_ref = xstrdup_or_null(getenv(GIT_NOTES_REF_ENVIRONMENT));\n \tif (!notes_ref)\n-\t\tnotes_ref = notes_ref_name; /* value of core.notesRef config */\n+\t\trepo_config_get_string(repo, \"core.notesref\", &notes_ref);\n \tif (!notes_ref)\n-\t\tnotes_ref = GIT_NOTES_DEFAULT_REF;\n+\t\tnotes_ref = xstrdup(GIT_NOTES_DEFAULT_REF);\n \treturn notes_ref;\n }\n \n@@ -1010,13 +1011,14 @@ void init_notes(struct notes_tree *t, const char *notes_ref,\n \tstruct object_id oid, object_oid;\n \tunsigned short mode;\n \tstruct leaf_node root_tree;\n+\tchar *to_free = NULL;\n \n \tif (!t)\n \t\tt = &default_notes_tree;\n \tassert(!t->initialized);\n \n \tif (!notes_ref)\n-\t\tnotes_ref = default_notes_ref();\n+\t\tnotes_ref = to_free = default_notes_ref(the_repository);\n \tupdate_ref_namespace(NAMESPACE_NOTES, xstrdup(notes_ref));\n \n \tif (!combine_notes)\n@@ -1033,7 +1035,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,\n \n \tif (flags & NOTES_INIT_EMPTY ||\n \t    repo_get_oid_treeish(the_repository, notes_ref, &object_oid))\n-\t\treturn;\n+\t\tgoto out;\n \tif (flags & NOTES_INIT_WRITABLE && refs_read_ref(get_main_ref_store(the_repository), notes_ref, &object_oid))\n \t\tdie(\"Cannot use notes ref %s\", notes_ref);\n \tif (get_tree_entry(the_repository, &object_oid, \"\", &oid, &mode))\n@@ -1043,6 +1045,9 @@ void init_notes(struct notes_tree *t, const char *notes_ref,\n \toidclr(&root_tree.key_oid, the_repository->hash_algo);\n \toidcpy(&root_tree.val_oid, &oid);\n \tload_subtree(t, &root_tree, t->root, 0);\n+\n+out:\n+\tfree(to_free);\n }\n \n struct notes_tree **load_notes_trees(struct string_list *refs, int flags)\n@@ -1105,7 +1110,7 @@ void load_display_notes(struct display_notes_opt *opt)\n \n \tif (!opt || opt->use_default_notes > 0 ||\n \t    (opt->use_default_notes == -1 && !opt->extra_notes_refs.nr)) {\n-\t\tstring_list_append(&display_notes_refs, default_notes_ref());\n+\t\tstring_list_append_nodup(&display_notes_refs, default_notes_ref(the_repository));\n \t\tdisplay_ref_env = getenv(GIT_NOTES_DISPLAY_REF_ENVIRONMENT);\n \t\tif (display_ref_env) {\n \t\t\tstring_list_add_refs_from_colon_sep(&display_notes_refs,\ndiff --git a/notes.h b/notes.h\nindex 235216944bc..6dc6d7b2654 100644\n--- a/notes.h\n+++ b/notes.h\n@@ -4,6 +4,7 @@\n #include \"string-list.h\"\n \n struct object_id;\n+struct repository;\n struct strbuf;\n \n /*\n@@ -70,7 +71,7 @@ extern struct notes_tree {\n  * 3. The value of the core.notesRef config variable, if set\n  * 4. GIT_NOTES_DEFAULT_REF (i.e. \"refs/notes/commits\")\n  */\n-const char *default_notes_ref(void);\n+char *default_notes_ref(struct repository *repo);\n \n /*\n  * Flags controlling behaviour of notes tree initialization\n-- \n2.46.0.421.g159f2d50e7.dirty\n\n"},{"id":"501926","messageId":"xmqqr0a6rmxo.fsf@gitster.g","threadId":"62019","inReplyTo":"ZtFtpjaGFhORNEP4@tanuki","subject":"Re: [PATCH 00/21] environment: guard reliance on `the_repository`","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-30T16:32:35Z","receivedAt":"2024-08-30T16:32:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Thu, Aug 29, 2024 at 12:59:35PM -0700, Junio C Hamano wrote:\n>> There may be more, but I know at least of these at the moment from\n>> https://github.com/git/git/actions/runs/10619536685/job/29437358521\n>> \n>> Perhaps this can become [0.5/21] of the series, before globals are\n>> hidden behind the macro.\n>\n> Thanks, I'll add these. I really need to spend some time to finally get\n> Win32 builds set up in GitLab CI.\n\nWindows builds we can get from GitHub Actions already.  It would be\nnice if somebody had Cygwin, which might have avoided a need for\n<d8c5e920-aff7-4e4b-af77-0d3193466b57@ramsayjones.plus.com>\n\nThanks.\n"},{"id":"501973","messageId":"ZtWFiv-caqIfYLoD@tanuki","threadId":"62019","inReplyTo":"xmqqr0a6rmxo.fsf@gitster.g","subject":"Re: [PATCH 00/21] environment: guard reliance on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-02T09:29:46Z","receivedAt":"2024-09-02T09:29:51Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Aug 30, 2024 at 09:32:35AM -0700, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > On Thu, Aug 29, 2024 at 12:59:35PM -0700, Junio C Hamano wrote:\n> >> There may be more, but I know at least of these at the moment from\n> >> https://github.com/git/git/actions/runs/10619536685/job/29437358521\n> >> \n> >> Perhaps this can become [0.5/21] of the series, before globals are\n> >> hidden behind the macro.\n> >\n> > Thanks, I'll add these. I really need to spend some time to finally get\n> > Win32 builds set up in GitLab CI.\n> \n> Windows builds we can get from GitHub Actions already.  It would be\n> nice if somebody had Cygwin, which might have avoided a need for\n> <d8c5e920-aff7-4e4b-af77-0d3193466b57@ramsayjones.plus.com>\n\nWe already have it, yeah. But as I typically only use GitLab CI, I tend\nto hit the failures on Windows systems when the series is already out\nthere, which requires a roundtrip that would have otherwise been\navoided.\n\nIn any case, having Cygwin added to the mix in addition certainly would\nbe nice.\n\nPatrick\n"},{"id":"502083","messageId":"D3X4D0DUL3TS.1FAOC0KJ08D9L@jamesliu.io","threadId":"62019","inReplyTo":"b8aa5dcc0b67e3957dc65f38b7dc02a97cc096a7.1725008898.git.ps@pks.im","subject":"Re: [PATCH v2 08/21] config: make dependency on repo in `read_early_config()` explicit","fromName":"James Liu","fromEmail":"james@jamesliu.io","sentAt":"2024-09-04T01:46:47Z","receivedAt":"2024-09-04T01:46:57Z","isPatch":true,"sender":{"key":"james@jamesliu.io","avatar":"https://avatars.githubusercontent.com/u/4476568?v=4"},"body":"On Fri Aug 30, 2024 at 7:09 PM AEST, Patrick Steinhardt wrote:\n> diff --git a/config.c b/config.c\n> index a8357ea9544..043e1c8a078 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -6,8 +6,6 @@\n>   *\n>   */\n>  \n> -#define USE_THE_REPOSITORY_VARIABLE\n> -\n>  #include \"git-compat-util.h\"\n>  #include \"abspath.h\"\n>  #include \"advice.h\"\n> @@ -2204,7 +2202,7 @@ static void configset_iter(struct config_set *set, config_fn_t fn, void *data)\n>  \t}\n>  }\n>  \n> -void read_early_config(config_fn_t cb, void *data)\n> +void read_early_config(struct repository *repo, config_fn_t cb, void *data)\n>  {\n>  \tstruct config_options opts = {0};\n>  \tstruct strbuf commondir = STRBUF_INIT;\n> @@ -2212,9 +2210,9 @@ void read_early_config(config_fn_t cb, void *data)\n>  \n>  \topts.respect_includes = 1;\n>  \n> -\tif (have_git_dir()) {\n> -\t\topts.commondir = repo_get_common_dir(the_repository);\n> -\t\topts.git_dir = repo_get_git_dir(the_repository);\n> +\tif (repo && repo->gitdir) {\n> +\t\topts.commondir = repo_get_common_dir(repo);\n> +\t\topts.git_dir = repo_get_git_dir(repo);\n>  \t/*\n>  \t * When setup_git_directory() was not yet asked to discover the\n>  \t * GIT_DIR, we ask discover_git_directory() to figure out whether there\n\nIt doesn't really matter either way since we perform the same checks, but should we do\n\n        if (repo && repo_get_git_dir(repo))\n\ninstead of accessing the field directly?\n\n"},{"id":"502084","messageId":"D3X4VGA5L7JS.KX0H76M2YL2O@jamesliu.io","threadId":"62019","inReplyTo":"fc6fcebf7f737617c635b338e3c0dce10e77881c.1725008898.git.ps@pks.im","subject":"Re: [PATCH v2 20/21] environment: stop storing \"core.warnAmbiguousRefs\" globally","fromName":"James Liu","fromEmail":"james@jamesliu.io","sentAt":"2024-09-04T02:10:53Z","receivedAt":"2024-09-04T02:11:01Z","isPatch":true,"sender":{"key":"james@jamesliu.io","avatar":"https://avatars.githubusercontent.com/u/4476568?v=4"},"body":"On Fri Aug 30, 2024 at 7:09 PM AEST, Patrick Steinhardt wrote:\n> Same as the preceding commits, storing the \"core.warnAmbiguousRefs\"\n> value globally is misdesigned as this setting may be set per repository.\n>\n> Move the logic into the repo-settings subsystem. The usual pattern here\n> is that users are expected to call `prepare_repo_settings()` before they\n> access the settings themselves. This seems somewhat fragile though, as\n> it is easy to miss and leads to somewhat ugly code patterns at the call\n> sites.\n>\n> Instead, introduce a new function that encapsulates this logic for us.\n> This also allows us to change how exactly the lazy initialization works\n> in the future, e.g. by only partially initializing values as requested\n> by the caller.\n\nCool! `prepare_repo_settings()` is safe (and seems also reasonably cheap)\nto execute multiple times.\n\n"},{"id":"502085","messageId":"D3X4X0B5P0WG.1WHNSQNIRDHYW@jamesliu.io","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"Re: [PATCH v2 00/21] environment: guard reliance on `the_repository`","fromName":"James Liu","fromEmail":"james@jamesliu.io","sentAt":"2024-09-04T02:12:54Z","receivedAt":"2024-09-04T02:13:05Z","isPatch":true,"sender":{"key":"james@jamesliu.io","avatar":"https://avatars.githubusercontent.com/u/4476568?v=4"},"body":"On Fri Aug 30, 2024 at 7:08 PM AEST, Patrick Steinhardt wrote:\n> Hi,\n>\n> this is the second version of my patch series which guards functions and\n> variables in the environment subsystem that rely on `the_repository`\n> with the `USE_THE_REPOSITORY_VARIABLE` define.\n>\n> Changes compared to v1:\n>\n>   - Clean up now-unnecessary and add newly-necessary includes.\n>\n>   - Stop reordering includes in \"setup.c\".\n>\n>   - Fix missing `USE_THE_REPOSITORY_VARIABLE` defines in Win32 code.\n>\n> Thanks!\n>\n> Patrick\n\nThanks Patrick, this is a nice series of cleanups! I've left a few\ncomments.\n\nApologies that I haven't been able to review these changes until now --\nI've had to take some time off in the past week.\n\nCheers,\nJames\n"},{"id":"502095","messageId":"ZtgIyjGnpwX3VvYP@pks.im","threadId":"62019","inReplyTo":"D3X4D0DUL3TS.1FAOC0KJ08D9L@jamesliu.io","subject":"Re: [PATCH v2 08/21] config: make dependency on repo in `read_early_config()` explicit","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-04T07:14:18Z","receivedAt":"2024-09-04T07:14:22Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Sep 04, 2024 at 11:46:47AM +1000, James Liu wrote:\n> On Fri Aug 30, 2024 at 7:09 PM AEST, Patrick Steinhardt wrote:\n> > diff --git a/config.c b/config.c\n> > index a8357ea9544..043e1c8a078 100644\n> > --- a/config.c\n> > +++ b/config.c\n> > @@ -6,8 +6,6 @@\n> >   *\n> >   */\n> >  \n> > -#define USE_THE_REPOSITORY_VARIABLE\n> > -\n> >  #include \"git-compat-util.h\"\n> >  #include \"abspath.h\"\n> >  #include \"advice.h\"\n> > @@ -2204,7 +2202,7 @@ static void configset_iter(struct config_set *set, config_fn_t fn, void *data)\n> >  \t}\n> >  }\n> >  \n> > -void read_early_config(config_fn_t cb, void *data)\n> > +void read_early_config(struct repository *repo, config_fn_t cb, void *data)\n> >  {\n> >  \tstruct config_options opts = {0};\n> >  \tstruct strbuf commondir = STRBUF_INIT;\n> > @@ -2212,9 +2210,9 @@ void read_early_config(config_fn_t cb, void *data)\n> >  \n> >  \topts.respect_includes = 1;\n> >  \n> > -\tif (have_git_dir()) {\n> > -\t\topts.commondir = repo_get_common_dir(the_repository);\n> > -\t\topts.git_dir = repo_get_git_dir(the_repository);\n> > +\tif (repo && repo->gitdir) {\n> > +\t\topts.commondir = repo_get_common_dir(repo);\n> > +\t\topts.git_dir = repo_get_git_dir(repo);\n> >  \t/*\n> >  \t * When setup_git_directory() was not yet asked to discover the\n> >  \t * GIT_DIR, we ask discover_git_directory() to figure out whether there\n> \n> It doesn't really matter either way since we perform the same checks, but should we do\n> \n>         if (repo && repo_get_git_dir(repo))\n> \n> instead of accessing the field directly?\n\nWe in fact can't. `read_early_config()` is typically invoked with the\nglobal `the_repository`. That variable is always set, but its `git_dir`\nmay not be populated depending on when exactly we call this function and\nwhether or not we are inside a repository. With `repo_get_git_dir()`\nwe'd now die in scenarios where it's unset, which we do not want.\n\nPatrick\n"},{"id":"502096","messageId":"ZtgIzZlyOkgtXjnC@pks.im","threadId":"62019","inReplyTo":"D3X4X0B5P0WG.1WHNSQNIRDHYW@jamesliu.io","subject":"Re: [PATCH v2 00/21] environment: guard reliance on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-04T07:14:21Z","receivedAt":"2024-09-04T07:14:25Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Sep 04, 2024 at 12:12:54PM +1000, James Liu wrote:\n> On Fri Aug 30, 2024 at 7:08 PM AEST, Patrick Steinhardt wrote:\n> > Hi,\n> >\n> > this is the second version of my patch series which guards functions and\n> > variables in the environment subsystem that rely on `the_repository`\n> > with the `USE_THE_REPOSITORY_VARIABLE` define.\n> >\n> > Changes compared to v1:\n> >\n> >   - Clean up now-unnecessary and add newly-necessary includes.\n> >\n> >   - Stop reordering includes in \"setup.c\".\n> >\n> >   - Fix missing `USE_THE_REPOSITORY_VARIABLE` defines in Win32 code.\n> >\n> > Thanks!\n> >\n> > Patrick\n> \n> Thanks Patrick, this is a nice series of cleanups! I've left a few\n> comments.\n> \n> Apologies that I haven't been able to review these changes until now --\n> I've had to take some time off in the past week.\n\nNo worries, thanks for your review!\n\nPatrick\n"},{"id":"502622","messageId":"wnorpwj5stwekbdvqzz6oyom5ppqhcsg3afvujslmy45r2djdb@sn6voa5d2e5v","threadId":"62019","inReplyTo":"22e9dcb28a981eaa1a37a8b41e8d061347ed6c2e.1725008898.git.ps@pks.im","subject":"Re: [PATCH v2 06/21] environment: make `get_git_work_tree()` accept a repository","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-09-11T15:15:06Z","receivedAt":"2024-09-11T15:16:21Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/30 11:09AM, Patrick Steinhardt wrote:\n> The `get_git_work_tree()` function retrieves the path of the work tree\n> of `the_repository`. Make it accept a `struct repository` such that it\n> can work on arbitrary repositories and make it part of the repository\n> subsystem. This reduces our reliance on `the_repository` and clarifies\n> scope.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n[snip]\n> diff --git a/repository.c b/repository.c\n> index cdefcb4002d..92238da3d9e 100644\n> --- a/repository.c\n> +++ b/repository.c\n> @@ -126,6 +126,11 @@ const char *repo_get_graft_file(struct repository *repo)\n>  \treturn repo->graft_file;\n>  }\n>  \n> +const char *repo_get_work_tree(struct repository *repo)\n> +{\n> +\treturn repo->worktree;\n> +}\n> +\n\nNow that `repo_get_work_tree()` is accepting a `struct repository`, it's\nonly functioning as a simple accessor and seems somewhat unneccesary. Is\nit preferrable to keep this?\n\n-Justin\n"},{"id":"502632","messageId":"q4bmhi7dhadwhhuijatrpiayi7zjhrlgshcgucfp2s7uiczkth@o4jtzzqv2dmt","threadId":"62019","inReplyTo":"ec4804a99bf70f9a97d1faea60bd55aaa97d1b80.1725008898.git.ps@pks.im","subject":"Re: [PATCH v2 07/21] config: document `read_early_config()` and `read_very_early_config()`","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-09-11T15:59:42Z","receivedAt":"2024-09-11T16:00:57Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/30 11:09AM, Patrick Steinhardt wrote:\n> It's not clear what `read_early_config()` and `read_very_early_config()`\n> do differently compared to `repo_read_config()` from just looking at\n> their names. Document both of these in the header file to clarify their\n> intent.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  config.c |  4 ----\n>  config.h | 11 +++++++++++\n>  2 files changed, 11 insertions(+), 4 deletions(-)\n> \n> diff --git a/config.c b/config.c\n> index 0b87f0f9050..a8357ea9544 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -2234,10 +2234,6 @@ void read_early_config(config_fn_t cb, void *data)\n>  \tstrbuf_release(&gitdir);\n>  }\n>  \n> -/*\n> - * Read config but only enumerate system and global settings.\n> - * Omit any repo-local, worktree-local, or command-line settings.\n> - */\n>  void read_very_early_config(config_fn_t cb, void *data)\n>  {\n>  \tstruct config_options opts = { 0 };\n> diff --git a/config.h b/config.h\n> index d0497157c52..f5fa833cb98 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -192,7 +192,18 @@ int git_config_from_blob_oid(config_fn_t fn, const char *name,\n>  void git_config_push_parameter(const char *text);\n>  void git_config_push_env(const char *spec);\n>  int git_config_from_parameters(config_fn_t fn, void *data);\n> +\n> +/*\n> + * Read config when the Git directory has not yet been set up. In case\n> + * `the_repository` has not yet been set up, try to discover the Git\n> + * directory to read the configuration from.\n> + */\n>  void read_early_config(config_fn_t cb, void *data);\n\nTo restate in my own words, `read_early_config()` allows a config to be\nread before `the_repository` is setup by discovering the git dir itself.\nOut of curiousity, what prevents us from just ensuring `the_repository`\nis properly setup first?\n\n> +\n> +/*\n> + * Read config but only enumerate system and global settings.\n> + * Omit any repo-local, worktree-local, or command-line settings.\n> + */\n>  void read_very_early_config(config_fn_t cb, void *data);\n\nHere `read_very_early_config()` looks like it only cares about system\nand global configuration so it doesn't require a git dir or\n`the_repository` to be set up. Makes sense.\n\nNot really related to this change, but it would be nice if the name of\nthe function itself was more descript. Something like\n`config_read_system_and_global()`.\n\nOverall, I find these new comments to be very helpful. Thanks! :)\n"},{"id":"502633","messageId":"otvkxgywps6smoib32x4gqiwc4klbjl6qbh66bh6wwwfvb2b2p@22gqczmx3p3e","threadId":"62019","inReplyTo":"f0d3794dfc44cd4393fd79fab9f60b73cf33db89.1725008898.git.ps@pks.im","subject":"Re: [PATCH v2 10/21] environment: make `get_git_namespace()` self-contained","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-09-11T16:21:32Z","receivedAt":"2024-09-11T16:22:47Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/30 11:09AM, Patrick Steinhardt wrote:\n> The logic to set up and retrieve `git_namespace` is distributed across\n> different functions which communicate with each other via a global\n> environment variable. This is rather pointless though, as the value is\n> always derived from an environment variable, and this environment\n> variable does not change after we have parsed global options.\n> \n> Convert the function to be fully self-contained such that it lazily\n> populates once called.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n[snip]\n> @@ -229,9 +204,35 @@ int have_git_dir(void)\n>  \n>  const char *get_git_namespace(void)\n>  {\n> -\tif (!git_namespace)\n> -\t\tBUG(\"git environment hasn't been setup\");\n> -\treturn git_namespace;\n> +\tstatic const char *namespace;\n> +\n> +\tstruct strbuf buf = STRBUF_INIT;\n> +\tstruct strbuf **components, **c;\n> +\tconst char *raw_namespace;\n> +\n> +\tif (namespace)\n> +\t\treturn namespace;\n\nWe only initialize `namespace` once and do it lazily when\n`get_git_namespace()` is invoked for the first time. This is nice\nbecause we can simplify and remove the `git_namespace` global.\n\nMakes sense to me.\n\n> +\n> +\traw_namespace = getenv(GIT_NAMESPACE_ENVIRONMENT);\n> +\tif (!raw_namespace || !*raw_namespace) {\n> +\t\tnamespace = \"\";\n> +\t\treturn namespace;\n> +\t}\n> +\n> +\tstrbuf_addstr(&buf, raw_namespace);\n> +\tcomponents = strbuf_split(&buf, '/');\n> +\tstrbuf_reset(&buf);\n> +\tfor (c = components; *c; c++)\n> +\t\tif (strcmp((*c)->buf, \"/\") != 0)\n> +\t\t\tstrbuf_addf(&buf, \"refs/namespaces/%s\", (*c)->buf);\n> +\tstrbuf_list_free(components);\n> +\tif (check_refname_format(buf.buf, 0))\n> +\t\tdie(_(\"bad git namespace path \\\"%s\\\"\"), raw_namespace);\n> +\tstrbuf_addch(&buf, '/');\n> +\n> +\tnamespace = strbuf_detach(&buf, NULL);\n> +\n> +\treturn namespace;\n>  }\n>  \n>  const char *strip_namespace(const char *namespaced_ref)\n> -- \n> 2.46.0.421.g159f2d50e7.dirty\n> \n"},{"id":"502636","messageId":"6hoykgw3gm5hchmtfaci6gwwha6iouidtqvupx55vsjfoedquo@nfgaumnmu4po","threadId":"62019","inReplyTo":"fc30365e1f13d47eb89339603f6a4744525b3967.1725008898.git.ps@pks.im","subject":"Re: [PATCH v2 16/21] branch: stop modifying `log_all_ref_updates` variable","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-09-11T17:14:55Z","receivedAt":"2024-09-11T17:16:11Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/30 11:09AM, Patrick Steinhardt wrote:\n> In \"branch.c\" we modify the global `log_all_ref_updates` variable to\n> force creation of a reflog entry. Modifying global state like this is\n> discouraged, as it may have all kinds of consequences in other places of\n> our codebase.\n> \n> Stop modifying the variable and pass the `REF_FORCE_CREATE_REFLOG` flag,\n> which has the same effect.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  branch.c | 5 +++--\n>  1 file changed, 3 insertions(+), 2 deletions(-)\n> \n> diff --git a/branch.c b/branch.c\n> index c887ea21514..08fa4094d2b 100644\n> --- a/branch.c\n> +++ b/branch.c\n> @@ -601,6 +601,7 @@ void create_branch(struct repository *r,\n>  \tint forcing = 0;\n>  \tstruct ref_transaction *transaction;\n>  \tstruct strbuf err = STRBUF_INIT;\n> +\tint flags = 0;\n>  \tchar *msg;\n>  \n>  \tif (track == BRANCH_TRACK_OVERRIDE)\n> @@ -619,7 +620,7 @@ void create_branch(struct repository *r,\n>  \t\tgoto cleanup;\n>  \n>  \tif (reflog)\n> -\t\tlog_all_ref_updates = LOG_REFS_NORMAL;\n> +\t\tflags |= REF_FORCE_CREATE_REFLOG;\n\nI'm trying to understand how setting the `REF_FORCE_CREATE_REFLOG` flag\nis ultimately equivalent to setting `log_all_ref_updates =\nLOG_REFS_NORMAL`.\n\nFrom my understanding, when `log_all_ref_updates` is set to\n`LOG_REFS_NORMAL`, this is the equivalent to\n`core.logAllRefUpdates=true`. This means if a missing reflog file is\ncreated for a subset of references[1]. The `REF_FORCE_CREATE_REFLOG`\nflag seems more analogous to `always` value for `core.logAllRefUpdates`\nand would create reflogs for all references. Is this not the case? Or\ndoes it not really matter?\n\n[1] https://git-scm.com/docs/git-config#Documentation/git-config.txt-corelogAllRefUpdates\n\n>  \n>  \tif (forcing)\n>  \t\tmsg = xstrfmt(\"branch: Reset to %s\", start_name);\n> @@ -630,7 +631,7 @@ void create_branch(struct repository *r,\n>  \tif (!transaction ||\n>  \t\tref_transaction_update(transaction, ref.buf,\n>  \t\t\t\t\t&oid, forcing ? NULL : null_oid(),\n> -\t\t\t\t\tNULL, NULL, 0, msg, &err) ||\n> +\t\t\t\t\tNULL, NULL, flags, msg, &err) ||\n>  \t\tref_transaction_commit(transaction, &err))\n>  \t\tdie(\"%s\", err.buf);\n>  \tref_transaction_free(transaction);\n> -- \n> 2.46.0.421.g159f2d50e7.dirty\n> \n"},{"id":"502642","messageId":"CAOLa=ZQxVtFrZqFJ+Q+0ifj5h+x-7-ZE6viD9OUyNr2CvE7s-A@mail.gmail.com","threadId":"62019","inReplyTo":"a1969c5b0734cacd0316c34ef3d3b1939f521cd4.1725008898.git.ps@pks.im","subject":"Re: [PATCH v2 01/21] environment: make `get_git_dir()` accept a repository","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2024-09-11T21:12:51Z","receivedAt":"2024-09-11T21:12:53Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n[snip]\n\n> diff --git a/repository.c b/repository.c\n> index 9825a308993..6f43f2e8344 100644\n> --- a/repository.c\n> +++ b/repository.c\n> @@ -91,6 +91,13 @@ static void expand_base_dir(char **out, const char *in,\n>  \t\t*out = xstrfmt(\"%s/%s\", base_dir, def_in);\n>  }\n>\n> +const char *repo_get_git_dir(struct repository *repo)\n> +{\n> +\tif (!repo->gitdir)\n> +\t\tBUG(\"git environment hasn't been setup\");\n\nShouldn't this message be more generic now? Since this function can be\nused with any repository?\n\n> +\treturn repo->gitdir;\n> +}\n> +\n>  static void repo_set_commondir(struct repository *repo,\n>  \t\t\t       const char *commondir)\n>  {\n\n[snip]\n\nRest of the patch looks good. Thanks\n"},{"id":"502644","messageId":"CAOLa=ZQLd4M_CmjnJBg2ht-U9sa21bq5=WgXn7RWe2cWpZx5zQ@mail.gmail.com","threadId":"62019","inReplyTo":"ac2cc4e03719ecf6d6a2eb4aacb8a162429addb0.1725008898.git.ps@pks.im","subject":"Re: [PATCH v2 09/21] environment: move `odb_mkstemp()` into object layer","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2024-09-11T21:26:42Z","receivedAt":"2024-09-11T21:26:43Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> The `odb_mkstemp()` function is quite clearly tied to the object store,\n> but regardless of that it is located in \"environment.c\". Move it over,\n> which also helps to get rid of dependencies on `the_repository` in the\n> environment subsystem.\n>\n\nThe commit talks only about `odb_mkstemp()` but the code also moves\n`odb_pack_keep`. We should add that here.\n\n[snip]\n"},{"id":"502674","messageId":"CAOLa=ZSzBadik1cOYvVj0zmf6-gQgn7x3GXvPiJwgzE=2p0T+w@mail.gmail.com","threadId":"62019","inReplyTo":"b5ed6928070ca02463bf53d339aba47bbf25e86a.1725008898.git.ps@pks.im","subject":"Re: [PATCH v2 18/21] environment: stop storing \"core.logAllRefUpdates\" globally","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2024-09-12T11:10:01Z","receivedAt":"2024-09-12T11:10:03Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n[snip]\n\n> diff --git a/refs/files-backend.c b/refs/files-backend.c\n> index f5871abcf75..a536d7d1b57 100644\n> --- a/refs/files-backend.c\n> +++ b/refs/files-backend.c\n> @@ -75,6 +75,7 @@ struct files_ref_store {\n>  \tunsigned int store_flags;\n>\n>  \tchar *gitcommondir;\n> +\tenum log_refs_config log_all_ref_updates;\n>\n\nSo we add it to the backend's store and set it when the backend is\ninitiated. Makes sense\n\n[snip]\n"},{"id":"502675","messageId":"CAOLa=ZQ20ndA6cG8_9OHO-Ci5AHu5i2K6O+2hJ8oa6+nhxaPZA@mail.gmail.com","threadId":"62019","inReplyTo":"cover.1725008897.git.ps@pks.im","subject":"Re: [PATCH v2 00/21] environment: guard reliance on `the_repository`","fromName":"karthik nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2024-09-12T11:14:53Z","receivedAt":"2024-09-12T11:14:55Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> Hi,\n>\n> this is the second version of my patch series which guards functions and\n> variables in the environment subsystem that rely on `the_repository`\n> with the `USE_THE_REPOSITORY_VARIABLE` define.\n>\n> Changes compared to v1:\n>\n>   - Clean up now-unnecessary and add newly-necessary includes.\n>\n>   - Stop reordering includes in \"setup.c\".\n>\n>   - Fix missing `USE_THE_REPOSITORY_VARIABLE` defines in Win32 code.\n>\n> Thanks!\n>\n\nI haven't read v1, but this version reads nicely. I left two comments,\nand I think the first one applies to the first few patches.\n\nThanks\n\n[snip]\n"},{"id":"502676","messageId":"ZuLNjhWtNpO6T8Bs@pks.im","threadId":"62019","inReplyTo":"wnorpwj5stwekbdvqzz6oyom5ppqhcsg3afvujslmy45r2djdb@sn6voa5d2e5v","subject":"Re: [PATCH v2 06/21] environment: make `get_git_work_tree()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:16:59Z","receivedAt":"2024-09-12T11:17:04Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Sep 11, 2024 at 10:15:06AM -0500, Justin Tobler wrote:\n> On 24/08/30 11:09AM, Patrick Steinhardt wrote:\n> > The `get_git_work_tree()` function retrieves the path of the work tree\n> > of `the_repository`. Make it accept a `struct repository` such that it\n> > can work on arbitrary repositories and make it part of the repository\n> > subsystem. This reduces our reliance on `the_repository` and clarifies\n> > scope.\n> > \n> > Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> > ---\n> [snip]\n> > diff --git a/repository.c b/repository.c\n> > index cdefcb4002d..92238da3d9e 100644\n> > --- a/repository.c\n> > +++ b/repository.c\n> > @@ -126,6 +126,11 @@ const char *repo_get_graft_file(struct repository *repo)\n> >  \treturn repo->graft_file;\n> >  }\n> >  \n> > +const char *repo_get_work_tree(struct repository *repo)\n> > +{\n> > +\treturn repo->worktree;\n> > +}\n> > +\n> \n> Now that `repo_get_work_tree()` is accepting a `struct repository`, it's\n> only functioning as a simple accessor and seems somewhat unneccesary. Is\n> it preferrable to keep this?\n\nI think it still makes sense to keep it, mostly because we also have\naccessor functions for the other paths, too. It would feel weirdly\nasymmetric to have `repo_get_git_dir()` but not `repo_get_work_tree()`,\nin my opinion.\n\nPatrick\n"},{"id":"502677","messageId":"ZuLNsC7akB64OPpa@pks.im","threadId":"62019","inReplyTo":"q4bmhi7dhadwhhuijatrpiayi7zjhrlgshcgucfp2s7uiczkth@o4jtzzqv2dmt","subject":"Re: [PATCH v2 07/21] config: document `read_early_config()` and `read_very_early_config()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:17:04Z","receivedAt":"2024-09-12T11:17:07Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Sep 11, 2024 at 10:59:42AM -0500, Justin Tobler wrote:\n> On 24/08/30 11:09AM, Patrick Steinhardt wrote:\n> > It's not clear what `read_early_config()` and `read_very_early_config()`\n> > do differently compared to `repo_read_config()` from just looking at\n> > their names. Document both of these in the header file to clarify their\n> > intent.\n> > \n> > Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> > ---\n> >  config.c |  4 ----\n> >  config.h | 11 +++++++++++\n> >  2 files changed, 11 insertions(+), 4 deletions(-)\n> > \n> > diff --git a/config.c b/config.c\n> > index 0b87f0f9050..a8357ea9544 100644\n> > --- a/config.c\n> > +++ b/config.c\n> > @@ -2234,10 +2234,6 @@ void read_early_config(config_fn_t cb, void *data)\n> >  \tstrbuf_release(&gitdir);\n> >  }\n> >  \n> > -/*\n> > - * Read config but only enumerate system and global settings.\n> > - * Omit any repo-local, worktree-local, or command-line settings.\n> > - */\n> >  void read_very_early_config(config_fn_t cb, void *data)\n> >  {\n> >  \tstruct config_options opts = { 0 };\n> > diff --git a/config.h b/config.h\n> > index d0497157c52..f5fa833cb98 100644\n> > --- a/config.h\n> > +++ b/config.h\n> > @@ -192,7 +192,18 @@ int git_config_from_blob_oid(config_fn_t fn, const char *name,\n> >  void git_config_push_parameter(const char *text);\n> >  void git_config_push_env(const char *spec);\n> >  int git_config_from_parameters(config_fn_t fn, void *data);\n> > +\n> > +/*\n> > + * Read config when the Git directory has not yet been set up. In case\n> > + * `the_repository` has not yet been set up, try to discover the Git\n> > + * directory to read the configuration from.\n> > + */\n> >  void read_early_config(config_fn_t cb, void *data);\n> \n> To restate in my own words, `read_early_config()` allows a config to be\n> read before `the_repository` is setup by discovering the git dir itself.\n> Out of curiousity, what prevents us from just ensuring `the_repository`\n> is properly setup first?\n\nThis function is mostly called when we may or may not have a repository.\nThis is for example important for alias handling: we want aliases to\nwork when outside a repository, and they are not yet set up at the point\nin time where we need to resolve such an alias. If you happen to be in a\nrepository, you also want to make its aliases available. If you aren't,\nyou only want to make aliases in your global and system configuration\navailable.\n\n> > +\n> > +/*\n> > + * Read config but only enumerate system and global settings.\n> > + * Omit any repo-local, worktree-local, or command-line settings.\n> > + */\n> >  void read_very_early_config(config_fn_t cb, void *data);\n> \n> Here `read_very_early_config()` looks like it only cares about system\n> and global configuration so it doesn't require a git dir or\n> `the_repository` to be set up. Makes sense.\n> \n> Not really related to this change, but it would be nice if the name of\n> the function itself was more descript. Something like\n> `config_read_system_and_global()`.\n> \n> Overall, I find these new comments to be very helpful. Thanks! :)\n\nAgreed, the names aren't great. But as you say, I'd rather not fix them\nas part of this patch series.\n\nPatrick\n"},{"id":"502678","messageId":"ZuLNtdd_jIbJaZZE@pks.im","threadId":"62019","inReplyTo":"CAOLa=ZQxVtFrZqFJ+Q+0ifj5h+x-7-ZE6viD9OUyNr2CvE7s-A@mail.gmail.com","subject":"Re: [PATCH v2 01/21] environment: make `get_git_dir()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:17:09Z","receivedAt":"2024-09-12T11:17:11Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Sep 11, 2024 at 02:12:51PM -0700, karthik nayak wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> [snip]\n> \n> > diff --git a/repository.c b/repository.c\n> > index 9825a308993..6f43f2e8344 100644\n> > --- a/repository.c\n> > +++ b/repository.c\n> > @@ -91,6 +91,13 @@ static void expand_base_dir(char **out, const char *in,\n> >  \t\t*out = xstrfmt(\"%s/%s\", base_dir, def_in);\n> >  }\n> >\n> > +const char *repo_get_git_dir(struct repository *repo)\n> > +{\n> > +\tif (!repo->gitdir)\n> > +\t\tBUG(\"git environment hasn't been setup\");\n> \n> Shouldn't this message be more generic now? Since this function can be\n> used with any repository?\n\nGood point indeed. I was initially worried that changing it may alter\nuser-visible behaviour. But in theory, calls to `BUG()` should be\nunreachable and thus never be encountered in the wild.\n\nPatrick\n"},{"id":"502679","messageId":"ZuLNuaSyamvleWu2@pks.im","threadId":"62019","inReplyTo":"CAOLa=ZQLd4M_CmjnJBg2ht-U9sa21bq5=WgXn7RWe2cWpZx5zQ@mail.gmail.com","subject":"Re: [PATCH v2 09/21] environment: move `odb_mkstemp()` into object layer","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:17:13Z","receivedAt":"2024-09-12T11:17:15Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Sep 11, 2024 at 02:26:42PM -0700, karthik nayak wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > The `odb_mkstemp()` function is quite clearly tied to the object store,\n> > but regardless of that it is located in \"environment.c\". Move it over,\n> > which also helps to get rid of dependencies on `the_repository` in the\n> > environment subsystem.\n> >\n> \n> The commit talks only about `odb_mkstemp()` but the code also moves\n> `odb_pack_keep`. We should add that here.\n\nTrue, will fix.\n\nPatrick\n"},{"id":"502680","messageId":"ZuLNwFIW2CQuHTI4@pks.im","threadId":"62019","inReplyTo":"6hoykgw3gm5hchmtfaci6gwwha6iouidtqvupx55vsjfoedquo@nfgaumnmu4po","subject":"Re: [PATCH v2 16/21] branch: stop modifying `log_all_ref_updates` variable","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:17:20Z","receivedAt":"2024-09-12T11:17:23Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Sep 11, 2024 at 12:14:55PM -0500, Justin Tobler wrote:\n> On 24/08/30 11:09AM, Patrick Steinhardt wrote:\n> > In \"branch.c\" we modify the global `log_all_ref_updates` variable to\n> > force creation of a reflog entry. Modifying global state like this is\n> > discouraged, as it may have all kinds of consequences in other places of\n> > our codebase.\n> > \n> > Stop modifying the variable and pass the `REF_FORCE_CREATE_REFLOG` flag,\n> > which has the same effect.\n> > \n> > Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> > ---\n> >  branch.c | 5 +++--\n> >  1 file changed, 3 insertions(+), 2 deletions(-)\n> > \n> > diff --git a/branch.c b/branch.c\n> > index c887ea21514..08fa4094d2b 100644\n> > --- a/branch.c\n> > +++ b/branch.c\n> > @@ -601,6 +601,7 @@ void create_branch(struct repository *r,\n> >  \tint forcing = 0;\n> >  \tstruct ref_transaction *transaction;\n> >  \tstruct strbuf err = STRBUF_INIT;\n> > +\tint flags = 0;\n> >  \tchar *msg;\n> >  \n> >  \tif (track == BRANCH_TRACK_OVERRIDE)\n> > @@ -619,7 +620,7 @@ void create_branch(struct repository *r,\n> >  \t\tgoto cleanup;\n> >  \n> >  \tif (reflog)\n> > -\t\tlog_all_ref_updates = LOG_REFS_NORMAL;\n> > +\t\tflags |= REF_FORCE_CREATE_REFLOG;\n> \n> I'm trying to understand how setting the `REF_FORCE_CREATE_REFLOG` flag\n> is ultimately equivalent to setting `log_all_ref_updates =\n> LOG_REFS_NORMAL`.\n> \n> From my understanding, when `log_all_ref_updates` is set to\n> `LOG_REFS_NORMAL`, this is the equivalent to\n> `core.logAllRefUpdates=true`. This means if a missing reflog file is\n> created for a subset of references[1]. The `REF_FORCE_CREATE_REFLOG`\n> flag seems more analogous to `always` value for `core.logAllRefUpdates`\n> and would create reflogs for all references. Is this not the case? Or\n> does it not really matter?\n> \n> [1] https://git-scm.com/docs/git-config#Documentation/git-config.txt-corelogAllRefUpdates\n\nIt's not equivalent in general, but in this case it is. Note that we are\nonly talking about branches here, not about arbitrary references.\nQuoting \"core.logAllRefUpdates\":\n\n    If this configuration variable is set to true, missing\n    \"$GIT_DIR/logs/<ref>\" file is automatically created for branch heads\n    (i.e. under refs/heads/), remote refs (i.e. under refs/remotes/),\n    note refs (i.e. under refs/notes/), and the symbolic ref HEAD. If it\n    is set to always, then a missing reflog is automatically created for\n    any ref under refs/.\n\nSo for branches, \"true\" and \"always\" have the same effect on the\ntechnical level.\n\nAnd on the conceptual level, `reflog` is set whenever \"--create-reflog\"\nis passed to git-branch(1), and asks the command to cretae the reflog\nregardless of \"core.logAllRefUpdates\".\n\nI'll add this information to the commit message.\n\nThanks for your review!\n\nPatrick\n"},{"id":"502681","messageId":"ZuLN1Eq0SqncdteD@pks.im","threadId":"62019","inReplyTo":"CAOLa=ZQ20ndA6cG8_9OHO-Ci5AHu5i2K6O+2hJ8oa6+nhxaPZA@mail.gmail.com","subject":"Re: [PATCH v2 00/21] environment: guard reliance on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:17:40Z","receivedAt":"2024-09-12T11:17:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Sep 12, 2024 at 04:14:53AM -0700, karthik nayak wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > Hi,\n> >\n> > this is the second version of my patch series which guards functions and\n> > variables in the environment subsystem that rely on `the_repository`\n> > with the `USE_THE_REPOSITORY_VARIABLE` define.\n> >\n> > Changes compared to v1:\n> >\n> >   - Clean up now-unnecessary and add newly-necessary includes.\n> >\n> >   - Stop reordering includes in \"setup.c\".\n> >\n> >   - Fix missing `USE_THE_REPOSITORY_VARIABLE` defines in Win32 code.\n> >\n> > Thanks!\n> >\n> \n> I haven't read v1, but this version reads nicely. I left two comments,\n> and I think the first one applies to the first few patches.\n> \n> Thanks\n\nThanks for your review!\n\nPatrick\n"},{"id":"502684","messageId":"cover.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1724923648.git.ps@pks.im","subject":"[PATCH v3 00/21] environment: guard reliance on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:21Z","receivedAt":"2024-09-12T11:29:25Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis is the third version of my patch series which guards functions and\nvariables in the environment subsystem that rely on `the_repository`\nwith the `USE_THE_REPOSITORY_VARIABLE` define.\n\nChanges compared to v2:\n\n  - Adapt BUG messages in the first 5 commits to better match the new\n    semantics of this function.\n\n  - Adapt commit message to mention that we don't only move over\n    `odb_mkstemp()`, but also `odb_pack_keep()`.\n\n  - Explain why setting REF_FORCE_CREATE_REFLOG is equivalent to setting\n    LOG_REFS_NORMAL.\n\nThanks!\n\nPatrick\n\nPatrick Steinhardt (21):\n  environment: make `get_git_dir()` accept a repository\n  environment: make `get_git_common_dir()` accept a repository\n  environment: make `get_object_directory()` accept a repository\n  environment: make `get_index_file()` accept a repository\n  environment: make `get_graft_file()` accept a repository\n  environment: make `get_git_work_tree()` accept a repository\n  config: document `read_early_config()` and `read_very_early_config()`\n  config: make dependency on repo in `read_early_config()` explicit\n  environment: move object database functions into object layer\n  environment: make `get_git_namespace()` self-contained\n  environment: move `set_git_dir()` and related into setup layer\n  environment: reorder header to split out `the_repository`-free section\n  environment: guard state depending on a repository\n  repo-settings: split out declarations into a standalone header\n  repo-settings: track defaults close to `struct repo_settings`\n  branch: stop modifying `log_all_ref_updates` variable\n  refs: stop modifying global `log_all_ref_updates` variable\n  environment: stop storing \"core.logAllRefUpdates\" globally\n  environment: stop storing \"core.preferSymlinkRefs\" globally\n  environment: stop storing \"core.warnAmbiguousRefs\" globally\n  environment: stop storing \"core.notesRef\" globally\n\n alias.c                     |   6 +-\n apply.c                     |   3 +-\n branch.c                    |   5 +-\n builtin/am.c                |  13 +-\n builtin/blame.c             |   2 +-\n builtin/checkout.c          |   5 +-\n builtin/commit-graph.c      |   5 +-\n builtin/commit.c            |  13 +-\n builtin/config.c            |   4 +-\n builtin/count-objects.c     |   3 +-\n builtin/difftool.c          |   9 +-\n builtin/fsmonitor--daemon.c |   7 +-\n builtin/gc.c                |   2 +-\n builtin/init-db.c           |   4 +-\n builtin/merge.c             |  18 +--\n builtin/multi-pack-index.c  |   4 +-\n builtin/notes.c             |  22 ++--\n builtin/pack-objects.c      |   2 +-\n builtin/prune.c             |   8 +-\n builtin/repack.c            |   7 +-\n builtin/replace.c           |   3 +-\n builtin/reset.c             |   5 +-\n builtin/rev-parse.c         |  11 +-\n builtin/stash.c             |  17 +--\n builtin/submodule--helper.c |   2 +-\n builtin/update-index.c      |   4 +-\n builtin/worktree.c          |   4 +-\n builtin/write-tree.c        |   4 +-\n bulk-checkin.c              |   4 +-\n bundle-uri.c                |   2 +-\n cache-tree.c                |   5 +-\n commit.c                    |   4 +-\n compat/mingw.c              |   2 +\n compat/win32/path-utils.c   |   2 +\n config.c                    |  42 +------\n config.h                    |  13 +-\n dir.c                       |   3 +-\n environment.c               | 237 +++++-------------------------------\n environment.h               | 142 ++++++++++-----------\n fetch-pack.c                |   2 +-\n fsmonitor.c                 |   3 +-\n help.c                      |   2 +-\n http-backend.c              |   2 +-\n name-hash.c                 |   3 +\n notes.c                     |  21 ++--\n notes.h                     |   3 +-\n object-file.c               |  37 +++++-\n object-name.c               |   5 +-\n object-store-ll.h           |  15 +++\n pack-write.c                |   3 +-\n packfile.c                  |   2 +-\n pager.c                     |   7 +-\n path.c                      |   2 +\n pathspec.c                  |   4 +-\n preload-index.c             |   3 +\n prompt.c                    |   2 +\n prune-packed.c              |   6 +-\n read-cache.c                |   6 +-\n ref-filter.c                |   3 +-\n refs.c                      |   9 +-\n refs.h                      |   4 +-\n refs/files-backend.c        |  32 +++--\n refs/reftable-backend.c     |  22 ++--\n repo-settings.c             |  35 +++++-\n repo-settings.h             |  75 ++++++++++++\n repository.c                |  40 ++++++\n repository.h                |  58 ++-------\n server-info.c               |   4 +-\n setup.c                     | 140 ++++++++++++++++++---\n setup.h                     |   5 +-\n sparse-index.c              |   2 +\n statinfo.c                  |   2 +\n submodule.c                 |   2 +-\n t/helper/test-config.c      |   3 +-\n t/helper/test-path-utils.c  |   2 +\n tmp-objdir.c                |   8 +-\n trace.c                     |  10 +-\n trace2/tr2_cfg.c            |   4 +-\n transport-helper.c          |   2 +-\n tree-diff.c                 |   3 +\n userdiff.c                  |   2 +\n worktree.c                  |  12 +-\n wt-status.c                 |   3 +-\n 83 files changed, 698 insertions(+), 560 deletions(-)\n create mode 100644 repo-settings.h\n\nRange-diff against v2:\n 1:  a1969c5b073 !  1:  adeaa5030b4 environment: make `get_git_dir()` accept a repository\n    @@ repository.c: static void expand_base_dir(char **out, const char *in,\n     +const char *repo_get_git_dir(struct repository *repo)\n     +{\n     +\tif (!repo->gitdir)\n    -+\t\tBUG(\"git environment hasn't been setup\");\n    ++\t\tBUG(\"repository hasn't been set up\");\n     +\treturn repo->gitdir;\n     +}\n     +\n 2:  deebf2c5205 !  2:  2964cfc7790 environment: make `get_git_common_dir()` accept a repository\n    @@ repository.c: const char *repo_get_git_dir(struct repository *repo)\n     +const char *repo_get_common_dir(struct repository *repo)\n     +{\n     +\tif (!repo->commondir)\n    -+\t\tBUG(\"git environment hasn't been setup\");\n    ++\t\tBUG(\"repository hasn't been set up\");\n     +\treturn repo->commondir;\n     +}\n     +\n 3:  43abfa7b139 !  3:  b2edc57163c environment: make `get_object_directory()` accept a repository\n    @@ repository.c: const char *repo_get_common_dir(struct repository *repo)\n     +const char *repo_get_object_directory(struct repository *repo)\n     +{\n     +\tif (!repo->objects->odb)\n    -+\t\tBUG(\"git environment hasn't been setup\");\n    ++\t\tBUG(\"repository hasn't been set up\");\n     +\treturn repo->objects->odb->path;\n     +}\n     +\n 4:  d7554cb0fe0 !  4:  f82bee6d04f environment: make `get_index_file()` accept a repository\n    @@ repository.c: const char *repo_get_object_directory(struct repository *repo)\n     +const char *repo_get_index_file(struct repository *repo)\n     +{\n     +\tif (!repo->index_file)\n    -+\t\tBUG(\"git environment hasn't been setup\");\n    ++\t\tBUG(\"repository hasn't been set up\");\n     +\treturn repo->index_file;\n     +}\n     +\n 5:  1cc727e4763 !  5:  e3f3f6391da environment: make `get_graft_file()` accept a repository\n    @@ repository.c: const char *repo_get_index_file(struct repository *repo)\n     +const char *repo_get_graft_file(struct repository *repo)\n     +{\n     +\tif (!repo->graft_file)\n    -+\t\tBUG(\"git environment hasn't been setup\");\n    ++\t\tBUG(\"repository hasn't been set up\");\n     +\treturn repo->graft_file;\n     +}\n     +\n 6:  22e9dcb28a9 =  6:  00950932195 environment: make `get_git_work_tree()` accept a repository\n 7:  ec4804a99bf =  7:  8c0010b4397 config: document `read_early_config()` and `read_very_early_config()`\n 8:  b8aa5dcc0b6 =  8:  1ed3d3f1d71 config: make dependency on repo in `read_early_config()` explicit\n 9:  ac2cc4e0371 !  9:  b164373d10b environment: move `odb_mkstemp()` into object layer\n    @@ Metadata\n     Author: Patrick Steinhardt <ps@pks.im>\n     \n      ## Commit message ##\n    -    environment: move `odb_mkstemp()` into object layer\n    +    environment: move object database functions into object layer\n     \n    -    The `odb_mkstemp()` function is quite clearly tied to the object store,\n    -    but regardless of that it is located in \"environment.c\". Move it over,\n    -    which also helps to get rid of dependencies on `the_repository` in the\n    -    environment subsystem.\n    +    The `odb_mkstemp()` and `odb_pack_keep()` functions are quite clearly\n    +    tied to the object store, but regardless of that they are located in\n    +    \"environment.c\". Move them over, which also helps to get rid of\n    +    dependencies on `the_repository` in the environment subsystem.\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n10:  f0d3794dfc4 = 10:  85c10fad522 environment: make `get_git_namespace()` self-contained\n11:  9e0e2528b94 = 11:  437b6f1f30d environment: move `set_git_dir()` and related into setup layer\n12:  78f77a006a0 = 12:  8de5b246dad environment: reorder header to split out `the_repository`-free section\n13:  9a3f466b530 = 13:  417cca950bf environment: guard state depending on a repository\n14:  0d7365c5190 = 14:  a9d032b3ec7 repo-settings: split out declarations into a standalone header\n15:  231c52ce82f = 15:  7a74c8d8a8d repo-settings: track defaults close to `struct repo_settings`\n16:  fc30365e1f1 ! 16:  b5f3bf5cd25 branch: stop modifying `log_all_ref_updates` variable\n    @@ Commit message\n         discouraged, as it may have all kinds of consequences in other places of\n         our codebase.\n     \n    -    Stop modifying the variable and pass the `REF_FORCE_CREATE_REFLOG` flag,\n    -    which has the same effect.\n    +    Stop modifying the variable and pass the `REF_FORCE_CREATE_REFLOG` flag\n    +    instead. Setting this flag has a stronger meaning than setting the\n    +    config to `LOG_REFS_NORMAL`:\n    +\n    +      - `LOG_REFS_NORMAL` will ask us to only create reflog entries for\n    +        preexisting reflogs or branches, remote refs, note refs and HEAD.\n    +\n    +      - `REF_FORCE_CREATE_REFLOG` will unconditionally create a reflog and\n    +        is thus equivalent to `LOG_REFS_ALWAYS`.\n    +\n    +    But as we are in `create_branch()` and thus do not have to worry about\n    +    arbitrary references, but only about branches, `LOG_REFS_NORMAL` and\n    +    `LOG_REFS_ALWAYS` are indeed equivalent.\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n17:  9cc8518a02d = 17:  128fefd33a8 refs: stop modifying global `log_all_ref_updates` variable\n18:  b5ed6928070 = 18:  df0f29cfec0 environment: stop storing \"core.logAllRefUpdates\" globally\n19:  194d858877f = 19:  e3527e7d73f environment: stop storing \"core.preferSymlinkRefs\" globally\n20:  fc6fcebf7f7 = 20:  3c4a9259fbb environment: stop storing \"core.warnAmbiguousRefs\" globally\n21:  a0b75c4bc99 = 21:  08672e8a073 environment: stop storing \"core.notesRef\" globally\n\nbase-commit: 17d4b10aea6bda2027047a0e3548a6f8ad667dde\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502685","messageId":"adeaa5030b4e81d23c94552bb4b583b691cc90bf.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 01/21] environment: make `get_git_dir()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:24Z","receivedAt":"2024-09-12T11:29:27Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_git_dir()` function retrieves the path to the Git directory for\n`the_repository`. Make it accept a `struct repository` such that it can\nwork on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n apply.c                     |  3 ++-\n builtin/am.c                |  5 +++--\n builtin/commit.c            |  7 ++++---\n builtin/config.c            |  2 +-\n builtin/difftool.c          |  5 +++--\n builtin/fsmonitor--daemon.c |  3 ++-\n builtin/merge.c             |  4 +++-\n builtin/stash.c             |  3 ++-\n cache-tree.c                |  5 +++--\n config.c                    |  4 +++-\n environment.c               | 10 ++--------\n environment.h               |  1 -\n pathspec.c                  |  2 +-\n read-cache.c                |  6 ++++--\n repository.c                |  7 +++++++\n repository.h                |  2 ++\n setup.c                     | 12 ++++++------\n setup.h                     |  2 +-\n trace.c                     |  5 ++++-\n transport-helper.c          |  2 +-\n worktree.c                  |  4 ++--\n 21 files changed, 56 insertions(+), 38 deletions(-)\n\ndiff --git a/apply.c b/apply.c\nindex 6e1060a952c..426cec32f8f 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -30,6 +30,7 @@\n #include \"path.h\"\n #include \"quote.h\"\n #include \"read-cache.h\"\n+#include \"repository.h\"\n #include \"rerere.h\"\n #include \"apply.h\"\n #include \"entry.h\"\n@@ -4111,7 +4112,7 @@ static int read_apply_cache(struct apply_state *state)\n {\n \tif (state->index_file)\n \t\treturn read_index_from(state->repo->index, state->index_file,\n-\t\t\t\t       get_git_dir());\n+\t\t\t\t       repo_get_git_dir(the_repository));\n \telse\n \t\treturn repo_read_index(state->repo);\n }\ndiff --git a/builtin/am.c b/builtin/am.c\nindex d8875ad4022..405214e242a 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1544,7 +1544,8 @@ static int run_apply(const struct am_state *state, const char *index_file)\n \tif (index_file) {\n \t\t/* Reload index as apply_all_patches() will have modified it. */\n \t\tdiscard_index(the_repository->index);\n-\t\tread_index_from(the_repository->index, index_file, get_git_dir());\n+\t\tread_index_from(the_repository->index, index_file,\n+\t\t\t\trepo_get_git_dir(the_repository));\n \t}\n \n \treturn 0;\n@@ -1587,7 +1588,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa\n \t\treturn error(\"could not build fake ancestor\");\n \n \tdiscard_index(the_repository->index);\n-\tread_index_from(the_repository->index, index_path, get_git_dir());\n+\tread_index_from(the_repository->index, index_path, repo_get_git_dir(the_repository));\n \n \tif (write_index_as_tree(&bases[0], the_repository->index, index_path, 0, NULL))\n \t\treturn error(_(\"Repository lacks necessary blobs to fall back on 3-way merge.\"));\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex b2033c48877..a1c1d16a099 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -26,6 +26,7 @@\n #include \"path.h\"\n #include \"preload-index.h\"\n #include \"read-cache.h\"\n+#include \"repository.h\"\n #include \"string-list.h\"\n #include \"rerere.h\"\n #include \"unpack-trees.h\"\n@@ -407,7 +408,7 @@ static const char *prepare_index(const char **argv, const char *prefix,\n \n \t\tdiscard_index(the_repository->index);\n \t\tread_index_from(the_repository->index, get_lock_file_path(&index_lock),\n-\t\t\t\tget_git_dir());\n+\t\t\t\trepo_get_git_dir(the_repository));\n \t\tif (cache_tree_update(the_repository->index, WRITE_TREE_SILENT) == 0) {\n \t\t\tif (reopen_lock_file(&index_lock) < 0)\n \t\t\t\tdie(_(\"unable to write index file\"));\n@@ -534,7 +535,7 @@ static const char *prepare_index(const char **argv, const char *prefix,\n \n \tdiscard_index(the_repository->index);\n \tret = get_lock_file_path(&false_lock);\n-\tread_index_from(the_repository->index, ret, get_git_dir());\n+\tread_index_from(the_repository->index, ret, repo_get_git_dir(the_repository));\n out:\n \tstring_list_clear(&partial, 0);\n \tclear_pathspec(&pathspec);\n@@ -1072,7 +1073,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\t */\n \t\tdiscard_index(the_repository->index);\n \t}\n-\tread_index_from(the_repository->index, index_file, get_git_dir());\n+\tread_index_from(the_repository->index, index_file, repo_get_git_dir(the_repository));\n \n \tif (cache_tree_update(the_repository->index, 0)) {\n \t\terror(_(\"Error building trees\"));\ndiff --git a/builtin/config.c b/builtin/config.c\nindex e00d983596b..c10697a2efb 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -808,7 +808,7 @@ static void location_options_init(struct config_location_options *opts,\n \t\topts->options.respect_includes = opts->respect_includes_opt;\n \tif (startup_info->have_repository) {\n \t\topts->options.commondir = get_git_common_dir();\n-\t\topts->options.git_dir = get_git_dir();\n+\t\topts->options.git_dir = repo_get_git_dir(the_repository);\n \t}\n }\n \ndiff --git a/builtin/difftool.c b/builtin/difftool.c\nindex dcc68e190c2..8c59411e6e0 100644\n--- a/builtin/difftool.c\n+++ b/builtin/difftool.c\n@@ -22,6 +22,7 @@\n #include \"hex.h\"\n #include \"parse-options.h\"\n #include \"read-cache-ll.h\"\n+#include \"repository.h\"\n #include \"sparse-index.h\"\n #include \"strvec.h\"\n #include \"strbuf.h\"\n@@ -214,7 +215,7 @@ static void changed_files(struct hashmap *result, const char *index_path,\n \tstruct child_process update_index = CHILD_PROCESS_INIT;\n \tstruct child_process diff_files = CHILD_PROCESS_INIT;\n \tstruct strbuf buf = STRBUF_INIT;\n-\tconst char *git_dir = absolute_path(get_git_dir());\n+\tconst char *git_dir = absolute_path(repo_get_git_dir(the_repository));\n \tFILE *fp;\n \n \tstrvec_pushl(&update_index.args,\n@@ -737,7 +738,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)\n \n \tif (!no_index){\n \t\tsetup_work_tree();\n-\t\tsetenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);\n+\t\tsetenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1);\n \t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);\n \t} else if (dir_diff)\n \t\tdie(_(\"options '%s' and '%s' cannot be used together\"), \"--dir-diff\", \"--no-index\");\ndiff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c\nindex 1593713f4cb..c54e736716a 100644\n--- a/builtin/fsmonitor--daemon.c\n+++ b/builtin/fsmonitor--daemon.c\n@@ -1311,7 +1311,8 @@ static int fsmonitor_run_daemon(void)\n \tstrbuf_addstr(&state.path_gitdir_watch, \"/.git\");\n \tif (!is_directory(state.path_gitdir_watch.buf)) {\n \t\tstrbuf_reset(&state.path_gitdir_watch);\n-\t\tstrbuf_addstr(&state.path_gitdir_watch, absolute_path(get_git_dir()));\n+\t\tstrbuf_addstr(&state.path_gitdir_watch,\n+\t\t\t      absolute_path(repo_get_git_dir(the_repository)));\n \t\tstate.nr_paths_watching = 2;\n \t}\n \ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 662a49a0e8c..a2bae0700b4 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -17,6 +17,7 @@\n #include \"object-name.h\"\n #include \"parse-options.h\"\n #include \"lockfile.h\"\n+#include \"repository.h\"\n #include \"run-command.h\"\n #include \"hook.h\"\n #include \"diff.h\"\n@@ -855,7 +856,8 @@ static void prepare_to_commit(struct commit_list *remoteheads)\n \t\tif (invoked_hook)\n \t\t\tdiscard_index(the_repository->index);\n \t}\n-\tread_index_from(the_repository->index, index_file, get_git_dir());\n+\tread_index_from(the_repository->index, index_file,\n+\t\t\trepo_get_git_dir(the_repository));\n \tstrbuf_addbuf(&msg, &merge_msg);\n \tif (squash)\n \t\tBUG(\"the control must not reach here under --squash\");\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex fcfd97972a4..ad6bcefb770 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -19,6 +19,7 @@\n #include \"entry.h\"\n #include \"preload-index.h\"\n #include \"read-cache.h\"\n+#include \"repository.h\"\n #include \"rerere.h\"\n #include \"revision.h\"\n #include \"setup.h\"\n@@ -642,7 +643,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\tstrvec_pushf(&cp.env, GIT_WORK_TREE_ENVIRONMENT\"=%s\",\n \t\t\t     absolute_path(get_git_work_tree()));\n \t\tstrvec_pushf(&cp.env, GIT_DIR_ENVIRONMENT\"=%s\",\n-\t\t\t     absolute_path(get_git_dir()));\n+\t\t\t     absolute_path(repo_get_git_dir(the_repository)));\n \t\tstrvec_push(&cp.args, \"status\");\n \t\trun_command(&cp);\n \t}\ndiff --git a/cache-tree.c b/cache-tree.c\nindex 50610c3f3cb..b482167a69a 100644\n--- a/cache-tree.c\n+++ b/cache-tree.c\n@@ -1,7 +1,6 @@\n #define USE_THE_REPOSITORY_VARIABLE\n \n #include \"git-compat-util.h\"\n-#include \"environment.h\"\n #include \"hex.h\"\n #include \"lockfile.h\"\n #include \"tree.h\"\n@@ -12,6 +11,7 @@\n #include \"object-store-ll.h\"\n #include \"read-cache-ll.h\"\n #include \"replace-object.h\"\n+#include \"repository.h\"\n #include \"promisor-remote.h\"\n #include \"trace.h\"\n #include \"trace2.h\"\n@@ -725,7 +725,8 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,\n \n \thold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);\n \n-\tentries = read_index_from(index_state, index_path, get_git_dir());\n+\tentries = read_index_from(index_state, index_path,\n+\t\t\t\t  repo_get_git_dir(the_repository));\n \tif (entries < 0) {\n \t\tret = WRITE_TREE_UNREADABLE_INDEX;\n \t\tgoto out;\ndiff --git a/config.c b/config.c\nindex 56b5862e59d..1733ba85dcd 100644\n--- a/config.c\n+++ b/config.c\n@@ -6,6 +6,8 @@\n  *\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"advice.h\"\n@@ -2212,7 +2214,7 @@ void read_early_config(config_fn_t cb, void *data)\n \n \tif (have_git_dir()) {\n \t\topts.commondir = get_git_common_dir();\n-\t\topts.git_dir = get_git_dir();\n+\t\topts.git_dir = repo_get_git_dir(the_repository);\n \t/*\n \t * When setup_git_directory() was not yet asked to discover the\n \t * GIT_DIR, we ask discover_git_directory() to figure out whether there\ndiff --git a/environment.c b/environment.c\nindex 1d6c48b52df..040b1ff1ba8 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -228,13 +228,6 @@ int have_git_dir(void)\n \t\t|| the_repository->gitdir;\n }\n \n-const char *get_git_dir(void)\n-{\n-\tif (!the_repository->gitdir)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->gitdir;\n-}\n-\n const char *get_git_common_dir(void)\n {\n \tif (!the_repository->commondir)\n@@ -352,7 +345,8 @@ static void update_relative_gitdir(const char *name UNUSED,\n \t\t\t\t   const char *new_cwd,\n \t\t\t\t   void *data UNUSED)\n {\n-\tchar *path = reparent_relative_path(old_cwd, new_cwd, get_git_dir());\n+\tchar *path = reparent_relative_path(old_cwd, new_cwd,\n+\t\t\t\t\t    repo_get_git_dir(the_repository));\n \tstruct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();\n \n \ttrace_printf_key(&trace_setup_key,\ndiff --git a/environment.h b/environment.h\nindex 0148738ed63..06d37d5c82b 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_git_dir(void);\n const char *get_git_common_dir(void);\n const char *get_object_directory(void);\n char *get_index_file(void);\ndiff --git a/pathspec.c b/pathspec.c\nindex fe1f0f41af0..416fe1e3dcc 100644\n--- a/pathspec.c\n+++ b/pathspec.c\n@@ -497,7 +497,7 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,\n \t\t\t\t    copyfrom);\n \t\t\thint_path = get_git_work_tree();\n \t\t\tif (!hint_path)\n-\t\t\t\thint_path = get_git_dir();\n+\t\t\t\thint_path = repo_get_git_dir(the_repository);\n \t\t\tdie(_(\"%s: '%s' is outside repository at '%s'\"), elt,\n \t\t\t    copyfrom, absolute_path(hint_path));\n \t\t}\ndiff --git a/read-cache.c b/read-cache.c\nindex 4e67dc182e7..764fdfec465 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -31,6 +31,7 @@\n #include \"path.h\"\n #include \"preload-index.h\"\n #include \"read-cache.h\"\n+#include \"repository.h\"\n #include \"resolve-undo.h\"\n #include \"revision.h\"\n #include \"strbuf.h\"\n@@ -3238,10 +3239,11 @@ static int should_delete_shared_index(const char *shared_index_path)\n static int clean_shared_index_files(const char *current_hex)\n {\n \tstruct dirent *de;\n-\tDIR *dir = opendir(get_git_dir());\n+\tDIR *dir = opendir(repo_get_git_dir(the_repository));\n \n \tif (!dir)\n-\t\treturn error_errno(_(\"unable to open git dir: %s\"), get_git_dir());\n+\t\treturn error_errno(_(\"unable to open git dir: %s\"),\n+\t\t\t\t   repo_get_git_dir(the_repository));\n \n \twhile ((de = readdir(dir)) != NULL) {\n \t\tconst char *sha1_hex;\ndiff --git a/repository.c b/repository.c\nindex 9825a308993..31afc62551e 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -91,6 +91,13 @@ static void expand_base_dir(char **out, const char *in,\n \t\t*out = xstrfmt(\"%s/%s\", base_dir, def_in);\n }\n \n+const char *repo_get_git_dir(struct repository *repo)\n+{\n+\tif (!repo->gitdir)\n+\t\tBUG(\"repository hasn't been set up\");\n+\treturn repo->gitdir;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex af6ea0a62cd..cf2172c0aa5 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -206,6 +206,8 @@ struct repository {\n extern struct repository *the_repository;\n #endif\n \n+const char *repo_get_git_dir(struct repository *repo);\n+\n /*\n  * Define a custom repository layout. Any field can be NULL, which\n  * will default back to the path according to the default layout.\ndiff --git a/setup.c b/setup.c\nindex 29f86739212..4a9c60922e7 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -149,7 +149,7 @@ char *prefix_path(const char *prefix, int len, const char *path)\n \tif (!r) {\n \t\tconst char *hint_path = get_git_work_tree();\n \t\tif (!hint_path)\n-\t\t\thint_path = get_git_dir();\n+\t\t\thint_path = repo_get_git_dir(the_repository);\n \t\tdie(_(\"'%s' is outside repository at '%s'\"), path,\n \t\t    absolute_path(hint_path));\n \t}\n@@ -468,7 +468,7 @@ int is_nonbare_repository_dir(struct strbuf *path)\n int is_inside_git_dir(void)\n {\n \tif (inside_git_dir < 0)\n-\t\tinside_git_dir = is_inside_dir(get_git_dir());\n+\t\tinside_git_dir = is_inside_dir(repo_get_git_dir(the_repository));\n \treturn inside_git_dir;\n }\n \n@@ -1836,7 +1836,7 @@ void check_repository_format(struct repository_format *fmt)\n \tstruct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;\n \tif (!fmt)\n \t\tfmt = &repo_fmt;\n-\tcheck_repository_format_gently(get_git_dir(), fmt, NULL);\n+\tcheck_repository_format_gently(repo_get_git_dir(the_repository), fmt, NULL);\n \tstartup_info->have_repository = 1;\n \trepo_set_hash_algo(the_repository, fmt->hash_algo);\n \trepo_set_compat_hash_algo(the_repository, fmt->compat_hash_algo);\n@@ -2224,7 +2224,7 @@ static int create_default_files(const char *template_path,\n \t * shared-repository settings, we would need to fix them up.\n \t */\n \tif (get_shared_repository()) {\n-\t\tadjust_shared_perm(get_git_dir());\n+\t\tadjust_shared_perm(repo_get_git_dir(the_repository));\n \t}\n \n \tinitialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, 0);\n@@ -2434,12 +2434,12 @@ int init_db(const char *git_dir, const char *real_git_dir,\n \t\t\tdie(_(\"%s already exists\"), real_git_dir);\n \n \t\tset_git_dir(real_git_dir, 1);\n-\t\tgit_dir = get_git_dir();\n+\t\tgit_dir = repo_get_git_dir(the_repository);\n \t\tseparate_git_dir(git_dir, original_git_dir);\n \t}\n \telse {\n \t\tset_git_dir(git_dir, 1);\n-\t\tgit_dir = get_git_dir();\n+\t\tgit_dir = repo_get_git_dir(the_repository);\n \t}\n \tstartup_info->have_repository = 1;\n \ndiff --git a/setup.h b/setup.h\nindex cd8dbc24976..fd2df7cd525 100644\n--- a/setup.h\n+++ b/setup.h\n@@ -176,7 +176,7 @@ int verify_repository_format(const struct repository_format *format,\n \t\t\t     struct strbuf *err);\n \n /*\n- * Check the repository format version in the path found in get_git_dir(),\n+ * Check the repository format version in the path found in repo_get_git_dir(the_repository),\n  * and die if it is a version we don't understand. Generally one would\n  * set_git_dir() before calling this, and use it only for \"are we in a valid\n  * repo?\".\ndiff --git a/trace.c b/trace.c\nindex 8669ddfca25..32c5cda7afd 100644\n--- a/trace.c\n+++ b/trace.c\n@@ -21,9 +21,12 @@\n  *  along with this program; if not, see <https://www.gnu.org/licenses/>.\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"environment.h\"\n+#include \"repository.h\"\n #include \"quote.h\"\n #include \"setup.h\"\n #include \"trace.h\"\n@@ -311,7 +314,7 @@ void trace_repo_setup(void)\n \tif (!startup_info->prefix)\n \t\tprefix = \"(null)\";\n \n-\ttrace_printf_key(&trace_setup_key, \"setup: git_dir: %s\\n\", quote_crnl(get_git_dir()));\n+\ttrace_printf_key(&trace_setup_key, \"setup: git_dir: %s\\n\", quote_crnl(repo_get_git_dir(the_repository)));\n \ttrace_printf_key(&trace_setup_key, \"setup: git_common_dir: %s\\n\", quote_crnl(get_git_common_dir()));\n \ttrace_printf_key(&trace_setup_key, \"setup: worktree: %s\\n\", quote_crnl(git_work_tree));\n \ttrace_printf_key(&trace_setup_key, \"setup: cwd: %s\\n\", quote_crnl(cwd));\ndiff --git a/transport-helper.c b/transport-helper.c\nindex 09b3560ffdc..abe16eea651 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -143,7 +143,7 @@ static struct child_process *get_helper(struct transport *transport)\n \n \tif (have_git_dir())\n \t\tstrvec_pushf(&helper->env, \"%s=%s\",\n-\t\t\t     GIT_DIR_ENVIRONMENT, get_git_dir());\n+\t\t\t     GIT_DIR_ENVIRONMENT, repo_get_git_dir(the_repository));\n \n \thelper->trace2_child_class = helper->args.v[0]; /* \"remote-<name>\" */\n \ndiff --git a/worktree.c b/worktree.c\nindex 30a947426ee..11335c5d9a3 100644\n--- a/worktree.c\n+++ b/worktree.c\n@@ -57,7 +57,7 @@ static void add_head_info(struct worktree *wt)\n \n static int is_current_worktree(struct worktree *wt)\n {\n-\tchar *git_dir = absolute_pathdup(get_git_dir());\n+\tchar *git_dir = absolute_pathdup(repo_get_git_dir(the_repository));\n \tconst char *wt_git_dir = get_worktree_git_dir(wt);\n \tint is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir));\n \tfree(git_dir);\n@@ -171,7 +171,7 @@ struct worktree **get_worktrees(void)\n const char *get_worktree_git_dir(const struct worktree *wt)\n {\n \tif (!wt)\n-\t\treturn get_git_dir();\n+\t\treturn repo_get_git_dir(the_repository);\n \telse if (!wt->id)\n \t\treturn get_git_common_dir();\n \telse\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502686","messageId":"2964cfc77901bac58bda4614befa604f16bfec90.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 02/21] environment: make `get_git_common_dir()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:27Z","receivedAt":"2024-09-12T11:29:29Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_git_common_dir()` function retrieves the path to the common\ndirectory for `the_repository`. Make it accept a `struct repository`\nsuch that it can work on arbitrary repositories and make it part of the\nrepository subsystem. This reduces our reliance on `the_repository` and\nclarifies scope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/config.c    | 2 +-\n builtin/gc.c        | 2 +-\n builtin/rev-parse.c | 3 ++-\n builtin/worktree.c  | 4 ++--\n config.c            | 2 +-\n environment.c       | 7 -------\n environment.h       | 1 -\n repository.c        | 7 +++++++\n repository.h        | 1 +\n setup.c             | 2 +-\n submodule.c         | 2 +-\n trace.c             | 2 +-\n worktree.c          | 8 ++++----\n 13 files changed, 22 insertions(+), 21 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex c10697a2efb..34a371414e8 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -807,7 +807,7 @@ static void location_options_init(struct config_location_options *opts,\n \telse\n \t\topts->options.respect_includes = opts->respect_includes_opt;\n \tif (startup_info->have_repository) {\n-\t\topts->options.commondir = get_git_common_dir();\n+\t\topts->options.commondir = repo_get_common_dir(the_repository);\n \t\topts->options.git_dir = repo_get_git_dir(the_repository);\n \t}\n }\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex 427faf1cfe1..0f3d74f8bd0 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -2132,7 +2132,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority\n \tget_schedule_cmd(&cmd, NULL);\n \n \tstrbuf_addf(&tfilename, \"%s/schedule_%s_XXXXXX\",\n-\t\t    get_git_common_dir(), frequency);\n+\t\t    repo_get_common_dir(the_repository), frequency);\n \ttfile = xmks_tempfile(tfilename.buf);\n \tstrbuf_release(&tfilename);\n \ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex 4285dc34a7b..cd85fe57bb0 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -19,6 +19,7 @@\n #include \"path.h\"\n #include \"diff.h\"\n #include \"read-cache-ll.h\"\n+#include \"repository.h\"\n #include \"revision.h\"\n #include \"setup.h\"\n #include \"split-index.h\"\n@@ -1042,7 +1043,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--git-common-dir\")) {\n-\t\t\t\tprint_path(get_git_common_dir(), prefix, format, DEFAULT_RELATIVE_IF_SHARED);\n+\t\t\t\tprint_path(repo_get_common_dir(the_repository), prefix, format, DEFAULT_RELATIVE_IF_SHARED);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--is-inside-git-dir\")) {\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 41e7f6a3271..645b548bf3b 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -219,7 +219,7 @@ static void prune_worktrees(void)\n \t}\n \tclosedir(dir);\n \n-\tstrbuf_add_absolute_path(&main_path, get_git_common_dir());\n+\tstrbuf_add_absolute_path(&main_path, repo_get_common_dir(the_repository));\n \t/* massage main worktree absolute path to match 'gitdir' content */\n \tstrbuf_strip_suffix(&main_path, \"/.\");\n \tstring_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));\n@@ -492,7 +492,7 @@ static int add_worktree(const char *path, const char *refname,\n \tstrbuf_addf(&sb, \"%s/gitdir\", sb_repo.buf);\n \tstrbuf_realpath(&realpath, sb_git.buf, 1);\n \twrite_file(sb.buf, \"%s\", realpath.buf);\n-\tstrbuf_realpath(&realpath, get_git_common_dir(), 1);\n+\tstrbuf_realpath(&realpath, repo_get_common_dir(the_repository), 1);\n \twrite_file(sb_git.buf, \"gitdir: %s/worktrees/%s\",\n \t\t   realpath.buf, name);\n \tstrbuf_reset(&sb);\ndiff --git a/config.c b/config.c\nindex 1733ba85dcd..0b87f0f9050 100644\n--- a/config.c\n+++ b/config.c\n@@ -2213,7 +2213,7 @@ void read_early_config(config_fn_t cb, void *data)\n \topts.respect_includes = 1;\n \n \tif (have_git_dir()) {\n-\t\topts.commondir = get_git_common_dir();\n+\t\topts.commondir = repo_get_common_dir(the_repository);\n \t\topts.git_dir = repo_get_git_dir(the_repository);\n \t/*\n \t * When setup_git_directory() was not yet asked to discover the\ndiff --git a/environment.c b/environment.c\nindex 040b1ff1ba8..7c4a142ca25 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -228,13 +228,6 @@ int have_git_dir(void)\n \t\t|| the_repository->gitdir;\n }\n \n-const char *get_git_common_dir(void)\n-{\n-\tif (!the_repository->commondir)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->commondir;\n-}\n-\n const char *get_git_namespace(void)\n {\n \tif (!git_namespace)\ndiff --git a/environment.h b/environment.h\nindex 06d37d5c82b..d778614158f 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_git_common_dir(void);\n const char *get_object_directory(void);\n char *get_index_file(void);\n char *get_graft_file(struct repository *r);\ndiff --git a/repository.c b/repository.c\nindex 31afc62551e..c8dcba1997a 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -98,6 +98,13 @@ const char *repo_get_git_dir(struct repository *repo)\n \treturn repo->gitdir;\n }\n \n+const char *repo_get_common_dir(struct repository *repo)\n+{\n+\tif (!repo->commondir)\n+\t\tBUG(\"repository hasn't been set up\");\n+\treturn repo->commondir;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex cf2172c0aa5..404435ad029 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -207,6 +207,7 @@ extern struct repository *the_repository;\n #endif\n \n const char *repo_get_git_dir(struct repository *repo);\n+const char *repo_get_common_dir(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/setup.c b/setup.c\nindex 4a9c60922e7..fe4a5dfc43b 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2068,7 +2068,7 @@ static void copy_templates(const char *option_template)\n \t\tgoto close_free_return;\n \t}\n \n-\tstrbuf_addstr(&path, get_git_common_dir());\n+\tstrbuf_addstr(&path, repo_get_common_dir(the_repository));\n \tstrbuf_complete(&path, '/');\n \tcopy_templates_1(&path, &template_path, dir);\n close_free_return:\ndiff --git a/submodule.c b/submodule.c\nindex 97516b0fec1..c7d164a31ab 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -2462,7 +2462,7 @@ void absorb_git_dir_into_superproject(const char *path,\n \t} else {\n \t\t/* Is it already absorbed into the superprojects git dir? */\n \t\tchar *real_sub_git_dir = real_pathdup(sub_git_dir, 1);\n-\t\tchar *real_common_git_dir = real_pathdup(get_git_common_dir(), 1);\n+\t\tchar *real_common_git_dir = real_pathdup(repo_get_common_dir(the_repository), 1);\n \n \t\tif (!starts_with(real_sub_git_dir, real_common_git_dir))\n \t\t\trelocate_single_git_dir_into_superproject(path, super_prefix);\ndiff --git a/trace.c b/trace.c\nindex 32c5cda7afd..e6728c301f3 100644\n--- a/trace.c\n+++ b/trace.c\n@@ -315,7 +315,7 @@ void trace_repo_setup(void)\n \t\tprefix = \"(null)\";\n \n \ttrace_printf_key(&trace_setup_key, \"setup: git_dir: %s\\n\", quote_crnl(repo_get_git_dir(the_repository)));\n-\ttrace_printf_key(&trace_setup_key, \"setup: git_common_dir: %s\\n\", quote_crnl(get_git_common_dir()));\n+\ttrace_printf_key(&trace_setup_key, \"setup: git_common_dir: %s\\n\", quote_crnl(repo_get_common_dir(the_repository)));\n \ttrace_printf_key(&trace_setup_key, \"setup: worktree: %s\\n\", quote_crnl(git_work_tree));\n \ttrace_printf_key(&trace_setup_key, \"setup: cwd: %s\\n\", quote_crnl(cwd));\n \ttrace_printf_key(&trace_setup_key, \"setup: prefix: %s\\n\", quote_crnl(prefix));\ndiff --git a/worktree.c b/worktree.c\nindex 11335c5d9a3..0f032ccedff 100644\n--- a/worktree.c\n+++ b/worktree.c\n@@ -72,7 +72,7 @@ static struct worktree *get_main_worktree(int skip_reading_head)\n \tstruct worktree *worktree = NULL;\n \tstruct strbuf worktree_path = STRBUF_INIT;\n \n-\tstrbuf_add_real_path(&worktree_path, get_git_common_dir());\n+\tstrbuf_add_real_path(&worktree_path, repo_get_common_dir(the_repository));\n \tstrbuf_strip_suffix(&worktree_path, \"/.git\");\n \n \tCALLOC_ARRAY(worktree, 1);\n@@ -143,7 +143,7 @@ static struct worktree **get_worktrees_internal(int skip_reading_head)\n \n \tlist[counter++] = get_main_worktree(skip_reading_head);\n \n-\tstrbuf_addf(&path, \"%s/worktrees\", get_git_common_dir());\n+\tstrbuf_addf(&path, \"%s/worktrees\", repo_get_common_dir(the_repository));\n \tdir = opendir(path.buf);\n \tstrbuf_release(&path);\n \tif (dir) {\n@@ -173,7 +173,7 @@ const char *get_worktree_git_dir(const struct worktree *wt)\n \tif (!wt)\n \t\treturn repo_get_git_dir(the_repository);\n \telse if (!wt->id)\n-\t\treturn get_git_common_dir();\n+\t\treturn repo_get_common_dir(the_repository);\n \telse\n \t\treturn git_common_path(\"worktrees/%s\", wt->id);\n }\n@@ -626,7 +626,7 @@ static int is_main_worktree_path(const char *path)\n \n \tstrbuf_add_real_path(&target, path);\n \tstrbuf_strip_suffix(&target, \"/.git\");\n-\tstrbuf_add_real_path(&maindir, get_git_common_dir());\n+\tstrbuf_add_real_path(&maindir, repo_get_common_dir(the_repository));\n \tstrbuf_strip_suffix(&maindir, \"/.git\");\n \tcmp = fspathcmp(maindir.buf, target.buf);\n \n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502687","messageId":"b2edc57163cb379020c3d8c198dc6a19658a67c9.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 03/21] environment: make `get_object_directory()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:30Z","receivedAt":"2024-09-12T11:29:32Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_object_directory()` function retrieves the path to the object\ndirectory for `the_repository`. Make it accept a `struct repository`\nsuch that it can work on arbitrary repositories and make it part of the\nrepository subsystem. This reduces our reliance on `the_repository` and\nclarifies scope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/commit-graph.c     | 5 ++---\n builtin/count-objects.c    | 3 +--\n builtin/multi-pack-index.c | 4 ++--\n builtin/pack-objects.c     | 2 +-\n builtin/prune.c            | 8 ++++----\n builtin/repack.c           | 7 ++++---\n bulk-checkin.c             | 4 ++--\n environment.c              | 7 -------\n environment.h              | 1 -\n fetch-pack.c               | 2 +-\n http-backend.c             | 2 +-\n object-file.c              | 4 ++--\n pack-write.c               | 3 ++-\n packfile.c                 | 2 +-\n prune-packed.c             | 6 ++++--\n repository.c               | 7 +++++++\n repository.h               | 1 +\n server-info.c              | 4 ++--\n setup.c                    | 2 +-\n tmp-objdir.c               | 8 +++++---\n 20 files changed, 43 insertions(+), 39 deletions(-)\n\ndiff --git a/builtin/commit-graph.c b/builtin/commit-graph.c\nindex 7102ee90a00..7411e6244f2 100644\n--- a/builtin/commit-graph.c\n+++ b/builtin/commit-graph.c\n@@ -1,7 +1,6 @@\n #include \"builtin.h\"\n #include \"commit.h\"\n #include \"config.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"hex.h\"\n #include \"parse-options.h\"\n@@ -95,7 +94,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(builtin_commit_graph_verify_usage, options);\n \n \tif (!opts.obj_dir)\n-\t\topts.obj_dir = get_object_directory();\n+\t\topts.obj_dir = repo_get_object_directory(the_repository);\n \tif (opts.shallow)\n \t\tflags |= COMMIT_GRAPH_VERIFY_SHALLOW;\n \tif (opts.progress)\n@@ -275,7 +274,7 @@ static int graph_write(int argc, const char **argv, const char *prefix)\n \tif (opts.reachable + opts.stdin_packs + opts.stdin_commits > 1)\n \t\tdie(_(\"use at most one of --reachable, --stdin-commits, or --stdin-packs\"));\n \tif (!opts.obj_dir)\n-\t\topts.obj_dir = get_object_directory();\n+\t\topts.obj_dir = repo_get_object_directory(the_repository);\n \tif (opts.append)\n \t\tflags |= COMMIT_GRAPH_WRITE_APPEND;\n \tif (opts.split)\ndiff --git a/builtin/count-objects.c b/builtin/count-objects.c\nindex ec6098a149d..42275f62d59 100644\n--- a/builtin/count-objects.c\n+++ b/builtin/count-objects.c\n@@ -7,7 +7,6 @@\n #include \"builtin.h\"\n #include \"config.h\"\n #include \"dir.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"path.h\"\n #include \"repository.h\"\n@@ -116,7 +115,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)\n \t\treport_linked_checkout_garbage(the_repository);\n \t}\n \n-\tfor_each_loose_file_in_objdir(get_object_directory(),\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n \t\t\t\t      count_loose, count_cruft, NULL, NULL);\n \n \tif (verbose) {\ndiff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c\nindex 8805cbbeb3b..55289e989df 100644\n--- a/builtin/multi-pack-index.c\n+++ b/builtin/multi-pack-index.c\n@@ -1,7 +1,6 @@\n #include \"builtin.h\"\n #include \"abspath.h\"\n #include \"config.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"parse-options.h\"\n #include \"midx.h\"\n@@ -9,6 +8,7 @@\n #include \"trace2.h\"\n #include \"object-store-ll.h\"\n #include \"replace-object.h\"\n+#include \"repository.h\"\n \n #define BUILTIN_MIDX_WRITE_USAGE \\\n \tN_(\"git multi-pack-index [<options>] write [--preferred-pack=<pack>]\" \\\n@@ -63,7 +63,7 @@ static int parse_object_dir(const struct option *opt, const char *arg,\n \tchar **value = opt->value;\n \tfree(*value);\n \tif (unset)\n-\t\t*value = xstrdup(get_object_directory());\n+\t\t*value = xstrdup(repo_get_object_directory(the_repository));\n \telse\n \t\t*value = real_pathdup(arg, 1);\n \treturn 0;\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 778be80f564..44341b206d4 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -3940,7 +3940,7 @@ static int add_loose_object(const struct object_id *oid, const char *path,\n  */\n static void add_unreachable_loose_objects(void)\n {\n-\tfor_each_loose_file_in_objdir(get_object_directory(),\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n \t\t\t\t      add_loose_object,\n \t\t\t\t      NULL, NULL, NULL);\n }\ndiff --git a/builtin/prune.c b/builtin/prune.c\nindex 57fe31467fe..47eeabbd13a 100644\n--- a/builtin/prune.c\n+++ b/builtin/prune.c\n@@ -193,12 +193,12 @@ int cmd_prune(int argc, const char **argv, const char *prefix)\n \t\trevs.exclude_promisor_objects = 1;\n \t}\n \n-\tfor_each_loose_file_in_objdir(get_object_directory(), prune_object,\n-\t\t\t\t      prune_cruft, prune_subdir, &revs);\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n+\t\t\t\t      prune_object, prune_cruft, prune_subdir, &revs);\n \n \tprune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0);\n-\tremove_temporary_files(get_object_directory());\n-\ts = mkpathdup(\"%s/pack\", get_object_directory());\n+\tremove_temporary_files(repo_get_object_directory(the_repository));\n+\ts = mkpathdup(\"%s/pack\", repo_get_object_directory(the_repository));\n \tremove_temporary_files(s);\n \tfree(s);\n \ndiff --git a/builtin/repack.c b/builtin/repack.c\nindex 62cfa50c50f..40feacb73f8 100644\n--- a/builtin/repack.c\n+++ b/builtin/repack.c\n@@ -1240,7 +1240,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \tif (write_midx && write_bitmaps) {\n \t\tstruct strbuf path = STRBUF_INIT;\n \n-\t\tstrbuf_addf(&path, \"%s/%s_XXXXXX\", get_object_directory(),\n+\t\tstrbuf_addf(&path, \"%s/%s_XXXXXX\", repo_get_object_directory(the_repository),\n \t\t\t    \"bitmap-ref-tips\");\n \n \t\trefs_snapshot = xmks_tempfile(path.buf);\n@@ -1249,7 +1249,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\tstrbuf_release(&path);\n \t}\n \n-\tpackdir = mkpathdup(\"%s/pack\", get_object_directory());\n+\tpackdir = mkpathdup(\"%s/pack\", repo_get_object_directory(the_repository));\n \tpacktmp_name = xstrfmt(\".tmp-%d-pack\", (int)getpid());\n \tpacktmp = mkpathdup(\"%s/%s\", packdir, packtmp_name);\n \n@@ -1519,7 +1519,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\tunsigned flags = 0;\n \t\tif (git_env_bool(GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL, 0))\n \t\t\tflags |= MIDX_WRITE_INCREMENTAL;\n-\t\twrite_midx_file(get_object_directory(), NULL, NULL, flags);\n+\t\twrite_midx_file(repo_get_object_directory(the_repository),\n+\t\t\t\tNULL, NULL, flags);\n \t}\n \n cleanup:\ndiff --git a/bulk-checkin.c b/bulk-checkin.c\nindex 9089c214fa4..2753d5bbe4a 100644\n--- a/bulk-checkin.c\n+++ b/bulk-checkin.c\n@@ -75,7 +75,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state)\n \t\tclose(fd);\n \t}\n \n-\tstrbuf_addf(&packname, \"%s/pack/pack-%s.\", get_object_directory(),\n+\tstrbuf_addf(&packname, \"%s/pack/pack-%s.\", repo_get_object_directory(the_repository),\n \t\t    hash_to_hex(hash));\n \tfinish_tmp_packfile(&packname, state->pack_tmp_name,\n \t\t\t    state->written, state->nr_written,\n@@ -113,7 +113,7 @@ static void flush_batch_fsync(void)\n \t * to ensure that the data in each new object file is durable before\n \t * the final name is visible.\n \t */\n-\tstrbuf_addf(&temp_path, \"%s/bulk_fsync_XXXXXX\", get_object_directory());\n+\tstrbuf_addf(&temp_path, \"%s/bulk_fsync_XXXXXX\", repo_get_object_directory(the_repository));\n \ttemp = xmks_tempfile(temp_path.buf);\n \tfsync_or_die(get_tempfile_fd(temp), get_tempfile_path(temp));\n \tdelete_tempfile(&temp);\ndiff --git a/environment.c b/environment.c\nindex 7c4a142ca25..0a2057399e0 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -273,13 +273,6 @@ const char *get_git_work_tree(void)\n \treturn the_repository->worktree;\n }\n \n-const char *get_object_directory(void)\n-{\n-\tif (!the_repository->objects->odb)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->objects->odb->path;\n-}\n-\n int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n {\n \tint fd;\ndiff --git a/environment.h b/environment.h\nindex d778614158f..91125d82991 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_object_directory(void);\n char *get_index_file(void);\n char *get_graft_file(struct repository *r);\n void set_git_dir(const char *path, int make_realpath);\ndiff --git a/fetch-pack.c b/fetch-pack.c\nindex 58b4581ad80..fddb90f2e78 100644\n--- a/fetch-pack.c\n+++ b/fetch-pack.c\n@@ -1839,7 +1839,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,\n \n \t\tstring_list_append_nodup(pack_lockfiles,\n \t\t\t\t\t xstrfmt(\"%s/pack/pack-%s.keep\",\n-\t\t\t\t\t\t get_object_directory(),\n+\t\t\t\t\t\t repo_get_object_directory(the_repository),\n \t\t\t\t\t\t packname));\n \t}\n \tstring_list_clear(&packfile_uris, 0);\ndiff --git a/http-backend.c b/http-backend.c\nindex 79ce097359b..73eec4ea3d8 100644\n--- a/http-backend.c\n+++ b/http-backend.c\n@@ -601,7 +601,7 @@ static void get_head(struct strbuf *hdr, char *arg UNUSED)\n \n static void get_info_packs(struct strbuf *hdr, char *arg UNUSED)\n {\n-\tsize_t objdirlen = strlen(get_object_directory());\n+\tsize_t objdirlen = strlen(repo_get_object_directory(the_repository));\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct packed_git *p;\n \tsize_t cnt = 0;\ndiff --git a/object-file.c b/object-file.c\nindex c5994202ba0..fa4121b98ad 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -2053,7 +2053,7 @@ static int start_loose_object_common(struct strbuf *tmp_file,\n \t\telse if (errno == EACCES)\n \t\t\treturn error(_(\"insufficient permission for adding \"\n \t\t\t\t       \"an object to repository database %s\"),\n-\t\t\t\t     get_object_directory());\n+\t\t\t\t     repo_get_object_directory(the_repository));\n \t\telse\n \t\t\treturn error_errno(\n \t\t\t\t_(\"unable to create temporary file\"));\n@@ -2228,7 +2228,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,\n \t\tprepare_loose_object_bulk_checkin();\n \n \t/* Since oid is not determined, save tmp file to odb path. */\n-\tstrbuf_addf(&filename, \"%s/\", get_object_directory());\n+\tstrbuf_addf(&filename, \"%s/\", repo_get_object_directory(the_repository));\n \thdrlen = format_object_header(hdr, sizeof(hdr), OBJ_BLOB, len);\n \n \t/*\ndiff --git a/pack-write.c b/pack-write.c\nindex d07f03d0ab0..27965672f17 100644\n--- a/pack-write.c\n+++ b/pack-write.c\n@@ -12,6 +12,7 @@\n #include \"pack-objects.h\"\n #include \"pack-revindex.h\"\n #include \"path.h\"\n+#include \"repository.h\"\n #include \"strbuf.h\"\n \n void reset_pack_idx_option(struct pack_idx_option *opts)\n@@ -473,7 +474,7 @@ char *index_pack_lockfile(int ip_out, int *is_well_formed)\n \t\tpackname[len-1] = 0;\n \t\tif (skip_prefix(packname, \"keep\\t\", &name))\n \t\t\treturn xstrfmt(\"%s/pack/pack-%s.keep\",\n-\t\t\t\t       get_object_directory(), name);\n+\t\t\t\t       repo_get_object_directory(the_repository), name);\n \t\treturn NULL;\n \t}\n \tif (is_well_formed)\ndiff --git a/packfile.c b/packfile.c\nindex cf12a539eac..df4ba677197 100644\n--- a/packfile.c\n+++ b/packfile.c\n@@ -30,7 +30,7 @@ char *odb_pack_name(struct strbuf *buf,\n \t\t    const char *ext)\n {\n \tstrbuf_reset(buf);\n-\tstrbuf_addf(buf, \"%s/pack/pack-%s.%s\", get_object_directory(),\n+\tstrbuf_addf(buf, \"%s/pack/pack-%s.%s\", repo_get_object_directory(the_repository),\n \t\t    hash_to_hex(hash), ext);\n \treturn buf->buf;\n }\ndiff --git a/prune-packed.c b/prune-packed.c\nindex e54daf740a2..2bb99c29dfb 100644\n--- a/prune-packed.c\n+++ b/prune-packed.c\n@@ -1,10 +1,12 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"object-store-ll.h\"\n #include \"packfile.h\"\n #include \"progress.h\"\n #include \"prune-packed.h\"\n+#include \"repository.h\"\n \n static struct progress *progress;\n \n@@ -37,7 +39,7 @@ void prune_packed_objects(int opts)\n \tif (opts & PRUNE_PACKED_VERBOSE)\n \t\tprogress = start_delayed_progress(_(\"Removing duplicate objects\"), 256);\n \n-\tfor_each_loose_file_in_objdir(get_object_directory(),\n+\tfor_each_loose_file_in_objdir(repo_get_object_directory(the_repository),\n \t\t\t\t      prune_object, NULL, prune_subdir, &opts);\n \n \t/* Ensure we show 100% before finishing progress */\ndiff --git a/repository.c b/repository.c\nindex c8dcba1997a..49c42c25daa 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -105,6 +105,13 @@ const char *repo_get_common_dir(struct repository *repo)\n \treturn repo->commondir;\n }\n \n+const char *repo_get_object_directory(struct repository *repo)\n+{\n+\tif (!repo->objects->odb)\n+\t\tBUG(\"repository hasn't been set up\");\n+\treturn repo->objects->odb->path;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex 404435ad029..778f1511ab1 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -208,6 +208,7 @@ extern struct repository *the_repository;\n \n const char *repo_get_git_dir(struct repository *repo);\n const char *repo_get_common_dir(struct repository *repo);\n+const char *repo_get_object_directory(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/server-info.c b/server-info.c\nindex 1508fa6f825..c5af4cd98a6 100644\n--- a/server-info.c\n+++ b/server-info.c\n@@ -2,7 +2,6 @@\n \n #include \"git-compat-util.h\"\n #include \"dir.h\"\n-#include \"environment.h\"\n #include \"hex.h\"\n #include \"repository.h\"\n #include \"refs.h\"\n@@ -342,7 +341,8 @@ static int write_pack_info_file(struct update_info_ctx *uic)\n \n static int update_info_packs(int force)\n {\n-\tchar *infofile = mkpathdup(\"%s/info/packs\", get_object_directory());\n+\tchar *infofile = mkpathdup(\"%s/info/packs\",\n+\t\t\t\t   repo_get_object_directory(the_repository));\n \tint ret;\n \n \tinit_pack_info(infofile, force);\ndiff --git a/setup.c b/setup.c\nindex fe4a5dfc43b..1ebcab625fe 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2282,7 +2282,7 @@ static void create_object_directory(void)\n \tstruct strbuf path = STRBUF_INIT;\n \tsize_t baselen;\n \n-\tstrbuf_addstr(&path, get_object_directory());\n+\tstrbuf_addstr(&path, repo_get_object_directory(the_repository));\n \tbaselen = path.len;\n \n \tsafe_create_dir(path.buf, 1);\ndiff --git a/tmp-objdir.c b/tmp-objdir.c\nindex a8e4553f274..c2fb9f91930 100644\n--- a/tmp-objdir.c\n+++ b/tmp-objdir.c\n@@ -13,6 +13,7 @@\n #include \"strvec.h\"\n #include \"quote.h\"\n #include \"object-store-ll.h\"\n+#include \"repository.h\"\n \n struct tmp_objdir {\n \tstruct strbuf path;\n@@ -132,7 +133,8 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix)\n \t * can recognize any stale objdirs left behind by a crash and delete\n \t * them.\n \t */\n-\tstrbuf_addf(&t->path, \"%s/tmp_objdir-%s-XXXXXX\", get_object_directory(), prefix);\n+\tstrbuf_addf(&t->path, \"%s/tmp_objdir-%s-XXXXXX\",\n+\t\t    repo_get_object_directory(the_repository), prefix);\n \n \tif (!mkdtemp(t->path.buf)) {\n \t\t/* free, not destroy, as we never touched the filesystem */\n@@ -152,7 +154,7 @@ struct tmp_objdir *tmp_objdir_create(const char *prefix)\n \t}\n \n \tenv_append(&t->env, ALTERNATE_DB_ENVIRONMENT,\n-\t\t   absolute_path(get_object_directory()));\n+\t\t   absolute_path(repo_get_object_directory(the_repository)));\n \tenv_replace(&t->env, DB_ENVIRONMENT, absolute_path(t->path.buf));\n \tenv_replace(&t->env, GIT_QUARANTINE_ENVIRONMENT,\n \t\t    absolute_path(t->path.buf));\n@@ -267,7 +269,7 @@ int tmp_objdir_migrate(struct tmp_objdir *t)\n \t}\n \n \tstrbuf_addbuf(&src, &t->path);\n-\tstrbuf_addstr(&dst, get_object_directory());\n+\tstrbuf_addstr(&dst, repo_get_object_directory(the_repository));\n \n \tret = migrate_paths(&src, &dst);\n \n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502688","messageId":"f82bee6d04f59d3f340dde8c309150a14f58420d.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 04/21] environment: make `get_index_file()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:32Z","receivedAt":"2024-09-12T11:29:34Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_index_file()` function retrieves the path to the index file\nof `the_repository`. Make it accept a `struct repository` such that it\ncan work on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/am.c           |  8 ++++++--\n builtin/commit.c       |  6 +++---\n builtin/merge.c        | 14 ++++++++------\n builtin/stash.c        | 12 ++++++------\n builtin/update-index.c |  2 +-\n builtin/write-tree.c   |  4 ++--\n environment.c          |  7 -------\n environment.h          |  1 -\n repository.c           |  7 +++++++\n repository.h           |  1 +\n wt-status.c            |  3 ++-\n 11 files changed, 36 insertions(+), 29 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 405214e242a..5498ddeb6aa 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1668,7 +1668,9 @@ static void do_commit(const struct am_state *state)\n \tif (!state->no_verify && run_hooks(the_repository, \"pre-applypatch\"))\n \t\texit(1);\n \n-\tif (write_index_as_tree(&tree, the_repository->index, get_index_file(), 0, NULL))\n+\tif (write_index_as_tree(&tree, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository),\n+\t\t\t\t0, NULL))\n \t\tdie(_(\"git write-tree failed to write a tree\"));\n \n \tif (!repo_get_oid_commit(the_repository, \"HEAD\", &parent)) {\n@@ -2078,7 +2080,9 @@ static int clean_index(const struct object_id *head, const struct object_id *rem\n \tif (fast_forward_to(head_tree, head_tree, 1))\n \t\treturn -1;\n \n-\tif (write_index_as_tree(&index, the_repository->index, get_index_file(), 0, NULL))\n+\tif (write_index_as_tree(&index, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository),\n+\t\t\t\t0, NULL))\n \t\treturn -1;\n \n \tindex_tree = parse_tree_indirect(&index);\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex a1c1d16a099..b09320f9070 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -473,7 +473,7 @@ static const char *prepare_index(const char **argv, const char *prefix,\n \t\t\t\t       COMMIT_LOCK | SKIP_IF_UNCHANGED))\n \t\t\tdie(_(\"unable to write new index file\"));\n \t\tcommit_style = COMMIT_AS_IS;\n-\t\tret = get_index_file();\n+\t\tret = repo_get_index_file(the_repository);\n \t\tgoto out;\n \t}\n \n@@ -1874,8 +1874,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \n \trepo_rerere(the_repository, 0);\n \trun_auto_maintenance(quiet);\n-\trun_commit_hook(use_editor, get_index_file(), NULL, \"post-commit\",\n-\t\t\tNULL);\n+\trun_commit_hook(use_editor, repo_get_index_file(the_repository),\n+\t\t\tNULL, \"post-commit\", NULL);\n \tif (amend && !no_post_rewrite) {\n \t\tcommit_post_rewrite(the_repository, current_head, &oid);\n \t}\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex a2bae0700b4..7f5475f738c 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -696,7 +696,9 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,\n \n static void write_tree_trivial(struct object_id *oid)\n {\n-\tif (write_index_as_tree(oid, the_repository->index, get_index_file(), 0, NULL))\n+\tif (write_index_as_tree(oid, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository),\n+\t\t\t\t0, NULL))\n \t\tdie(_(\"git write-tree failed to write a tree\"));\n }\n \n@@ -758,7 +760,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,\n \t\t}\n \t\tif (write_locked_index(the_repository->index, &lock,\n \t\t\t\t       COMMIT_LOCK | SKIP_IF_UNCHANGED))\n-\t\t\tdie(_(\"unable to write %s\"), get_index_file());\n+\t\t\tdie(_(\"unable to write %s\"), repo_get_index_file(the_repository));\n \t\treturn clean ? 0 : 1;\n \t} else {\n \t\treturn try_merge_command(the_repository,\n@@ -840,7 +842,7 @@ static void write_merge_heads(struct commit_list *);\n static void prepare_to_commit(struct commit_list *remoteheads)\n {\n \tstruct strbuf msg = STRBUF_INIT;\n-\tconst char *index_file = get_index_file();\n+\tconst char *index_file = repo_get_index_file(the_repository);\n \n \tif (!no_verify) {\n \t\tint invoked_hook;\n@@ -880,8 +882,8 @@ static void prepare_to_commit(struct commit_list *remoteheads)\n \t\tappend_signoff(&msg, ignored_log_message_bytes(msg.buf, msg.len), 0);\n \twrite_merge_heads(remoteheads);\n \twrite_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len);\n-\tif (run_commit_hook(0 < option_edit, get_index_file(), NULL,\n-\t\t\t    \"prepare-commit-msg\",\n+\tif (run_commit_hook(0 < option_edit, repo_get_index_file(the_repository),\n+\t\t\t    NULL, \"prepare-commit-msg\",\n \t\t\t    git_path_merge_msg(the_repository), \"merge\", NULL))\n \t\tabort_commit(remoteheads, NULL);\n \tif (0 < option_edit) {\n@@ -889,7 +891,7 @@ static void prepare_to_commit(struct commit_list *remoteheads)\n \t\t\tabort_commit(remoteheads, NULL);\n \t}\n \n-\tif (!no_verify && run_commit_hook(0 < option_edit, get_index_file(),\n+\tif (!no_verify && run_commit_hook(0 < option_edit, repo_get_index_file(the_repository),\n \t\t\t\t\t  NULL, \"commit-msg\",\n \t\t\t\t\t  git_path_merge_msg(the_repository), NULL))\n \t\tabort_commit(remoteheads, NULL);\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex ad6bcefb770..f2ec9549a47 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -540,8 +540,8 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\t\t\t\t NULL, NULL, NULL))\n \t\treturn error(_(\"could not write index\"));\n \n-\tif (write_index_as_tree(&c_tree, the_repository->index, get_index_file(), 0,\n-\t\t\t\tNULL))\n+\tif (write_index_as_tree(&c_tree, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository), 0, NULL))\n \t\treturn error(_(\"cannot apply a stash in the middle of a merge\"));\n \n \tif (index) {\n@@ -566,7 +566,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\t\tdiscard_index(the_repository->index);\n \t\t\trepo_read_index(the_repository);\n \t\t\tif (write_index_as_tree(&index_tree, the_repository->index,\n-\t\t\t\t\t\tget_index_file(), 0, NULL))\n+\t\t\t\t\t\trepo_get_index_file(the_repository), 0, NULL))\n \t\t\t\treturn error(_(\"could not save index tree\"));\n \n \t\t\treset_head();\n@@ -1406,8 +1406,8 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \n \tstrbuf_addf(&commit_tree_label, \"index on %s\\n\", msg.buf);\n \tcommit_list_insert(head_commit, &parents);\n-\tif (write_index_as_tree(&info->i_tree, the_repository->index, get_index_file(), 0,\n-\t\t\t\tNULL) ||\n+\tif (write_index_as_tree(&info->i_tree, the_repository->index,\n+\t\t\t\trepo_get_index_file(the_repository), 0, NULL) ||\n \t    commit_tree(commit_tree_label.buf, commit_tree_label.len,\n \t\t\t&info->i_tree, parents, &info->i_commit, NULL, NULL)) {\n \t\tif (!quiet)\n@@ -1905,7 +1905,7 @@ int cmd_stash(int argc, const char **argv, const char *prefix)\n \tprepare_repo_settings(the_repository);\n \tthe_repository->settings.command_requires_full_index = 0;\n \n-\tindex_file = get_index_file();\n+\tindex_file = repo_get_index_file(the_repository);\n \tstrbuf_addf(&stash_index_path, \"%s.stash.%\" PRIuMAX, index_file,\n \t\t    (uintmax_t)pid);\n \ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex 35a1f957adc..86c5d40e400 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -1239,7 +1239,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t\tif (newfd < 0) {\n \t\t\tif (refresh_args.flags & REFRESH_QUIET)\n \t\t\t\texit(128);\n-\t\t\tunable_to_lock_die(get_index_file(), lock_error);\n+\t\t\tunable_to_lock_die(repo_get_index_file(the_repository), lock_error);\n \t\t}\n \t\tif (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))\n \t\t\tdie(\"Unable to write new index file\");\ndiff --git a/builtin/write-tree.c b/builtin/write-tree.c\nindex 8c75b4609b5..9bcc4470ce1 100644\n--- a/builtin/write-tree.c\n+++ b/builtin/write-tree.c\n@@ -6,7 +6,6 @@\n \n #include \"builtin.h\"\n #include \"config.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"hex.h\"\n #include \"tree.h\"\n@@ -44,7 +43,8 @@ int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix)\n \tprepare_repo_settings(the_repository);\n \tthe_repository->settings.command_requires_full_index = 0;\n \n-\tret = write_index_as_tree(&oid, the_repository->index, get_index_file(),\n+\tret = write_index_as_tree(&oid, the_repository->index,\n+\t\t\t\t  repo_get_index_file(the_repository),\n \t\t\t\t  flags, tree_prefix);\n \tswitch (ret) {\n \tcase 0:\ndiff --git a/environment.c b/environment.c\nindex 0a2057399e0..10ef77576c3 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -306,13 +306,6 @@ int odb_pack_keep(const char *name)\n \treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n }\n \n-char *get_index_file(void)\n-{\n-\tif (!the_repository->index_file)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn the_repository->index_file;\n-}\n-\n char *get_graft_file(struct repository *r)\n {\n \tif (!r->graft_file)\ndiff --git a/environment.h b/environment.h\nindex 91125d82991..ff590cfff73 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -106,7 +106,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-char *get_index_file(void);\n char *get_graft_file(struct repository *r);\n void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\ndiff --git a/repository.c b/repository.c\nindex 49c42c25daa..849a912b031 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -112,6 +112,13 @@ const char *repo_get_object_directory(struct repository *repo)\n \treturn repo->objects->odb->path;\n }\n \n+const char *repo_get_index_file(struct repository *repo)\n+{\n+\tif (!repo->index_file)\n+\t\tBUG(\"repository hasn't been set up\");\n+\treturn repo->index_file;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex 778f1511ab1..15660ac2f19 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -209,6 +209,7 @@ extern struct repository *the_repository;\n const char *repo_get_git_dir(struct repository *repo);\n const char *repo_get_common_dir(struct repository *repo);\n const char *repo_get_object_directory(struct repository *repo);\n+const char *repo_get_index_file(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/wt-status.c b/wt-status.c\nindex b477239039d..b813d3fe1c4 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -16,6 +16,7 @@\n #include \"revision.h\"\n #include \"diffcore.h\"\n #include \"quote.h\"\n+#include \"repository.h\"\n #include \"run-command.h\"\n #include \"strvec.h\"\n #include \"remote.h\"\n@@ -152,7 +153,7 @@ void wt_status_prepare(struct repository *r, struct wt_status *s)\n \t\t\t\t\t\"HEAD\", 0, NULL, NULL);\n \ts->reference = \"HEAD\";\n \ts->fp = stdout;\n-\ts->index_file = get_index_file();\n+\ts->index_file = repo_get_index_file(the_repository);\n \ts->change.strdup_strings = 1;\n \ts->untracked.strdup_strings = 1;\n \ts->ignored.strdup_strings = 1;\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502689","messageId":"e3f3f6391da3c81a0c6333ef450270c359772622.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 05/21] environment: make `get_graft_file()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:35Z","receivedAt":"2024-09-12T11:29:40Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_graft_file()` function retrieves the path to the graft file of\n`the_repository`. Make it accept a `struct repository` such that it can\nwork on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/replace.c | 3 +--\n commit.c          | 4 ++--\n environment.c     | 7 -------\n environment.h     | 2 --\n repository.c      | 7 +++++++\n repository.h      | 1 +\n 6 files changed, 11 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 34cc4672bc1..01161350b1f 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -11,7 +11,6 @@\n #include \"builtin.h\"\n #include \"config.h\"\n #include \"editor.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"hex.h\"\n #include \"refs.h\"\n@@ -514,7 +513,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle)\n \n static int convert_graft_file(int force)\n {\n-\tconst char *graft_file = get_graft_file(the_repository);\n+\tconst char *graft_file = repo_get_graft_file(the_repository);\n \tFILE *fp = fopen_or_warn(graft_file, \"r\");\n \tstruct strbuf buf = STRBUF_INIT, err = STRBUF_INIT;\n \tstruct strvec args = STRVEC_INIT;\ndiff --git a/commit.c b/commit.c\nindex 3238772f521..1f710a92a17 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -292,14 +292,14 @@ static int read_graft_file(struct repository *r, const char *graft_file)\n \n void prepare_commit_graft(struct repository *r)\n {\n-\tchar *graft_file;\n+\tconst char *graft_file;\n \n \tif (r->parsed_objects->commit_graft_prepared)\n \t\treturn;\n \tif (!startup_info->have_repository)\n \t\treturn;\n \n-\tgraft_file = get_graft_file(r);\n+\tgraft_file = repo_get_graft_file(r);\n \tread_graft_file(r, graft_file);\n \t/* make sure shallows are read */\n \tis_repository_shallow(r);\ndiff --git a/environment.c b/environment.c\nindex 10ef77576c3..371f01a705d 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -306,13 +306,6 @@ int odb_pack_keep(const char *name)\n \treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n }\n \n-char *get_graft_file(struct repository *r)\n-{\n-\tif (!r->graft_file)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn r->graft_file;\n-}\n-\n static void set_git_dir_1(const char *path)\n {\n \txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\ndiff --git a/environment.h b/environment.h\nindex ff590cfff73..d12c48481b6 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -1,7 +1,6 @@\n #ifndef ENVIRONMENT_H\n #define ENVIRONMENT_H\n \n-struct repository;\n struct strvec;\n \n /*\n@@ -106,7 +105,6 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-char *get_graft_file(struct repository *r);\n void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\ndiff --git a/repository.c b/repository.c\nindex 849a912b031..c2c231a7fd8 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -119,6 +119,13 @@ const char *repo_get_index_file(struct repository *repo)\n \treturn repo->index_file;\n }\n \n+const char *repo_get_graft_file(struct repository *repo)\n+{\n+\tif (!repo->graft_file)\n+\t\tBUG(\"repository hasn't been set up\");\n+\treturn repo->graft_file;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex 15660ac2f19..ad0f984b444 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -210,6 +210,7 @@ const char *repo_get_git_dir(struct repository *repo);\n const char *repo_get_common_dir(struct repository *repo);\n const char *repo_get_object_directory(struct repository *repo);\n const char *repo_get_index_file(struct repository *repo);\n+const char *repo_get_graft_file(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502690","messageId":"00950932195ddb53dd1e54f93a6040bce4f6a434.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 06/21] environment: make `get_git_work_tree()` accept a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:40Z","receivedAt":"2024-09-12T11:29:42Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `get_git_work_tree()` function retrieves the path of the work tree\nof `the_repository`. Make it accept a `struct repository` such that it\ncan work on arbitrary repositories and make it part of the repository\nsubsystem. This reduces our reliance on `the_repository` and clarifies\nscope.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/blame.c             |  2 +-\n builtin/difftool.c          |  4 ++--\n builtin/fsmonitor--daemon.c |  4 ++--\n builtin/init-db.c           |  4 ++--\n builtin/reset.c             |  5 +++--\n builtin/rev-parse.c         |  4 ++--\n builtin/stash.c             |  2 +-\n builtin/submodule--helper.c |  2 +-\n builtin/update-index.c      |  2 +-\n dir.c                       |  3 ++-\n environment.c               |  7 +------\n environment.h               |  1 -\n fsmonitor.c                 |  3 ++-\n pathspec.c                  |  2 +-\n repository.c                |  5 +++++\n repository.h                |  1 +\n setup.c                     | 16 ++++++++--------\n trace.c                     |  3 +--\n 18 files changed, 36 insertions(+), 34 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 35e975fb132..1ffdda50904 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -1081,7 +1081,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t\tpath = add_prefix(prefix, argv[1]);\n \t\t\targv[1] = argv[2];\n \t\t} else {\t/* (2a) */\n-\t\t\tif (argc == 2 && is_a_rev(argv[1]) && !get_git_work_tree())\n+\t\t\tif (argc == 2 && is_a_rev(argv[1]) && !repo_get_work_tree(the_repository))\n \t\t\t\tdie(\"missing <path> to blame\");\n \t\t\tpath = add_prefix(prefix, argv[argc - 1]);\n \t\t}\ndiff --git a/builtin/difftool.c b/builtin/difftool.c\nindex 8c59411e6e0..7f2cbd797ad 100644\n--- a/builtin/difftool.c\n+++ b/builtin/difftool.c\n@@ -378,7 +378,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,\n \tstruct hashmap wt_modified, tmp_modified;\n \tint indices_loaded = 0;\n \n-\tworkdir = get_git_work_tree();\n+\tworkdir = repo_get_work_tree(the_repository);\n \n \t/* Setup temp directories */\n \ttmp = getenv(\"TMPDIR\");\n@@ -739,7 +739,7 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)\n \tif (!no_index){\n \t\tsetup_work_tree();\n \t\tsetenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1);\n-\t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);\n+\t\tsetenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(the_repository)), 1);\n \t} else if (dir_diff)\n \t\tdie(_(\"options '%s' and '%s' cannot be used together\"), \"--dir-diff\", \"--no-index\");\n \ndiff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c\nindex c54e736716a..25451d999e9 100644\n--- a/builtin/fsmonitor--daemon.c\n+++ b/builtin/fsmonitor--daemon.c\n@@ -2,7 +2,6 @@\n #include \"abspath.h\"\n #include \"config.h\"\n #include \"dir.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"parse-options.h\"\n #include \"fsmonitor-ll.h\"\n@@ -1291,7 +1290,8 @@ static int fsmonitor_run_daemon(void)\n \n \t/* Prepare to (recursively) watch the <worktree-root> directory. */\n \tstrbuf_init(&state.path_worktree_watch, 0);\n-\tstrbuf_addstr(&state.path_worktree_watch, absolute_path(get_git_work_tree()));\n+\tstrbuf_addstr(&state.path_worktree_watch,\n+\t\t      absolute_path(repo_get_work_tree(the_repository)));\n \tstate.nr_paths_watching = 1;\n \n \tstrbuf_init(&state.alias.alias, 0);\ndiff --git a/builtin/init-db.c b/builtin/init-db.c\nindex 582dcf20f86..fb04962dcea 100644\n--- a/builtin/init-db.c\n+++ b/builtin/init-db.c\n@@ -231,9 +231,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)\n \t\t\tset_git_work_tree(work_tree);\n \t\telse\n \t\t\tset_git_work_tree(git_work_tree_cfg);\n-\t\tif (access(get_git_work_tree(), X_OK))\n+\t\tif (access(repo_get_work_tree(the_repository), X_OK))\n \t\t\tdie_errno (_(\"Cannot access work tree '%s'\"),\n-\t\t\t\t   get_git_work_tree());\n+\t\t\t\t   repo_get_work_tree(the_repository));\n \t}\n \telse {\n \t\tif (real_git_dir)\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 5f941fb3a29..86b2f07d660 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -26,6 +26,7 @@\n #include \"object-name.h\"\n #include \"parse-options.h\"\n #include \"path.h\"\n+#include \"repository.h\"\n #include \"unpack-trees.h\"\n #include \"cache-tree.h\"\n #include \"setup.h\"\n@@ -441,7 +442,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \telse\n \t\ttrace2_cmd_mode(reset_type_names[reset_type]);\n \n-\tif (reset_type != SOFT && (reset_type != MIXED || get_git_work_tree()))\n+\tif (reset_type != SOFT && (reset_type != MIXED || repo_get_work_tree(the_repository)))\n \t\tsetup_work_tree();\n \n \tif (reset_type == MIXED && is_bare_repository())\n@@ -474,7 +475,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\t\t\tgoto cleanup;\n \t\t\t}\n \t\t\tthe_repository->index->updated_skipworktree = 1;\n-\t\t\tif (!no_refresh && get_git_work_tree()) {\n+\t\t\tif (!no_refresh && repo_get_work_tree(the_repository)) {\n \t\t\t\tuint64_t t_begin, t_delta_in_ms;\n \n \t\t\t\tt_begin = getnanotime();\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex cd85fe57bb0..a5108266daf 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -967,7 +967,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--show-toplevel\")) {\n-\t\t\t\tconst char *work_tree = get_git_work_tree();\n+\t\t\t\tconst char *work_tree = repo_get_work_tree(the_repository);\n \t\t\t\tif (work_tree)\n \t\t\t\t\tprint_path(work_tree, prefix, format, DEFAULT_UNMODIFIED);\n \t\t\t\telse\n@@ -992,7 +992,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tconst char *pfx = prefix;\n \t\t\t\tif (!is_inside_work_tree()) {\n \t\t\t\t\tconst char *work_tree =\n-\t\t\t\t\t\tget_git_work_tree();\n+\t\t\t\t\t\trepo_get_work_tree(the_repository);\n \t\t\t\t\tif (work_tree)\n \t\t\t\t\t\tprintf(\"%s\\n\", work_tree);\n \t\t\t\t\tcontinue;\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex f2ec9549a47..354641b3f10 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -641,7 +641,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,\n \t\tcp.git_cmd = 1;\n \t\tcp.dir = prefix;\n \t\tstrvec_pushf(&cp.env, GIT_WORK_TREE_ENVIRONMENT\"=%s\",\n-\t\t\t     absolute_path(get_git_work_tree()));\n+\t\t\t     absolute_path(repo_get_work_tree(the_repository)));\n \t\tstrvec_pushf(&cp.env, GIT_DIR_ENVIRONMENT\"=%s\",\n \t\t\t     absolute_path(repo_get_git_dir(the_repository)));\n \t\tstrvec_push(&cp.args, \"status\");\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 85fb23dee84..865b454d693 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1709,7 +1709,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,\n \t\texit(128);\n \n \tif (!is_absolute_path(clone_data->path))\n-\t\tclone_data_path = to_free = xstrfmt(\"%s/%s\", get_git_work_tree(),\n+\t\tclone_data_path = to_free = xstrfmt(\"%s/%s\", repo_get_work_tree(the_repository),\n \t\t\t\t\t\t    clone_data->path);\n \n \tif (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0)\ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex 86c5d40e400..8baa2256194 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -1194,7 +1194,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t\t\t\t  \"remove or change it, if you really want to \"\n \t\t\t\t  \"enable the untracked cache\"));\n \t\tadd_untracked_cache(the_repository->index);\n-\t\treport(_(\"Untracked cache enabled for '%s'\"), get_git_work_tree());\n+\t\treport(_(\"Untracked cache enabled for '%s'\"), repo_get_work_tree(the_repository));\n \t\tbreak;\n \tdefault:\n \t\tBUG(\"bad untracked_cache value: %d\", untracked_cache);\ndiff --git a/dir.c b/dir.c\nindex 5a23376bdae..c43b5e30813 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -20,6 +20,7 @@\n #include \"object-store-ll.h\"\n #include \"path.h\"\n #include \"refs.h\"\n+#include \"repository.h\"\n #include \"wildmatch.h\"\n #include \"pathspec.h\"\n #include \"utf8.h\"\n@@ -2838,7 +2839,7 @@ static const char *get_ident_string(void)\n \t\treturn sb.buf;\n \tif (uname(&uts) < 0)\n \t\tdie_errno(_(\"failed to get kernel name and information\"));\n-\tstrbuf_addf(&sb, \"Location %s, system %s\", get_git_work_tree(),\n+\tstrbuf_addf(&sb, \"Location %s, system %s\", repo_get_work_tree(the_repository),\n \t\t    uts.sysname);\n \treturn sb.buf;\n }\ndiff --git a/environment.c b/environment.c\nindex 371f01a705d..4d0637b3822 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -219,7 +219,7 @@ void setup_git_env(const char *git_dir)\n int is_bare_repository(void)\n {\n \t/* if core.bare is not 'false', let's see if there is a work tree */\n-\treturn is_bare_repository_cfg && !get_git_work_tree();\n+\treturn is_bare_repository_cfg && !repo_get_work_tree(the_repository);\n }\n \n int have_git_dir(void)\n@@ -268,11 +268,6 @@ void set_git_work_tree(const char *new_work_tree)\n \trepo_set_worktree(the_repository, new_work_tree);\n }\n \n-const char *get_git_work_tree(void)\n-{\n-\treturn the_repository->worktree;\n-}\n-\n int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n {\n \tint fd;\ndiff --git a/environment.h b/environment.h\nindex d12c48481b6..52e1803aba6 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -108,7 +108,6 @@ extern char *git_work_tree_cfg;\n void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\n-const char *get_git_work_tree(void);\n void set_git_work_tree(const char *tree);\n \n #define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\ndiff --git a/fsmonitor.c b/fsmonitor.c\nindex 28130f748f7..237ca59d004 100644\n--- a/fsmonitor.c\n+++ b/fsmonitor.c\n@@ -8,6 +8,7 @@\n #include \"fsmonitor.h\"\n #include \"fsmonitor-ipc.h\"\n #include \"name-hash.h\"\n+#include \"repository.h\"\n #include \"run-command.h\"\n #include \"strbuf.h\"\n #include \"trace2.h\"\n@@ -169,7 +170,7 @@ static int query_fsmonitor_hook(struct repository *r,\n \tstrvec_pushf(&cp.args, \"%d\", version);\n \tstrvec_pushf(&cp.args, \"%s\", last_update);\n \tcp.use_shell = 1;\n-\tcp.dir = get_git_work_tree();\n+\tcp.dir = repo_get_work_tree(the_repository);\n \n \ttrace2_region_enter(\"fsm_hook\", \"query\", NULL);\n \ndiff --git a/pathspec.c b/pathspec.c\nindex 416fe1e3dcc..0fc6f84a6e6 100644\n--- a/pathspec.c\n+++ b/pathspec.c\n@@ -495,7 +495,7 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,\n \t\t\tif (!have_git_dir())\n \t\t\t\tdie(_(\"'%s' is outside the directory tree\"),\n \t\t\t\t    copyfrom);\n-\t\t\thint_path = get_git_work_tree();\n+\t\t\thint_path = repo_get_work_tree(the_repository);\n \t\t\tif (!hint_path)\n \t\t\t\thint_path = repo_get_git_dir(the_repository);\n \t\t\tdie(_(\"%s: '%s' is outside repository at '%s'\"), elt,\ndiff --git a/repository.c b/repository.c\nindex c2c231a7fd8..afdd1946211 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -126,6 +126,11 @@ const char *repo_get_graft_file(struct repository *repo)\n \treturn repo->graft_file;\n }\n \n+const char *repo_get_work_tree(struct repository *repo)\n+{\n+\treturn repo->worktree;\n+}\n+\n static void repo_set_commondir(struct repository *repo,\n \t\t\t       const char *commondir)\n {\ndiff --git a/repository.h b/repository.h\nindex ad0f984b444..c603e969ae7 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -211,6 +211,7 @@ const char *repo_get_common_dir(struct repository *repo);\n const char *repo_get_object_directory(struct repository *repo);\n const char *repo_get_index_file(struct repository *repo);\n const char *repo_get_graft_file(struct repository *repo);\n+const char *repo_get_work_tree(struct repository *repo);\n \n /*\n  * Define a custom repository layout. Any field can be NULL, which\ndiff --git a/setup.c b/setup.c\nindex 1ebcab625fe..1bfec288ab6 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -51,7 +51,7 @@ static int abspath_part_inside_repo(char *path)\n \tsize_t wtlen;\n \tchar *path0;\n \tint off;\n-\tconst char *work_tree = precompose_string_if_needed(get_git_work_tree());\n+\tconst char *work_tree = precompose_string_if_needed(repo_get_work_tree(the_repository));\n \tstruct strbuf realpath = STRBUF_INIT;\n \n \tif (!work_tree)\n@@ -147,7 +147,7 @@ char *prefix_path(const char *prefix, int len, const char *path)\n {\n \tchar *r = prefix_path_gently(prefix, len, NULL, path);\n \tif (!r) {\n-\t\tconst char *hint_path = get_git_work_tree();\n+\t\tconst char *hint_path = repo_get_work_tree(the_repository);\n \t\tif (!hint_path)\n \t\t\thint_path = repo_get_git_dir(the_repository);\n \t\tdie(_(\"'%s' is outside repository at '%s'\"), path,\n@@ -475,7 +475,7 @@ int is_inside_git_dir(void)\n int is_inside_work_tree(void)\n {\n \tif (inside_work_tree < 0)\n-\t\tinside_work_tree = is_inside_dir(get_git_work_tree());\n+\t\tinside_work_tree = is_inside_dir(repo_get_work_tree(the_repository));\n \treturn inside_work_tree;\n }\n \n@@ -490,7 +490,7 @@ void setup_work_tree(void)\n \tif (work_tree_config_is_bogus)\n \t\tdie(_(\"unable to set up work tree using invalid config\"));\n \n-\twork_tree = get_git_work_tree();\n+\twork_tree = repo_get_work_tree(the_repository);\n \tif (!work_tree || chdir_notify(work_tree))\n \t\tdie(_(\"this operation must be run in a work tree\"));\n \n@@ -547,7 +547,7 @@ static void setup_original_cwd(void)\n \t * Get our worktree; we only protect the current working directory\n \t * if it's in the worktree.\n \t */\n-\tworktree = get_git_work_tree();\n+\tworktree = repo_get_work_tree(the_repository);\n \tif (!worktree)\n \t\tgoto no_prevention_needed;\n \n@@ -1062,9 +1062,9 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,\n \t\tset_git_work_tree(\".\");\n \n \t/* set_git_work_tree() must have been called by now */\n-\tworktree = get_git_work_tree();\n+\tworktree = repo_get_work_tree(the_repository);\n \n-\t/* both get_git_work_tree() and cwd are already normalized */\n+\t/* both repo_get_work_tree() and cwd are already normalized */\n \tif (!strcmp(cwd->buf, worktree)) { /* cwd == worktree */\n \t\tset_git_dir(gitdirenv, 0);\n \t\tfree(gitfile);\n@@ -2192,7 +2192,7 @@ static int create_default_files(const char *template_path,\n \tchar *path;\n \tint reinit;\n \tint filemode;\n-\tconst char *work_tree = get_git_work_tree();\n+\tconst char *work_tree = repo_get_work_tree(the_repository);\n \n \t/*\n \t * First copy the templates -- we might have the default\ndiff --git a/trace.c b/trace.c\nindex e6728c301f3..d8c43773ae8 100644\n--- a/trace.c\n+++ b/trace.c\n@@ -25,7 +25,6 @@\n \n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n-#include \"environment.h\"\n #include \"repository.h\"\n #include \"quote.h\"\n #include \"setup.h\"\n@@ -308,7 +307,7 @@ void trace_repo_setup(void)\n \n \tcwd = xgetcwd();\n \n-\tif (!(git_work_tree = get_git_work_tree()))\n+\tif (!(git_work_tree = repo_get_work_tree(the_repository)))\n \t\tgit_work_tree = \"(null)\";\n \n \tif (!startup_info->prefix)\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502691","messageId":"8c0010b439725585ffc3a9bb4f1f7eb4944a2d6f.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 07/21] config: document `read_early_config()` and `read_very_early_config()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:43Z","receivedAt":"2024-09-12T11:29:45Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"It's not clear what `read_early_config()` and `read_very_early_config()`\ndo differently compared to `repo_read_config()` from just looking at\ntheir names. Document both of these in the header file to clarify their\nintent.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c |  4 ----\n config.h | 11 +++++++++++\n 2 files changed, 11 insertions(+), 4 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 0b87f0f9050..a8357ea9544 100644\n--- a/config.c\n+++ b/config.c\n@@ -2234,10 +2234,6 @@ void read_early_config(config_fn_t cb, void *data)\n \tstrbuf_release(&gitdir);\n }\n \n-/*\n- * Read config but only enumerate system and global settings.\n- * Omit any repo-local, worktree-local, or command-line settings.\n- */\n void read_very_early_config(config_fn_t cb, void *data)\n {\n \tstruct config_options opts = { 0 };\ndiff --git a/config.h b/config.h\nindex d0497157c52..f5fa833cb98 100644\n--- a/config.h\n+++ b/config.h\n@@ -192,7 +192,18 @@ int git_config_from_blob_oid(config_fn_t fn, const char *name,\n void git_config_push_parameter(const char *text);\n void git_config_push_env(const char *spec);\n int git_config_from_parameters(config_fn_t fn, void *data);\n+\n+/*\n+ * Read config when the Git directory has not yet been set up. In case\n+ * `the_repository` has not yet been set up, try to discover the Git\n+ * directory to read the configuration from.\n+ */\n void read_early_config(config_fn_t cb, void *data);\n+\n+/*\n+ * Read config but only enumerate system and global settings.\n+ * Omit any repo-local, worktree-local, or command-line settings.\n+ */\n void read_very_early_config(config_fn_t cb, void *data);\n \n /**\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502692","messageId":"1ed3d3f1d7142129212750602585550c69aa599e.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 08/21] config: make dependency on repo in `read_early_config()` explicit","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:45Z","receivedAt":"2024-09-12T11:29:47Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `read_early_config()` function can be used to read configuration\nwhere a repository has not yet been set up. As such, it is optional\nwhether or not `the_repository` has already been initialized. If it was\ninitialized we use its commondir and gitdir. If not, the function will\ntry to detect the Git directories by itself and, if found, also parse\ntheir config files.\n\nThis means that we implicitly rely on `the_repository`. Make this\ndependency explicit by passing a `struct repository`. This allows us to\nagain drop the `USE_THE_REPOSITORY_VARIABLE` define in \"config.c\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n alias.c                |  6 ++++--\n config.c               | 10 ++++------\n config.h               |  2 +-\n help.c                 |  2 +-\n pager.c                |  7 +++++--\n t/helper/test-config.c |  3 ++-\n trace2/tr2_cfg.c       |  4 +++-\n 7 files changed, 20 insertions(+), 14 deletions(-)\n\ndiff --git a/alias.c b/alias.c\nindex 4daafd9bdae..1a1a141a0ae 100644\n--- a/alias.c\n+++ b/alias.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"alias.h\"\n #include \"config.h\"\n@@ -37,7 +39,7 @@ char *alias_lookup(const char *alias)\n {\n \tstruct config_alias_data data = { alias, NULL };\n \n-\tread_early_config(config_alias_cb, &data);\n+\tread_early_config(the_repository, config_alias_cb, &data);\n \n \treturn data.v;\n }\n@@ -46,7 +48,7 @@ void list_aliases(struct string_list *list)\n {\n \tstruct config_alias_data data = { NULL, NULL, list };\n \n-\tread_early_config(config_alias_cb, &data);\n+\tread_early_config(the_repository, config_alias_cb, &data);\n }\n \n void quote_cmdline(struct strbuf *buf, const char **argv)\ndiff --git a/config.c b/config.c\nindex a8357ea9544..043e1c8a078 100644\n--- a/config.c\n+++ b/config.c\n@@ -6,8 +6,6 @@\n  *\n  */\n \n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"advice.h\"\n@@ -2204,7 +2202,7 @@ static void configset_iter(struct config_set *set, config_fn_t fn, void *data)\n \t}\n }\n \n-void read_early_config(config_fn_t cb, void *data)\n+void read_early_config(struct repository *repo, config_fn_t cb, void *data)\n {\n \tstruct config_options opts = {0};\n \tstruct strbuf commondir = STRBUF_INIT;\n@@ -2212,9 +2210,9 @@ void read_early_config(config_fn_t cb, void *data)\n \n \topts.respect_includes = 1;\n \n-\tif (have_git_dir()) {\n-\t\topts.commondir = repo_get_common_dir(the_repository);\n-\t\topts.git_dir = repo_get_git_dir(the_repository);\n+\tif (repo && repo->gitdir) {\n+\t\topts.commondir = repo_get_common_dir(repo);\n+\t\topts.git_dir = repo_get_git_dir(repo);\n \t/*\n \t * When setup_git_directory() was not yet asked to discover the\n \t * GIT_DIR, we ask discover_git_directory() to figure out whether there\ndiff --git a/config.h b/config.h\nindex f5fa833cb98..5c730c4f899 100644\n--- a/config.h\n+++ b/config.h\n@@ -198,7 +198,7 @@ int git_config_from_parameters(config_fn_t fn, void *data);\n  * `the_repository` has not yet been set up, try to discover the Git\n  * directory to read the configuration from.\n  */\n-void read_early_config(config_fn_t cb, void *data);\n+void read_early_config(struct repository *repo, config_fn_t cb, void *data);\n \n /*\n  * Read config but only enumerate system and global settings.\ndiff --git a/help.c b/help.c\nindex c03863f2265..413c93edaea 100644\n--- a/help.c\n+++ b/help.c\n@@ -618,7 +618,7 @@ const char *help_unknown_cmd(const char *cmd)\n \tmemset(&other_cmds, 0, sizeof(other_cmds));\n \tmemset(&aliases, 0, sizeof(aliases));\n \n-\tread_early_config(git_unknown_cmd_config, NULL);\n+\tread_early_config(the_repository, git_unknown_cmd_config, NULL);\n \n \t/*\n \t * Disable autocorrection prompt in a non-interactive session\ndiff --git a/pager.c b/pager.c\nindex 9c24ce62633..40b664f893c 100644\n--- a/pager.c\n+++ b/pager.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"config.h\"\n #include \"editor.h\"\n@@ -92,7 +94,8 @@ const char *git_pager(int stdout_is_tty)\n \tpager = getenv(\"GIT_PAGER\");\n \tif (!pager) {\n \t\tif (!pager_program)\n-\t\t\tread_early_config(core_pager_config, NULL);\n+\t\t\tread_early_config(the_repository,\n+\t\t\t\t\t  core_pager_config, NULL);\n \t\tpager = pager_program;\n \t}\n \tif (!pager)\n@@ -298,7 +301,7 @@ int check_pager_config(const char *cmd)\n \tdata.want = -1;\n \tdata.value = NULL;\n \n-\tread_early_config(pager_command_config, &data);\n+\tread_early_config(the_repository, pager_command_config, &data);\n \n \tif (data.value)\n \t\tpager_program = data.value;\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex e193079ed54..33247f0e92e 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -96,7 +96,8 @@ int cmd__config(int argc, const char **argv)\n \tstruct config_set cs;\n \n \tif (argc == 3 && !strcmp(argv[1], \"read_early_config\")) {\n-\t\tread_early_config(early_config_cb, (void *)argv[2]);\n+\t\tread_early_config(the_repository, early_config_cb,\n+\t\t\t\t  (void *)argv[2]);\n \t\treturn 0;\n \t}\n \ndiff --git a/trace2/tr2_cfg.c b/trace2/tr2_cfg.c\nindex d96d908bb9d..22a99a0682a 100644\n--- a/trace2/tr2_cfg.c\n+++ b/trace2/tr2_cfg.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"config.h\"\n #include \"strbuf.h\"\n@@ -124,7 +126,7 @@ void tr2_cfg_list_config_fl(const char *file, int line)\n \tstruct tr2_cfg_data data = { file, line };\n \n \tif (tr2_cfg_load_patterns() > 0)\n-\t\tread_early_config(tr2_cfg_cb, &data);\n+\t\tread_early_config(the_repository, tr2_cfg_cb, &data);\n }\n \n void tr2_list_env_vars_fl(const char *file, int line)\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502693","messageId":"b164373d10bea7da632cb30ac85853e3162739a7.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 09/21] environment: move object database functions into object layer","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:48Z","receivedAt":"2024-09-12T11:29:50Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The `odb_mkstemp()` and `odb_pack_keep()` functions are quite clearly\ntied to the object store, but regardless of that they are located in\n\"environment.c\". Move them over, which also helps to get rid of\ndependencies on `the_repository` in the environment subsystem.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n bundle-uri.c      |  2 +-\n environment.c     | 34 ----------------------------------\n environment.h     | 15 ---------------\n object-file.c     | 33 +++++++++++++++++++++++++++++++++\n object-store-ll.h | 15 +++++++++++++++\n 5 files changed, 49 insertions(+), 50 deletions(-)\n\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 1e0ee156ba3..eb8eca078bb 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -4,7 +4,6 @@\n #include \"bundle-uri.h\"\n #include \"bundle.h\"\n #include \"copy.h\"\n-#include \"environment.h\"\n #include \"gettext.h\"\n #include \"refs.h\"\n #include \"run-command.h\"\n@@ -13,6 +12,7 @@\n #include \"config.h\"\n #include \"fetch-pack.h\"\n #include \"remote.h\"\n+#include \"object-store-ll.h\"\n \n static struct {\n \tenum bundle_list_heuristic heuristic;\ndiff --git a/environment.c b/environment.c\nindex 4d0637b3822..f337efd1dd5 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -23,7 +23,6 @@\n #include \"commit.h\"\n #include \"strvec.h\"\n #include \"object-file.h\"\n-#include \"object-store-ll.h\"\n #include \"path.h\"\n #include \"replace-object.h\"\n #include \"tmp-objdir.h\"\n@@ -268,39 +267,6 @@ void set_git_work_tree(const char *new_work_tree)\n \trepo_set_worktree(the_repository, new_work_tree);\n }\n \n-int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n-{\n-\tint fd;\n-\t/*\n-\t * we let the umask do its job, don't try to be more\n-\t * restrictive except to remove write permission.\n-\t */\n-\tint mode = 0444;\n-\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n-\tfd = git_mkstemp_mode(temp_filename->buf, mode);\n-\tif (0 <= fd)\n-\t\treturn fd;\n-\n-\t/* slow path */\n-\t/* some mkstemp implementations erase temp_filename on failure */\n-\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n-\tsafe_create_leading_directories(temp_filename->buf);\n-\treturn xmkstemp_mode(temp_filename->buf, mode);\n-}\n-\n-int odb_pack_keep(const char *name)\n-{\n-\tint fd;\n-\n-\tfd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n-\tif (0 <= fd)\n-\t\treturn fd;\n-\n-\t/* slow path */\n-\tsafe_create_leading_directories_const(name);\n-\treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n-}\n-\n static void set_git_dir_1(const char *path)\n {\n \txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\ndiff --git a/environment.h b/environment.h\nindex 52e1803aba6..682d4f2e3b5 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -200,21 +200,6 @@ extern int grafts_keep_true_parents;\n \n extern int repository_format_precious_objects;\n \n-/*\n- * Create a temporary file rooted in the object database directory, or\n- * die on failure. The filename is taken from \"pattern\", which should have the\n- * usual \"XXXXXX\" trailer, and the resulting filename is written into the\n- * \"template\" buffer. Returns the open descriptor.\n- */\n-int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);\n-\n-/*\n- * Create a pack .keep file named \"name\" (which should generally be the output\n- * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on\n- * error.\n- */\n-int odb_pack_keep(const char *name);\n-\n const char *get_log_output_encoding(void);\n const char *get_commit_output_encoding(void);\n \ndiff --git a/object-file.c b/object-file.c\nindex fa4121b98ad..968da27cd41 100644\n--- a/object-file.c\n+++ b/object-file.c\n@@ -419,6 +419,39 @@ enum scld_error safe_create_leading_directories_const(const char *path)\n \treturn result;\n }\n \n+int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)\n+{\n+\tint fd;\n+\t/*\n+\t * we let the umask do its job, don't try to be more\n+\t * restrictive except to remove write permission.\n+\t */\n+\tint mode = 0444;\n+\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n+\tfd = git_mkstemp_mode(temp_filename->buf, mode);\n+\tif (0 <= fd)\n+\t\treturn fd;\n+\n+\t/* slow path */\n+\t/* some mkstemp implementations erase temp_filename on failure */\n+\tgit_path_buf(temp_filename, \"objects/%s\", pattern);\n+\tsafe_create_leading_directories(temp_filename->buf);\n+\treturn xmkstemp_mode(temp_filename->buf, mode);\n+}\n+\n+int odb_pack_keep(const char *name)\n+{\n+\tint fd;\n+\n+\tfd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n+\tif (0 <= fd)\n+\t\treturn fd;\n+\n+\t/* slow path */\n+\tsafe_create_leading_directories_const(name);\n+\treturn open(name, O_RDWR|O_CREAT|O_EXCL, 0600);\n+}\n+\n static void fill_loose_path(struct strbuf *buf, const struct object_id *oid)\n {\n \tint i;\ndiff --git a/object-store-ll.h b/object-store-ll.h\nindex c5f2bb2fc2f..53b8e693b1b 100644\n--- a/object-store-ll.h\n+++ b/object-store-ll.h\n@@ -231,6 +231,21 @@ struct raw_object_store {\n struct raw_object_store *raw_object_store_new(void);\n void raw_object_store_clear(struct raw_object_store *o);\n \n+/*\n+ * Create a temporary file rooted in the object database directory, or\n+ * die on failure. The filename is taken from \"pattern\", which should have the\n+ * usual \"XXXXXX\" trailer, and the resulting filename is written into the\n+ * \"template\" buffer. Returns the open descriptor.\n+ */\n+int odb_mkstemp(struct strbuf *temp_filename, const char *pattern);\n+\n+/*\n+ * Create a pack .keep file named \"name\" (which should generally be the output\n+ * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on\n+ * error.\n+ */\n+int odb_pack_keep(const char *name);\n+\n /*\n  * Put in `buf` the name of the file in the local object database that\n  * would be used to store a loose object with the specified oid.\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502694","messageId":"85c10fad522ba6d7369129d115e5cc240ef6d352.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 10/21] environment: make `get_git_namespace()` self-contained","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:51Z","receivedAt":"2024-09-12T11:29:53Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The logic to set up and retrieve `git_namespace` is distributed across\ndifferent functions which communicate with each other via a global\nenvironment variable. This is rather pointless though, as the value is\nalways derived from an environment variable, and this environment\nvariable does not change after we have parsed global options.\n\nConvert the function to be fully self-contained such that it lazily\npopulates once called.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n environment.c | 57 ++++++++++++++++++++++++++-------------------------\n 1 file changed, 29 insertions(+), 28 deletions(-)\n\ndiff --git a/environment.c b/environment.c\nindex f337efd1dd5..49844418419 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -122,8 +122,6 @@ int core_preload_index = 1;\n /* This is set by setup_git_dir_gently() and/or git_default_config() */\n char *git_work_tree_cfg;\n \n-static char *git_namespace;\n-\n /*\n  * Repository-local GIT_* environment variables; see environment.h for details.\n  */\n@@ -146,27 +144,6 @@ const char * const local_repo_env[] = {\n \tNULL\n };\n \n-static char *expand_namespace(const char *raw_namespace)\n-{\n-\tstruct strbuf buf = STRBUF_INIT;\n-\tstruct strbuf **components, **c;\n-\n-\tif (!raw_namespace || !*raw_namespace)\n-\t\treturn xstrdup(\"\");\n-\n-\tstrbuf_addstr(&buf, raw_namespace);\n-\tcomponents = strbuf_split(&buf, '/');\n-\tstrbuf_reset(&buf);\n-\tfor (c = components; *c; c++)\n-\t\tif (strcmp((*c)->buf, \"/\") != 0)\n-\t\t\tstrbuf_addf(&buf, \"refs/namespaces/%s\", (*c)->buf);\n-\tstrbuf_list_free(components);\n-\tif (check_refname_format(buf.buf, 0))\n-\t\tdie(_(\"bad git namespace path \\\"%s\\\"\"), raw_namespace);\n-\tstrbuf_addch(&buf, '/');\n-\treturn strbuf_detach(&buf, NULL);\n-}\n-\n const char *getenv_safe(struct strvec *argv, const char *name)\n {\n \tconst char *value = getenv(name);\n@@ -205,8 +182,6 @@ void setup_git_env(const char *git_dir)\n \t\t\t\t\t\t\t  : \"refs/replace/\");\n \tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\n \n-\tfree(git_namespace);\n-\tgit_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));\n \tshallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);\n \tif (shallow_file)\n \t\tset_alternate_shallow_file(the_repository, shallow_file, 0);\n@@ -229,9 +204,35 @@ int have_git_dir(void)\n \n const char *get_git_namespace(void)\n {\n-\tif (!git_namespace)\n-\t\tBUG(\"git environment hasn't been setup\");\n-\treturn git_namespace;\n+\tstatic const char *namespace;\n+\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tstruct strbuf **components, **c;\n+\tconst char *raw_namespace;\n+\n+\tif (namespace)\n+\t\treturn namespace;\n+\n+\traw_namespace = getenv(GIT_NAMESPACE_ENVIRONMENT);\n+\tif (!raw_namespace || !*raw_namespace) {\n+\t\tnamespace = \"\";\n+\t\treturn namespace;\n+\t}\n+\n+\tstrbuf_addstr(&buf, raw_namespace);\n+\tcomponents = strbuf_split(&buf, '/');\n+\tstrbuf_reset(&buf);\n+\tfor (c = components; *c; c++)\n+\t\tif (strcmp((*c)->buf, \"/\") != 0)\n+\t\t\tstrbuf_addf(&buf, \"refs/namespaces/%s\", (*c)->buf);\n+\tstrbuf_list_free(components);\n+\tif (check_refname_format(buf.buf, 0))\n+\t\tdie(_(\"bad git namespace path \\\"%s\\\"\"), raw_namespace);\n+\tstrbuf_addch(&buf, '/');\n+\n+\tnamespace = strbuf_detach(&buf, NULL);\n+\n+\treturn namespace;\n }\n \n const char *strip_namespace(const char *namespaced_ref)\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502695","messageId":"437b6f1f30d1e582e2e8a35f43d60a1fccb86740.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 11/21] environment: move `set_git_dir()` and related into setup layer","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:54Z","receivedAt":"2024-09-12T11:29:59Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The functions `set_git_dir()` and friends are used to set up\nrepositories. As such, they are quite clearly part of the setup\nsubsystem, but still live in \"environment.c\". Move them over, which also\nhelps to get rid of dependencies on `the_repository` in the environment\nsubsystem.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n environment.c | 105 -------------------------------------------------\n environment.h |   2 -\n setup.c       | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++\n setup.h       |   3 ++\n 4 files changed, 109 insertions(+), 107 deletions(-)\n\ndiff --git a/environment.c b/environment.c\nindex 49844418419..64ae13ef240 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -22,14 +22,9 @@\n #include \"fmt-merge-msg.h\"\n #include \"commit.h\"\n #include \"strvec.h\"\n-#include \"object-file.h\"\n #include \"path.h\"\n-#include \"replace-object.h\"\n-#include \"tmp-objdir.h\"\n #include \"chdir-notify.h\"\n #include \"setup.h\"\n-#include \"shallow.h\"\n-#include \"trace.h\"\n #include \"write-or-die.h\"\n \n int trust_executable_bit = 1;\n@@ -155,41 +150,6 @@ const char *getenv_safe(struct strvec *argv, const char *name)\n \treturn argv->v[argv->nr - 1];\n }\n \n-void setup_git_env(const char *git_dir)\n-{\n-\tchar *git_replace_ref_base;\n-\tconst char *shallow_file;\n-\tconst char *replace_ref_base;\n-\tstruct set_gitdir_args args = { NULL };\n-\tstruct strvec to_free = STRVEC_INIT;\n-\n-\targs.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);\n-\targs.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);\n-\targs.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);\n-\targs.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);\n-\targs.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);\n-\tif (getenv(GIT_QUARANTINE_ENVIRONMENT)) {\n-\t\targs.disable_ref_updates = 1;\n-\t}\n-\n-\trepo_set_gitdir(the_repository, git_dir, &args);\n-\tstrvec_clear(&to_free);\n-\n-\tif (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))\n-\t\tdisable_replace_refs();\n-\treplace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);\n-\tgit_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base\n-\t\t\t\t\t\t\t  : \"refs/replace/\");\n-\tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\n-\n-\tshallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);\n-\tif (shallow_file)\n-\t\tset_alternate_shallow_file(the_repository, shallow_file, 0);\n-\n-\tif (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))\n-\t\tfetch_if_missing = 0;\n-}\n-\n int is_bare_repository(void)\n {\n \t/* if core.bare is not 'false', let's see if there is a work tree */\n@@ -243,71 +203,6 @@ const char *strip_namespace(const char *namespaced_ref)\n \treturn NULL;\n }\n \n-static int git_work_tree_initialized;\n-\n-/*\n- * Note.  This works only before you used a work tree.  This was added\n- * primarily to support git-clone to work in a new repository it just\n- * created, and is not meant to flip between different work trees.\n- */\n-void set_git_work_tree(const char *new_work_tree)\n-{\n-\tif (git_work_tree_initialized) {\n-\t\tstruct strbuf realpath = STRBUF_INIT;\n-\n-\t\tstrbuf_realpath(&realpath, new_work_tree, 1);\n-\t\tnew_work_tree = realpath.buf;\n-\t\tif (strcmp(new_work_tree, the_repository->worktree))\n-\t\t\tdie(\"internal error: work tree has already been set\\n\"\n-\t\t\t    \"Current worktree: %s\\nNew worktree: %s\",\n-\t\t\t    the_repository->worktree, new_work_tree);\n-\t\tstrbuf_release(&realpath);\n-\t\treturn;\n-\t}\n-\tgit_work_tree_initialized = 1;\n-\trepo_set_worktree(the_repository, new_work_tree);\n-}\n-\n-static void set_git_dir_1(const char *path)\n-{\n-\txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\n-\tsetup_git_env(path);\n-}\n-\n-static void update_relative_gitdir(const char *name UNUSED,\n-\t\t\t\t   const char *old_cwd,\n-\t\t\t\t   const char *new_cwd,\n-\t\t\t\t   void *data UNUSED)\n-{\n-\tchar *path = reparent_relative_path(old_cwd, new_cwd,\n-\t\t\t\t\t    repo_get_git_dir(the_repository));\n-\tstruct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();\n-\n-\ttrace_printf_key(&trace_setup_key,\n-\t\t\t \"setup: move $GIT_DIR to '%s'\",\n-\t\t\t path);\n-\tset_git_dir_1(path);\n-\tif (tmp_objdir)\n-\t\ttmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);\n-\tfree(path);\n-}\n-\n-void set_git_dir(const char *path, int make_realpath)\n-{\n-\tstruct strbuf realpath = STRBUF_INIT;\n-\n-\tif (make_realpath) {\n-\t\tstrbuf_realpath(&realpath, path, 1);\n-\t\tpath = realpath.buf;\n-\t}\n-\n-\tset_git_dir_1(path);\n-\tif (!is_absolute_path(path))\n-\t\tchdir_notify_register(NULL, update_relative_gitdir, NULL);\n-\n-\tstrbuf_release(&realpath);\n-}\n-\n const char *get_log_output_encoding(void)\n {\n \treturn git_log_output_encoding ? git_log_output_encoding\ndiff --git a/environment.h b/environment.h\nindex 682d4f2e3b5..b8460396790 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -105,10 +105,8 @@ int have_git_dir(void);\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-void set_git_dir(const char *path, int make_realpath);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\n-void set_git_work_tree(const char *tree);\n \n #define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n \ndiff --git a/setup.c b/setup.c\nindex 1bfec288ab6..19cce5afa72 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -7,16 +7,22 @@\n #include \"exec-cmd.h\"\n #include \"gettext.h\"\n #include \"hex.h\"\n+#include \"object-file.h\"\n #include \"object-name.h\"\n #include \"refs.h\"\n+#include \"replace-object.h\"\n #include \"repository.h\"\n #include \"config.h\"\n #include \"dir.h\"\n #include \"setup.h\"\n+#include \"shallow.h\"\n #include \"string-list.h\"\n+#include \"strvec.h\"\n #include \"chdir-notify.h\"\n #include \"path.h\"\n #include \"quote.h\"\n+#include \"tmp-objdir.h\"\n+#include \"trace.h\"\n #include \"trace2.h\"\n #include \"worktree.h\"\n #include \"exec-cmd.h\"\n@@ -1613,6 +1619,106 @@ enum discovery_result discover_git_directory_reason(struct strbuf *commondir,\n \treturn result;\n }\n \n+void setup_git_env(const char *git_dir)\n+{\n+\tchar *git_replace_ref_base;\n+\tconst char *shallow_file;\n+\tconst char *replace_ref_base;\n+\tstruct set_gitdir_args args = { NULL };\n+\tstruct strvec to_free = STRVEC_INIT;\n+\n+\targs.commondir = getenv_safe(&to_free, GIT_COMMON_DIR_ENVIRONMENT);\n+\targs.object_dir = getenv_safe(&to_free, DB_ENVIRONMENT);\n+\targs.graft_file = getenv_safe(&to_free, GRAFT_ENVIRONMENT);\n+\targs.index_file = getenv_safe(&to_free, INDEX_ENVIRONMENT);\n+\targs.alternate_db = getenv_safe(&to_free, ALTERNATE_DB_ENVIRONMENT);\n+\tif (getenv(GIT_QUARANTINE_ENVIRONMENT)) {\n+\t\targs.disable_ref_updates = 1;\n+\t}\n+\n+\trepo_set_gitdir(the_repository, git_dir, &args);\n+\tstrvec_clear(&to_free);\n+\n+\tif (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))\n+\t\tdisable_replace_refs();\n+\treplace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);\n+\tgit_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base\n+\t\t\t\t\t\t\t  : \"refs/replace/\");\n+\tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\n+\n+\tshallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);\n+\tif (shallow_file)\n+\t\tset_alternate_shallow_file(the_repository, shallow_file, 0);\n+\n+\tif (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))\n+\t\tfetch_if_missing = 0;\n+}\n+\n+static void set_git_dir_1(const char *path)\n+{\n+\txsetenv(GIT_DIR_ENVIRONMENT, path, 1);\n+\tsetup_git_env(path);\n+}\n+\n+static void update_relative_gitdir(const char *name UNUSED,\n+\t\t\t\t   const char *old_cwd,\n+\t\t\t\t   const char *new_cwd,\n+\t\t\t\t   void *data UNUSED)\n+{\n+\tchar *path = reparent_relative_path(old_cwd, new_cwd,\n+\t\t\t\t\t    repo_get_git_dir(the_repository));\n+\tstruct tmp_objdir *tmp_objdir = tmp_objdir_unapply_primary_odb();\n+\n+\ttrace_printf_key(&trace_setup_key,\n+\t\t\t \"setup: move $GIT_DIR to '%s'\",\n+\t\t\t path);\n+\tset_git_dir_1(path);\n+\tif (tmp_objdir)\n+\t\ttmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);\n+\tfree(path);\n+}\n+\n+void set_git_dir(const char *path, int make_realpath)\n+{\n+\tstruct strbuf realpath = STRBUF_INIT;\n+\n+\tif (make_realpath) {\n+\t\tstrbuf_realpath(&realpath, path, 1);\n+\t\tpath = realpath.buf;\n+\t}\n+\n+\tset_git_dir_1(path);\n+\tif (!is_absolute_path(path))\n+\t\tchdir_notify_register(NULL, update_relative_gitdir, NULL);\n+\n+\tstrbuf_release(&realpath);\n+}\n+\n+static int git_work_tree_initialized;\n+\n+/*\n+ * Note.  This works only before you used a work tree.  This was added\n+ * primarily to support git-clone to work in a new repository it just\n+ * created, and is not meant to flip between different work trees.\n+ */\n+void set_git_work_tree(const char *new_work_tree)\n+{\n+\tif (git_work_tree_initialized) {\n+\t\tstruct strbuf realpath = STRBUF_INIT;\n+\n+\t\tstrbuf_realpath(&realpath, new_work_tree, 1);\n+\t\tnew_work_tree = realpath.buf;\n+\t\tif (strcmp(new_work_tree, the_repository->worktree))\n+\t\t\tdie(\"internal error: work tree has already been set\\n\"\n+\t\t\t    \"Current worktree: %s\\nNew worktree: %s\",\n+\t\t\t    the_repository->worktree, new_work_tree);\n+\t\tstrbuf_release(&realpath);\n+\t\treturn;\n+\t}\n+\tgit_work_tree_initialized = 1;\n+\trepo_set_worktree(the_repository, new_work_tree);\n+}\n+\n const char *setup_git_directory_gently(int *nongit_ok)\n {\n \tstatic struct strbuf cwd = STRBUF_INIT;\ndiff --git a/setup.h b/setup.h\nindex fd2df7cd525..e496ab3e4de 100644\n--- a/setup.h\n+++ b/setup.h\n@@ -94,6 +94,9 @@ static inline int discover_git_directory(struct strbuf *commondir,\n \treturn 0;\n }\n \n+void set_git_dir(const char *path, int make_realpath);\n+void set_git_work_tree(const char *tree);\n+\n const char *setup_git_directory_gently(int *);\n const char *setup_git_directory(void);\n char *prefix_path(const char *prefix, int len, const char *path);\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502696","messageId":"8de5b246dadd7de97ffebb22f6f018aeb7a74917.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 12/21] environment: reorder header to split out `the_repository`-free section","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:29:59Z","receivedAt":"2024-09-12T11:30:01Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Reorder the \"environment.h\" header such that declarations which are free\nfrom `the_repository` come before those which aren't. The new structure\nis now:\n\n    - Defines for environment variable names.\n\n    - Things which do not rely on a repository.\n\n    - Things which do, including those that implicitly rely on a parsed\n      repository. This includes for example variables which get\n      populated when reading repository config.\n\nThis will allow us to guard the last category of declarations with\n`USE_THE_REPOSITORY_VARIABLE`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n environment.h | 81 +++++++++++++++++++++++++--------------------------\n 1 file changed, 40 insertions(+), 41 deletions(-)\n\ndiff --git a/environment.h b/environment.h\nindex b8460396790..f1a7c645db5 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -1,22 +1,6 @@\n #ifndef ENVIRONMENT_H\n #define ENVIRONMENT_H\n \n-struct strvec;\n-\n-/*\n- * The character that begins a commented line in user-editable file\n- * that is subject to stripspace.\n- */\n-extern const char *comment_line_str;\n-extern char *comment_line_str_to_free;\n-extern int auto_comment_line_char;\n-\n-/*\n- * Wrapper of getenv() that returns a strdup value. This value is kept\n- * in argv to be freed later.\n- */\n-const char *getenv_safe(struct strvec *argv, const char *name);\n-\n /* Double-check local_repo_env below if you add to this list. */\n #define GIT_DIR_ENVIRONMENT \"GIT_DIR\"\n #define GIT_COMMON_DIR_ENVIRONMENT \"GIT_COMMON_DIR\"\n@@ -86,6 +70,8 @@ const char *getenv_safe(struct strvec *argv, const char *name);\n  */\n #define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT \"GIT_IMPLICIT_WORK_TREE\"\n \n+#define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n+\n /*\n  * Repository-local GIT_* environment variables; these will be cleared\n  * when git spawns a sub-process that runs inside another repository.\n@@ -94,6 +80,28 @@ const char *getenv_safe(struct strvec *argv, const char *name);\n  */\n extern const char * const local_repo_env[];\n \n+struct strvec;\n+\n+/*\n+ * Wrapper of getenv() that returns a strdup value. This value is kept\n+ * in argv to be freed later.\n+ */\n+const char *getenv_safe(struct strvec *argv, const char *name);\n+\n+/*\n+ * Should we print an ellipsis after an abbreviated SHA-1 value\n+ * when doing diff-raw output or indicating a detached HEAD?\n+ */\n+int print_sha1_ellipsis(void);\n+\n+/*\n+ * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value).\n+ */\n+int use_optional_locks(void);\n+\n+const char *get_git_namespace(void);\n+const char *strip_namespace(const char *namespaced_ref);\n+\n void setup_git_env(const char *git_dir);\n \n /*\n@@ -102,13 +110,19 @@ void setup_git_env(const char *git_dir);\n  */\n int have_git_dir(void);\n \n+/*\n+ * Accessors for the core.sharedrepository config which lazy-load the value\n+ * from the config (if not already set). The \"reset\" function can be\n+ * used to unset \"set\" or cached value, meaning that the value will be loaded\n+ * fresh from the config file on the next call to get_shared_repository().\n+ */\n+void set_shared_repository(int value);\n+int get_shared_repository(void);\n+void reset_shared_repository(void);\n+\n extern int is_bare_repository_cfg;\n int is_bare_repository(void);\n extern char *git_work_tree_cfg;\n-const char *get_git_namespace(void);\n-const char *strip_namespace(const char *namespaced_ref);\n-\n-#define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n \n /* Environment bits from configuration mechanism */\n extern int trust_executable_bit;\n@@ -134,16 +148,6 @@ extern unsigned long big_file_threshold;\n extern unsigned long pack_size_limit_cfg;\n extern int max_allowed_tree_depth;\n \n-/*\n- * Accessors for the core.sharedrepository config which lazy-load the value\n- * from the config (if not already set). The \"reset\" function can be\n- * used to unset \"set\" or cached value, meaning that the value will be loaded\n- * fresh from the config file on the next call to get_shared_repository().\n- */\n-void set_shared_repository(int value);\n-int get_shared_repository(void);\n-void reset_shared_repository(void);\n-\n extern int core_preload_index;\n extern int precomposed_unicode;\n extern int protect_hfs;\n@@ -153,11 +157,6 @@ extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n-/*\n- * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value).\n- */\n-int use_optional_locks(void);\n-\n enum log_refs_config {\n \tLOG_REFS_UNSET = -1,\n \tLOG_REFS_NONE = 0,\n@@ -172,6 +171,7 @@ enum rebase_setup_type {\n \tAUTOREBASE_REMOTE,\n \tAUTOREBASE_ALWAYS\n };\n+extern enum rebase_setup_type autorebase;\n \n enum push_default_type {\n \tPUSH_DEFAULT_NOTHING = 0,\n@@ -181,15 +181,12 @@ enum push_default_type {\n \tPUSH_DEFAULT_CURRENT,\n \tPUSH_DEFAULT_UNSPECIFIED\n };\n-\n-extern enum rebase_setup_type autorebase;\n extern enum push_default_type push_default;\n \n enum object_creation_mode {\n \tOBJECT_CREATION_USES_HARDLINKS = 0,\n \tOBJECT_CREATION_USES_RENAMES = 1\n };\n-\n extern enum object_creation_mode object_creation_mode;\n \n extern char *notes_ref_name;\n@@ -209,9 +206,11 @@ extern char *askpass_program;\n extern char *excludes_file;\n \n /*\n- * Should we print an ellipsis after an abbreviated SHA-1 value\n- * when doing diff-raw output or indicating a detached HEAD?\n+ * The character that begins a commented line in user-editable file\n+ * that is subject to stripspace.\n  */\n-int print_sha1_ellipsis(void);\n+extern const char *comment_line_str;\n+extern char *comment_line_str_to_free;\n+extern int auto_comment_line_char;\n \n #endif\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502697","messageId":"417cca950bff25c5947663532d5ed468079e6c72.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 13/21] environment: guard state depending on a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:30:01Z","receivedAt":"2024-09-12T11:30:04Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In \"environment.h\" we have quite a lot of functions and variables that\neither explicitly or implicitly depend on `the_repository`.\n\nThe implicit set of stateful declarations includes for example variables\nwhich get populated when parsing a repository's Git configuration. This\nset of variables is broken by design, as their state often depends on\nthe last repository config that has been parsed. So they may or may not\nrepresent the state of `the_repository`.\n\nFixing that is quite a big undertaking, and later patches in this series\nwill demonstrate a solution for a first small set of those variables. So\nfor now, let's guard these with `USE_THE_REPOSITORY_VARIABLE` so that\ncallers are aware of the implicit dependency.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n compat/mingw.c             |  2 ++\n compat/win32/path-utils.c  |  2 ++\n config.c                   |  2 ++\n environment.h              | 25 ++++++++++++++++++++++++-\n name-hash.c                |  3 +++\n path.c                     |  2 ++\n preload-index.c            |  3 +++\n prompt.c                   |  2 ++\n refs/files-backend.c       |  2 ++\n sparse-index.c             |  2 ++\n statinfo.c                 |  2 ++\n t/helper/test-path-utils.c |  2 ++\n tree-diff.c                |  3 +++\n userdiff.c                 |  2 ++\n 14 files changed, 53 insertions(+), 1 deletion(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 29d3f09768c..5c2080c04c1 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"../git-compat-util.h\"\n #include \"win32.h\"\n #include <aclapi.h>\ndiff --git a/compat/win32/path-utils.c b/compat/win32/path-utils.c\nindex b658ca3f811..966ef779b9c 100644\n--- a/compat/win32/path-utils.c\n+++ b/compat/win32/path-utils.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"../../git-compat-util.h\"\n #include \"../../environment.h\"\n \ndiff --git a/config.c b/config.c\nindex 043e1c8a078..f3066c37477 100644\n--- a/config.c\n+++ b/config.c\n@@ -6,6 +6,8 @@\n  *\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"advice.h\"\ndiff --git a/environment.h b/environment.h\nindex f1a7c645db5..934859e1c59 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -102,6 +102,28 @@ int use_optional_locks(void);\n const char *get_git_namespace(void);\n const char *strip_namespace(const char *namespaced_ref);\n \n+/*\n+ * TODO: All the below state either explicitly or implicitly relies on\n+ * `the_repository`. We should eventually get rid of these and make the\n+ * dependency on a repository explicit:\n+ *\n+ *   - `setup_git_env()` ideally shouldn't exist as it modifies global state,\n+ *     namely the environment. The current process shouldn't ever access that\n+ *     state via envvars though, but should instead consult a `struct\n+ *     repository`. When spawning new processes, we would ideally also pass a\n+ *     `struct repository` and then set up the environment variables for the\n+ *     child process, only.\n+ *\n+ *   - `have_git_dir()` should not have to exist at all. Instead, we should\n+ *     decide on whether or not we have a `struct repository`.\n+ *\n+ *   - All the global config variables should become tied to a repository. Like\n+ *     this, we'd correctly honor repository-local configuration and be able to\n+ *     distinguish configuration values from different repositories.\n+ *\n+ * Please do not add new global config variables here.\n+ */\n+# ifdef USE_THE_REPOSITORY_VARIABLE\n void setup_git_env(const char *git_dir);\n \n /*\n@@ -213,4 +235,5 @@ extern const char *comment_line_str;\n extern char *comment_line_str_to_free;\n extern int auto_comment_line_char;\n \n-#endif\n+# endif /* USE_THE_REPOSITORY_VARIABLE */\n+#endif /* ENVIRONMENT_H */\ndiff --git a/name-hash.c b/name-hash.c\nindex 3a58ce03d9c..95528e3bcd2 100644\n--- a/name-hash.c\n+++ b/name-hash.c\n@@ -5,6 +5,9 @@\n  *\n  * Copyright (C) 2008 Linus Torvalds\n  */\n+\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\ndiff --git a/path.c b/path.c\nindex a3bf25b7def..93491bab141 100644\n--- a/path.c\n+++ b/path.c\n@@ -2,6 +2,8 @@\n  * Utilities for paths and pathnames\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"environment.h\"\ndiff --git a/preload-index.c b/preload-index.c\nindex 63fd35d64b1..7926eb09a69 100644\n--- a/preload-index.c\n+++ b/preload-index.c\n@@ -1,6 +1,9 @@\n /*\n  * Copyright (C) 2008 Linus Torvalds\n  */\n+\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"pathspec.h\"\n #include \"dir.h\"\ndiff --git a/prompt.c b/prompt.c\nindex 8935fe4dfb9..f21c5bf1c7e 100644\n--- a/prompt.c\n+++ b/prompt.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"parse.h\"\n #include \"environment.h\"\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 1cff65f6ae5..1bbb550f3af 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"../git-compat-util.h\"\n #include \"../copy.h\"\n #include \"../environment.h\"\ndiff --git a/sparse-index.c b/sparse-index.c\nindex 9958656ded1..542ca5f411c 100644\n--- a/sparse-index.c\n+++ b/sparse-index.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"gettext.h\"\ndiff --git a/statinfo.c b/statinfo.c\nindex 3c6bc049c15..30a164b0e68 100644\n--- a/statinfo.c\n+++ b/statinfo.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"environment.h\"\n #include \"statinfo.h\"\ndiff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c\nindex bf0e23ed505..f57c8d706aa 100644\n--- a/t/helper/test-path-utils.c\n+++ b/t/helper/test-path-utils.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"test-tool.h\"\n #include \"abspath.h\"\n #include \"environment.h\"\ndiff --git a/tree-diff.c b/tree-diff.c\nindex 9252481df36..5eab8af631b 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -1,6 +1,9 @@\n /*\n  * Helper functions for tree diff generation\n  */\n+\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"diff.h\"\n #include \"diffcore.h\"\ndiff --git a/userdiff.c b/userdiff.c\nindex 989629149f6..d43d8360d17 100644\n--- a/userdiff.c\n+++ b/userdiff.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"config.h\"\n #include \"userdiff.h\"\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502698","messageId":"a9d032b3ec7cb4cc99198c66ac8d003fea3f6883.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 14/21] repo-settings: split out declarations into a standalone header","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:30:04Z","receivedAt":"2024-09-12T11:30:06Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"While we have \"repo-settings.c\", we do not have a corresponding\n\"repo-settings.h\" file. Instead, this functionality is part of the\n\"repository.h\" header, making it hard to discover.\n\nSplit the declarations out of \"repository.h\" and create a standalone\nheader file with them.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n repo-settings.c |  1 +\n repo-settings.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++\n repository.h    | 51 +-------------------------------------------\n 3 files changed, 58 insertions(+), 50 deletions(-)\n create mode 100644 repo-settings.h\n\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 2b4e68731be..6165546e80a 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -1,5 +1,6 @@\n #include \"git-compat-util.h\"\n #include \"config.h\"\n+#include \"repo-settings.h\"\n #include \"repository.h\"\n #include \"midx.h\"\n \ndiff --git a/repo-settings.h b/repo-settings.h\nnew file mode 100644\nindex 00000000000..ff20a965373\n--- /dev/null\n+++ b/repo-settings.h\n@@ -0,0 +1,56 @@\n+#ifndef REPO_SETTINGS_H\n+#define REPO_SETTINGS_H\n+\n+struct fsmonitor_settings;\n+struct repository;\n+\n+enum untracked_cache_setting {\n+\tUNTRACKED_CACHE_KEEP,\n+\tUNTRACKED_CACHE_REMOVE,\n+\tUNTRACKED_CACHE_WRITE,\n+};\n+\n+enum fetch_negotiation_setting {\n+\tFETCH_NEGOTIATION_CONSECUTIVE,\n+\tFETCH_NEGOTIATION_SKIPPING,\n+\tFETCH_NEGOTIATION_NOOP,\n+};\n+\n+struct repo_settings {\n+\tint initialized;\n+\n+\tint core_commit_graph;\n+\tint commit_graph_generation_version;\n+\tint commit_graph_changed_paths_version;\n+\tint gc_write_commit_graph;\n+\tint fetch_write_commit_graph;\n+\tint command_requires_full_index;\n+\tint sparse_index;\n+\tint pack_read_reverse_index;\n+\tint pack_use_bitmap_boundary_traversal;\n+\tint pack_use_multi_pack_reuse;\n+\n+\t/*\n+\t * Does this repository have core.useReplaceRefs=true (on by\n+\t * default)? This provides a repository-scoped version of this\n+\t * config, though it could be disabled process-wide via some Git\n+\t * builtins or the --no-replace-objects option. See\n+\t * replace_refs_enabled() for more details.\n+\t */\n+\tint read_replace_refs;\n+\n+\tstruct fsmonitor_settings *fsmonitor; /* lazily loaded */\n+\n+\tint index_version;\n+\tint index_skip_hash;\n+\tenum untracked_cache_setting core_untracked_cache;\n+\n+\tint pack_use_sparse;\n+\tenum fetch_negotiation_setting fetch_negotiation_algorithm;\n+\n+\tint core_multi_pack_index;\n+};\n+\n+void prepare_repo_settings(struct repository *r);\n+\n+#endif /* REPO_SETTINGS_H */\ndiff --git a/repository.h b/repository.h\nindex c603e969ae7..24a66a496a6 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -2,9 +2,9 @@\n #define REPOSITORY_H\n \n #include \"strmap.h\"\n+#include \"repo-settings.h\"\n \n struct config_set;\n-struct fsmonitor_settings;\n struct git_hash_algo;\n struct index_state;\n struct lock_file;\n@@ -14,59 +14,12 @@ struct submodule_cache;\n struct promisor_remote_config;\n struct remote_state;\n \n-enum untracked_cache_setting {\n-\tUNTRACKED_CACHE_KEEP,\n-\tUNTRACKED_CACHE_REMOVE,\n-\tUNTRACKED_CACHE_WRITE,\n-};\n-\n-enum fetch_negotiation_setting {\n-\tFETCH_NEGOTIATION_CONSECUTIVE,\n-\tFETCH_NEGOTIATION_SKIPPING,\n-\tFETCH_NEGOTIATION_NOOP,\n-};\n-\n enum ref_storage_format {\n \tREF_STORAGE_FORMAT_UNKNOWN,\n \tREF_STORAGE_FORMAT_FILES,\n \tREF_STORAGE_FORMAT_REFTABLE,\n };\n \n-struct repo_settings {\n-\tint initialized;\n-\n-\tint core_commit_graph;\n-\tint commit_graph_generation_version;\n-\tint commit_graph_changed_paths_version;\n-\tint gc_write_commit_graph;\n-\tint fetch_write_commit_graph;\n-\tint command_requires_full_index;\n-\tint sparse_index;\n-\tint pack_read_reverse_index;\n-\tint pack_use_bitmap_boundary_traversal;\n-\tint pack_use_multi_pack_reuse;\n-\n-\t/*\n-\t * Does this repository have core.useReplaceRefs=true (on by\n-\t * default)? This provides a repository-scoped version of this\n-\t * config, though it could be disabled process-wide via some Git\n-\t * builtins or the --no-replace-objects option. See\n-\t * replace_refs_enabled() for more details.\n-\t */\n-\tint read_replace_refs;\n-\n-\tstruct fsmonitor_settings *fsmonitor; /* lazily loaded */\n-\n-\tint index_version;\n-\tint index_skip_hash;\n-\tenum untracked_cache_setting core_untracked_cache;\n-\n-\tint pack_use_sparse;\n-\tenum fetch_negotiation_setting fetch_negotiation_algorithm;\n-\n-\tint core_multi_pack_index;\n-};\n-\n struct repo_path_cache {\n \tchar *squash_msg;\n \tchar *merge_msg;\n@@ -273,8 +226,6 @@ int repo_read_index_unmerged(struct repository *);\n  */\n void repo_update_index_if_able(struct repository *, struct lock_file *);\n \n-void prepare_repo_settings(struct repository *r);\n-\n /*\n  * Return 1 if upgrade repository format to target_version succeeded,\n  * 0 if no upgrade is necessary, and -1 when upgrade is not possible.\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502699","messageId":"7a74c8d8a8d640c2f0784984da93813c34fe3982.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 15/21] repo-settings: track defaults close to `struct repo_settings`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:30:07Z","receivedAt":"2024-09-12T11:30:10Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The default values for `struct repo_settings` are set up in\n`prepare_repo_settings()`. This is somewhat different from how we\ntypically do this, namely by providing an `INIT` macro that sets up the\ndefault values for us.\n\nRefactor the code to do the same.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n repo-settings.c | 9 ++++-----\n repo-settings.h | 5 +++++\n 2 files changed, 9 insertions(+), 5 deletions(-)\n\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 6165546e80a..3a76ba276c9 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -20,6 +20,7 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest,\n \n void prepare_repo_settings(struct repository *r)\n {\n+\tconst struct repo_settings defaults = REPO_SETTINGS_INIT;\n \tint experimental;\n \tint value;\n \tconst char *strval;\n@@ -29,13 +30,11 @@ void prepare_repo_settings(struct repository *r)\n \tif (!r->gitdir)\n \t\tBUG(\"Cannot add settings for uninitialized repository\");\n \n-\tif (r->settings.initialized++)\n+\tif (r->settings.initialized)\n \t\treturn;\n \n-\t/* Defaults */\n-\tr->settings.index_version = -1;\n-\tr->settings.core_untracked_cache = UNTRACKED_CACHE_KEEP;\n-\tr->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE;\n+\tmemcpy(&r->settings, &defaults, sizeof(defaults));\n+\tr->settings.initialized++;\n \n \t/* Booleans config or default, cascades to other settings */\n \trepo_cfg_bool(r, \"feature.manyfiles\", &manyfiles, 0);\ndiff --git a/repo-settings.h b/repo-settings.h\nindex ff20a965373..28f95695b3a 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -50,6 +50,11 @@ struct repo_settings {\n \n \tint core_multi_pack_index;\n };\n+#define REPO_SETTINGS_INIT { \\\n+\t.index_version = -1, \\\n+\t.core_untracked_cache = UNTRACKED_CACHE_KEEP, \\\n+\t.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \\\n+}\n \n void prepare_repo_settings(struct repository *r);\n \n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502700","messageId":"b5f3bf5cd25817fdba8f47a415462af6c07fc2b9.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 16/21] branch: stop modifying `log_all_ref_updates` variable","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:30:10Z","receivedAt":"2024-09-12T11:30:12Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In \"branch.c\" we modify the global `log_all_ref_updates` variable to\nforce creation of a reflog entry. Modifying global state like this is\ndiscouraged, as it may have all kinds of consequences in other places of\nour codebase.\n\nStop modifying the variable and pass the `REF_FORCE_CREATE_REFLOG` flag\ninstead. Setting this flag has a stronger meaning than setting the\nconfig to `LOG_REFS_NORMAL`:\n\n  - `LOG_REFS_NORMAL` will ask us to only create reflog entries for\n    preexisting reflogs or branches, remote refs, note refs and HEAD.\n\n  - `REF_FORCE_CREATE_REFLOG` will unconditionally create a reflog and\n    is thus equivalent to `LOG_REFS_ALWAYS`.\n\nBut as we are in `create_branch()` and thus do not have to worry about\narbitrary references, but only about branches, `LOG_REFS_NORMAL` and\n`LOG_REFS_ALWAYS` are indeed equivalent.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n branch.c | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/branch.c b/branch.c\nindex c887ea21514..08fa4094d2b 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -601,6 +601,7 @@ void create_branch(struct repository *r,\n \tint forcing = 0;\n \tstruct ref_transaction *transaction;\n \tstruct strbuf err = STRBUF_INIT;\n+\tint flags = 0;\n \tchar *msg;\n \n \tif (track == BRANCH_TRACK_OVERRIDE)\n@@ -619,7 +620,7 @@ void create_branch(struct repository *r,\n \t\tgoto cleanup;\n \n \tif (reflog)\n-\t\tlog_all_ref_updates = LOG_REFS_NORMAL;\n+\t\tflags |= REF_FORCE_CREATE_REFLOG;\n \n \tif (forcing)\n \t\tmsg = xstrfmt(\"branch: Reset to %s\", start_name);\n@@ -630,7 +631,7 @@ void create_branch(struct repository *r,\n \tif (!transaction ||\n \t\tref_transaction_update(transaction, ref.buf,\n \t\t\t\t\t&oid, forcing ? NULL : null_oid(),\n-\t\t\t\t\tNULL, NULL, 0, msg, &err) ||\n+\t\t\t\t\tNULL, NULL, flags, msg, &err) ||\n \t\tref_transaction_commit(transaction, &err))\n \t\tdie(\"%s\", err.buf);\n \tref_transaction_free(transaction);\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502701","messageId":"128fefd33a86e9b3d80203e891dc383643d6dec0.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 17/21] refs: stop modifying global `log_all_ref_updates` variable","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:30:13Z","receivedAt":"2024-09-12T11:30:18Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In refs-related code we modify the global `log_all_ref_updates`\nvariable, which is done because `should_autocreate_reflog()` does not\naccept passing an `enum log_refs_config` but instead accesses the global\nvariable. Adapt its interface such that the value is provided by the\ncaller, which allows us to compute the proper value locally without\nhaving to modify global state.\n\nThis change requires us to move the enum to \"repo-settings.h\", or\notherwise we get compilation errors due to include cycles. We're about\nto fully move this setting into the repo-settings subsystem anyway, so\nthis is fine.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/checkout.c      |  3 ++-\n environment.h           |  8 ++------\n refs.c                  |  5 +++--\n refs.h                  |  4 +++-\n refs/files-backend.c    | 23 ++++++++++++-----------\n refs/reftable-backend.c | 12 +++++++-----\n repo-settings.h         |  7 +++++++\n 7 files changed, 36 insertions(+), 26 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 4cfe6fab505..6db7f39492e 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -23,6 +23,7 @@\n #include \"read-cache.h\"\n #include \"refs.h\"\n #include \"remote.h\"\n+#include \"repo-settings.h\"\n #include \"resolve-undo.h\"\n #include \"revision.h\"\n #include \"setup.h\"\n@@ -954,7 +955,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,\n \n \t\t\trefname = mkpathdup(\"refs/heads/%s\", opts->new_orphan_branch);\n \t\t\tif (opts->new_branch_log &&\n-\t\t\t    !should_autocreate_reflog(refname)) {\n+\t\t\t    !should_autocreate_reflog(log_all_ref_updates, refname)) {\n \t\t\t\tint ret;\n \t\t\t\tstruct strbuf err = STRBUF_INIT;\n \ndiff --git a/environment.h b/environment.h\nindex 934859e1c59..0b4e5afc36d 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -1,6 +1,8 @@\n #ifndef ENVIRONMENT_H\n #define ENVIRONMENT_H\n \n+#include \"repo-settings.h\"\n+\n /* Double-check local_repo_env below if you add to this list. */\n #define GIT_DIR_ENVIRONMENT \"GIT_DIR\"\n #define GIT_COMMON_DIR_ENVIRONMENT \"GIT_COMMON_DIR\"\n@@ -179,12 +181,6 @@ extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n-enum log_refs_config {\n-\tLOG_REFS_UNSET = -1,\n-\tLOG_REFS_NONE = 0,\n-\tLOG_REFS_NORMAL,\n-\tLOG_REFS_ALWAYS\n-};\n extern enum log_refs_config log_all_ref_updates;\n \n enum rebase_setup_type {\ndiff --git a/refs.c b/refs.c\nindex ceb72d4bd74..d7402bcd196 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -24,7 +24,7 @@\n #include \"submodule.h\"\n #include \"worktree.h\"\n #include \"strvec.h\"\n-#include \"repository.h\"\n+#include \"repo-settings.h\"\n #include \"setup.h\"\n #include \"sigchain.h\"\n #include \"date.h\"\n@@ -958,7 +958,8 @@ static char *normalize_reflog_message(const char *msg)\n \treturn strbuf_detach(&sb, NULL);\n }\n \n-int should_autocreate_reflog(const char *refname)\n+int should_autocreate_reflog(enum log_refs_config log_all_ref_updates,\n+\t\t\t     const char *refname)\n {\n \tswitch (log_all_ref_updates) {\n \tcase LOG_REFS_ALWAYS:\ndiff --git a/refs.h b/refs.h\nindex f8b919a1388..f2c4ccde611 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -3,6 +3,7 @@\n \n #include \"commit.h\"\n #include \"repository.h\"\n+#include \"repo-settings.h\"\n \n struct fsck_options;\n struct object_id;\n@@ -111,7 +112,8 @@ int refs_verify_refname_available(struct ref_store *refs,\n \n int refs_ref_exists(struct ref_store *refs, const char *refname);\n \n-int should_autocreate_reflog(const char *refname);\n+int should_autocreate_reflog(enum log_refs_config log_all_ref_updates,\n+\t\t\t     const char *refname);\n \n int is_branch(const char *refname);\n \ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 1bbb550f3af..f5871abcf75 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -8,6 +8,7 @@\n #include \"../hex.h\"\n #include \"../fsck.h\"\n #include \"../refs.h\"\n+#include \"../repo-settings.h\"\n #include \"refs-internal.h\"\n #include \"ref-cache.h\"\n #include \"packed-backend.h\"\n@@ -1443,6 +1444,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs,\n static int commit_ref_update(struct files_ref_store *refs,\n \t\t\t     struct ref_lock *lock,\n \t\t\t     const struct object_id *oid, const char *logmsg,\n+\t\t\t     int flags,\n \t\t\t     struct strbuf *err);\n \n /*\n@@ -1586,7 +1588,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,\n \toidcpy(&lock->old_oid, &orig_oid);\n \n \tif (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) ||\n-\t    commit_ref_update(refs, lock, &orig_oid, logmsg, &err)) {\n+\t    commit_ref_update(refs, lock, &orig_oid, logmsg, 0, &err)) {\n \t\terror(\"unable to write current sha1 into %s: %s\", newrefname, err.buf);\n \t\tstrbuf_release(&err);\n \t\tgoto rollback;\n@@ -1603,14 +1605,11 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,\n \t\tgoto rollbacklog;\n \t}\n \n-\tflag = log_all_ref_updates;\n-\tlog_all_ref_updates = LOG_REFS_NONE;\n \tif (write_ref_to_lockfile(refs, lock, &orig_oid, 0, &err) ||\n-\t    commit_ref_update(refs, lock, &orig_oid, NULL, &err)) {\n+\t    commit_ref_update(refs, lock, &orig_oid, NULL, REF_SKIP_CREATE_REFLOG, &err)) {\n \t\terror(\"unable to write current sha1 into %s: %s\", oldrefname, err.buf);\n \t\tstrbuf_release(&err);\n \t}\n-\tlog_all_ref_updates = flag;\n \n  rollbacklog:\n \tif (logmoved && rename(sb_newref.buf, sb_oldref.buf))\n@@ -1705,13 +1704,17 @@ static int log_ref_setup(struct files_ref_store *refs,\n \t\t\t const char *refname, int force_create,\n \t\t\t int *logfd, struct strbuf *err)\n {\n+\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n \tstruct strbuf logfile_sb = STRBUF_INIT;\n \tchar *logfile;\n \n+\tif (log_refs_cfg == LOG_REFS_UNSET)\n+\t\tlog_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n+\n \tfiles_reflog_path(refs, &logfile_sb, refname);\n \tlogfile = strbuf_detach(&logfile_sb, NULL);\n \n-\tif (force_create || should_autocreate_reflog(refname)) {\n+\tif (force_create || should_autocreate_reflog(log_refs_cfg, refname)) {\n \t\tif (raceproof_create_file(logfile, open_or_create_logfile, logfd)) {\n \t\t\tif (errno == ENOENT)\n \t\t\t\tstrbuf_addf(err, \"unable to create directory for '%s': \"\n@@ -1800,9 +1803,6 @@ static int files_log_ref_write(struct files_ref_store *refs,\n \tif (flags & REF_SKIP_CREATE_REFLOG)\n \t\treturn 0;\n \n-\tif (log_all_ref_updates == LOG_REFS_UNSET)\n-\t\tlog_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n-\n \tresult = log_ref_setup(refs, refname,\n \t\t\t       flags & REF_FORCE_CREATE_REFLOG,\n \t\t\t       &logfd, err);\n@@ -1891,6 +1891,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs,\n static int commit_ref_update(struct files_ref_store *refs,\n \t\t\t     struct ref_lock *lock,\n \t\t\t     const struct object_id *oid, const char *logmsg,\n+\t\t\t     int flags,\n \t\t\t     struct strbuf *err)\n {\n \tfiles_assert_main_repository(refs, \"commit_ref_update\");\n@@ -1898,7 +1899,7 @@ static int commit_ref_update(struct files_ref_store *refs,\n \tclear_loose_ref_cache(refs);\n \tif (files_log_ref_write(refs, lock->ref_name,\n \t\t\t\t&lock->old_oid, oid,\n-\t\t\t\tlogmsg, 0, err)) {\n+\t\t\t\tlogmsg, flags, err)) {\n \t\tchar *old_msg = strbuf_detach(err, NULL);\n \t\tstrbuf_addf(err, \"cannot update the ref '%s': %s\",\n \t\t\t    lock->ref_name, old_msg);\n@@ -1931,7 +1932,7 @@ static int commit_ref_update(struct files_ref_store *refs,\n \t\t\tstruct strbuf log_err = STRBUF_INIT;\n \t\t\tif (files_log_ref_write(refs, \"HEAD\",\n \t\t\t\t\t\t&lock->old_oid, oid,\n-\t\t\t\t\t\tlogmsg, 0, &log_err)) {\n+\t\t\t\t\t\tlogmsg, flags, &log_err)) {\n \t\t\t\terror(\"%s\", log_err.buf);\n \t\t\t\tstrbuf_release(&log_err);\n \t\t\t}\ndiff --git a/refs/reftable-backend.c b/refs/reftable-backend.c\nindex 1c4b19e737f..c78186423a1 100644\n--- a/refs/reftable-backend.c\n+++ b/refs/reftable-backend.c\n@@ -19,6 +19,7 @@\n #include \"../reftable/reftable-record.h\"\n #include \"../reftable/reftable-error.h\"\n #include \"../reftable/reftable-iterator.h\"\n+#include \"../repo-settings.h\"\n #include \"../setup.h\"\n #include \"../strmap.h\"\n #include \"parse.h\"\n@@ -158,20 +159,21 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store,\n \n static int should_write_log(struct ref_store *refs, const char *refname)\n {\n-\tif (log_all_ref_updates == LOG_REFS_UNSET)\n-\t\tlog_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n+\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n+\tif (log_refs_cfg == LOG_REFS_UNSET)\n+\t\tlog_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n \n-\tswitch (log_all_ref_updates) {\n+\tswitch (log_refs_cfg) {\n \tcase LOG_REFS_NONE:\n \t\treturn refs_reflog_exists(refs, refname);\n \tcase LOG_REFS_ALWAYS:\n \t\treturn 1;\n \tcase LOG_REFS_NORMAL:\n-\t\tif (should_autocreate_reflog(refname))\n+\t\tif (should_autocreate_reflog(log_refs_cfg, refname))\n \t\t\treturn 1;\n \t\treturn refs_reflog_exists(refs, refname);\n \tdefault:\n-\t\tBUG(\"unhandled core.logAllRefUpdates value %d\", log_all_ref_updates);\n+\t\tBUG(\"unhandled core.logAllRefUpdates value %d\", log_refs_cfg);\n \t}\n }\n \ndiff --git a/repo-settings.h b/repo-settings.h\nindex 28f95695b3a..d03b6e57f0c 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -16,6 +16,13 @@ enum fetch_negotiation_setting {\n \tFETCH_NEGOTIATION_NOOP,\n };\n \n+enum log_refs_config {\n+\tLOG_REFS_UNSET = -1,\n+\tLOG_REFS_NONE = 0,\n+\tLOG_REFS_NORMAL,\n+\tLOG_REFS_ALWAYS\n+};\n+\n struct repo_settings {\n \tint initialized;\n \n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502702","messageId":"df0f29cfec0e359e41296148e1990a013e9f9222.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 18/21] environment: stop storing \"core.logAllRefUpdates\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:30:18Z","receivedAt":"2024-09-12T11:30:20Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The value of \"core.logAllRefUpdates\" is being stored in the global\nvariable `log_all_ref_updates`. This design is somewhat aged nowadays,\nwhere it is entirely possible to access multiple repositories in the\nsame process which all have different values for this setting. So using\na single global variable to track it is plain wrong.\n\nRemove the global variable. Instead, we now provide a new function part\nof the repo-settings subsystem that parses the value for a specific\nrepository. While that may require us to read the value multiple times,\nwe work around this by reading it once when the ref backends are set up\nand caching the value there.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/checkout.c      |  2 ++\n config.c                | 10 ----------\n environment.c           |  1 -\n environment.h           |  2 --\n refs/files-backend.c    |  4 +++-\n refs/reftable-backend.c | 12 +++++++-----\n repo-settings.c         | 16 ++++++++++++++++\n repo-settings.h         |  3 +++\n setup.c                 |  2 +-\n 9 files changed, 32 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 6db7f39492e..7e18b87c7a4 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -951,6 +951,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts,\n \tconst char *old_desc, *reflog_msg;\n \tif (opts->new_branch) {\n \t\tif (opts->new_orphan_branch) {\n+\t\t\tenum log_refs_config log_all_ref_updates =\n+\t\t\t\trepo_settings_get_log_all_ref_updates(the_repository);\n \t\t\tchar *refname;\n \n \t\t\trefname = mkpathdup(\"refs/heads/%s\", opts->new_orphan_branch);\ndiff --git a/config.c b/config.c\nindex f3066c37477..47101c3e977 100644\n--- a/config.c\n+++ b/config.c\n@@ -1452,16 +1452,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.logallrefupdates\")) {\n-\t\tif (value && !strcasecmp(value, \"always\"))\n-\t\t\tlog_all_ref_updates = LOG_REFS_ALWAYS;\n-\t\telse if (git_config_bool(var, value))\n-\t\t\tlog_all_ref_updates = LOG_REFS_NORMAL;\n-\t\telse\n-\t\t\tlog_all_ref_updates = LOG_REFS_NONE;\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.warnambiguousrefs\")) {\n \t\twarn_ambiguous_refs = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 64ae13ef240..992d87e0d60 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -77,7 +77,6 @@ int sparse_expect_files_outside_of_patterns;\n int merge_log_config = -1;\n int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */\n unsigned long pack_size_limit_cfg;\n-enum log_refs_config log_all_ref_updates = LOG_REFS_UNSET;\n int max_allowed_tree_depth =\n #ifdef _MSC_VER\n \t/*\ndiff --git a/environment.h b/environment.h\nindex 0b4e5afc36d..315fd319951 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -181,8 +181,6 @@ extern int core_apply_sparse_checkout;\n extern int core_sparse_checkout_cone;\n extern int sparse_expect_files_outside_of_patterns;\n \n-extern enum log_refs_config log_all_ref_updates;\n-\n enum rebase_setup_type {\n \tAUTOREBASE_NEVER = 0,\n \tAUTOREBASE_LOCAL,\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex f5871abcf75..a536d7d1b57 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -75,6 +75,7 @@ struct files_ref_store {\n \tunsigned int store_flags;\n \n \tchar *gitcommondir;\n+\tenum log_refs_config log_all_ref_updates;\n \n \tstruct ref_cache *loose;\n \n@@ -107,6 +108,7 @@ static struct ref_store *files_ref_store_init(struct repository *repo,\n \trefs->gitcommondir = strbuf_detach(&sb, NULL);\n \trefs->packed_ref_store =\n \t\tpacked_ref_store_init(repo, refs->gitcommondir, flags);\n+\trefs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);\n \n \tchdir_notify_reparent(\"files-backend $GIT_DIR\", &refs->base.gitdir);\n \tchdir_notify_reparent(\"files-backend $GIT_COMMONDIR\",\n@@ -1704,7 +1706,7 @@ static int log_ref_setup(struct files_ref_store *refs,\n \t\t\t const char *refname, int force_create,\n \t\t\t int *logfd, struct strbuf *err)\n {\n-\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n+\tenum log_refs_config log_refs_cfg = refs->log_all_ref_updates;\n \tstruct strbuf logfile_sb = STRBUF_INIT;\n \tchar *logfile;\n \ndiff --git a/refs/reftable-backend.c b/refs/reftable-backend.c\nindex c78186423a1..043e19439f6 100644\n--- a/refs/reftable-backend.c\n+++ b/refs/reftable-backend.c\n@@ -52,6 +52,7 @@ struct reftable_ref_store {\n \tstruct reftable_write_options write_options;\n \n \tunsigned int store_flags;\n+\tenum log_refs_config log_all_ref_updates;\n \tint err;\n };\n \n@@ -157,21 +158,21 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store,\n \t}\n }\n \n-static int should_write_log(struct ref_store *refs, const char *refname)\n+static int should_write_log(struct reftable_ref_store *refs, const char *refname)\n {\n-\tenum log_refs_config log_refs_cfg = log_all_ref_updates;\n+\tenum log_refs_config log_refs_cfg = refs->log_all_ref_updates;\n \tif (log_refs_cfg == LOG_REFS_UNSET)\n \t\tlog_refs_cfg = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;\n \n \tswitch (log_refs_cfg) {\n \tcase LOG_REFS_NONE:\n-\t\treturn refs_reflog_exists(refs, refname);\n+\t\treturn refs_reflog_exists(&refs->base, refname);\n \tcase LOG_REFS_ALWAYS:\n \t\treturn 1;\n \tcase LOG_REFS_NORMAL:\n \t\tif (should_autocreate_reflog(log_refs_cfg, refname))\n \t\t\treturn 1;\n-\t\treturn refs_reflog_exists(refs, refname);\n+\t\treturn refs_reflog_exists(&refs->base, refname);\n \tdefault:\n \t\tBUG(\"unhandled core.logAllRefUpdates value %d\", log_refs_cfg);\n \t}\n@@ -278,6 +279,7 @@ static struct ref_store *reftable_be_init(struct repository *repo,\n \tbase_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable);\n \tstrmap_init(&refs->worktree_stacks);\n \trefs->store_flags = store_flags;\n+\trefs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);\n \n \trefs->write_options.hash_id = repo->hash_algo->format_id;\n \trefs->write_options.default_permissions = calc_shared_perm(0666 & ~mask);\n@@ -1220,7 +1222,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data\n \t\t} else if (!(u->flags & REF_SKIP_CREATE_REFLOG) &&\n \t\t\t   (u->flags & REF_HAVE_NEW) &&\n \t\t\t   (u->flags & REF_FORCE_CREATE_REFLOG ||\n-\t\t\t    should_write_log(&arg->refs->base, u->refname))) {\n+\t\t\t    should_write_log(arg->refs, u->refname))) {\n \t\t\tstruct reftable_log_record *log;\n \t\t\tint create_reflog = 1;\n \ndiff --git a/repo-settings.c b/repo-settings.c\nindex 3a76ba276c9..1322fd2f972 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -124,3 +124,19 @@ void prepare_repo_settings(struct repository *r)\n \t */\n \tr->settings.command_requires_full_index = 1;\n }\n+\n+enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)\n+{\n+\tconst char *value;\n+\n+\tif (!repo_config_get_string_tmp(repo, \"core.logallrefupdates\", &value)) {\n+\t\tif (value && !strcasecmp(value, \"always\"))\n+\t\t\treturn LOG_REFS_ALWAYS;\n+\t\telse if (git_config_bool(\"core.logallrefupdates\", value))\n+\t\t\treturn LOG_REFS_NORMAL;\n+\t\telse\n+\t\t\treturn LOG_REFS_NONE;\n+\t}\n+\n+\treturn LOG_REFS_UNSET;\n+}\ndiff --git a/repo-settings.h b/repo-settings.h\nindex d03b6e57f0c..76adb96a669 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -65,4 +65,7 @@ struct repo_settings {\n \n void prepare_repo_settings(struct repository *r);\n \n+/* Read the value for \"core.logAllRefUpdates\". */\n+enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo);\n+\n #endif /* REPO_SETTINGS_H */\ndiff --git a/setup.c b/setup.c\nindex 19cce5afa72..74991914726 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2354,7 +2354,7 @@ static int create_default_files(const char *template_path,\n \telse {\n \t\tgit_config_set(\"core.bare\", \"false\");\n \t\t/* allow template config file to override the default */\n-\t\tif (log_all_ref_updates == LOG_REFS_UNSET)\n+\t\tif (repo_settings_get_log_all_ref_updates(the_repository) == LOG_REFS_UNSET)\n \t\t\tgit_config_set(\"core.logallrefupdates\", \"true\");\n \t\tif (needs_work_tree_config(original_git_dir, work_tree))\n \t\t\tgit_config_set(\"core.worktree\", work_tree);\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502703","messageId":"e3527e7d73f33b15c056abdfb6140c42f41560eb.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 19/21] environment: stop storing \"core.preferSymlinkRefs\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:30:21Z","receivedAt":"2024-09-12T11:30:23Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Same as the preceding commit, storing the \"core.preferSymlinkRefs\" value\nglobally is misdesigned as this setting may be set per repository.\n\nThere is only a single user of this value anyway, namely the \"files\"\nbackend. So let's just remove the global variable and read the value of\nthis setting when initializing the backend.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c             | 5 -----\n environment.c        | 1 -\n environment.h        | 1 -\n refs/files-backend.c | 5 ++++-\n 4 files changed, 4 insertions(+), 8 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 47101c3e977..a59890180a3 100644\n--- a/config.c\n+++ b/config.c\n@@ -1447,11 +1447,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.prefersymlinkrefs\")) {\n-\t\tprefer_symlink_refs = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.warnambiguousrefs\")) {\n \t\twarn_ambiguous_refs = git_config_bool(var, value);\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 992d87e0d60..6805c7b01df 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -34,7 +34,6 @@ int has_symlinks = 1;\n int minimum_abbrev = 4, default_abbrev = -1;\n int ignore_case;\n int assume_unchanged;\n-int prefer_symlink_refs;\n int is_bare_repository_cfg = -1; /* unspecified */\n int warn_ambiguous_refs = 1;\n int warn_on_object_refname_ambiguity = 1;\ndiff --git a/environment.h b/environment.h\nindex 315fd319951..0cab644e2d3 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -156,7 +156,6 @@ extern int has_symlinks;\n extern int minimum_abbrev, default_abbrev;\n extern int ignore_case;\n extern int assume_unchanged;\n-extern int prefer_symlink_refs;\n extern int warn_ambiguous_refs;\n extern int warn_on_object_refname_ambiguity;\n extern char *apply_default_whitespace;\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex a536d7d1b57..e5b0aff00dc 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1,6 +1,7 @@\n #define USE_THE_REPOSITORY_VARIABLE\n \n #include \"../git-compat-util.h\"\n+#include \"../config.h\"\n #include \"../copy.h\"\n #include \"../environment.h\"\n #include \"../gettext.h\"\n@@ -76,6 +77,7 @@ struct files_ref_store {\n \n \tchar *gitcommondir;\n \tenum log_refs_config log_all_ref_updates;\n+\tint prefer_symlink_refs;\n \n \tstruct ref_cache *loose;\n \n@@ -109,6 +111,7 @@ static struct ref_store *files_ref_store_init(struct repository *repo,\n \trefs->packed_ref_store =\n \t\tpacked_ref_store_init(repo, refs->gitcommondir, flags);\n \trefs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);\n+\trepo_config_get_bool(repo, \"core.prefersymlinkrefs\", &refs->prefer_symlink_refs);\n \n \tchdir_notify_reparent(\"files-backend $GIT_DIR\", &refs->base.gitdir);\n \tchdir_notify_reparent(\"files-backend $GIT_COMMONDIR\",\n@@ -2942,7 +2945,7 @@ static int files_transaction_finish(struct ref_store *ref_store,\n \t\t * We try creating a symlink, if that succeeds we continue to the\n \t\t * next update. If not, we try and create a regular symref.\n \t\t */\n-\t\tif (update->new_target && prefer_symlink_refs)\n+\t\tif (update->new_target && refs->prefer_symlink_refs)\n \t\t\tif (!create_ref_symlink(lock, update->new_target))\n \t\t\t\tcontinue;\n \n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502704","messageId":"3c4a9259fbbe7d0aa7edbffaffb26b13feb5f52b.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 20/21] environment: stop storing \"core.warnAmbiguousRefs\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:30:24Z","receivedAt":"2024-09-12T11:30:26Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Same as the preceding commits, storing the \"core.warnAmbiguousRefs\"\nvalue globally is misdesigned as this setting may be set per repository.\n\nMove the logic into the repo-settings subsystem. The usual pattern here\nis that users are expected to call `prepare_repo_settings()` before they\naccess the settings themselves. This seems somewhat fragile though, as\nit is easy to miss and leads to somewhat ugly code patterns at the call\nsites.\n\nInstead, introduce a new function that encapsulates this logic for us.\nThis also allows us to change how exactly the lazy initialization works\nin the future, e.g. by only partially initializing values as requested\nby the caller.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/rev-parse.c | 4 +++-\n config.c            | 5 -----\n environment.c       | 1 -\n environment.h       | 1 -\n object-name.c       | 5 +++--\n ref-filter.c        | 3 ++-\n refs.c              | 4 ++--\n repo-settings.c     | 9 +++++++++\n repo-settings.h     | 4 ++++\n 9 files changed, 23 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/rev-parse.c b/builtin/rev-parse.c\nindex a5108266daf..34b46754426 100644\n--- a/builtin/rev-parse.c\n+++ b/builtin/rev-parse.c\n@@ -19,6 +19,7 @@\n #include \"path.h\"\n #include \"diff.h\"\n #include \"read-cache-ll.h\"\n+#include \"repo-settings.h\"\n #include \"repository.h\"\n #include \"revision.h\"\n #include \"setup.h\"\n@@ -899,7 +900,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t}\n \t\t\tif (opt_with_value(arg, \"--abbrev-ref\", &arg)) {\n \t\t\t\tabbrev_ref = 1;\n-\t\t\t\tabbrev_ref_strict = warn_ambiguous_refs;\n+\t\t\t\tabbrev_ref_strict =\n+\t\t\t\t\trepo_settings_get_warn_ambiguous_refs(the_repository);\n \t\t\t\tif (arg) {\n \t\t\t\t\tif (!strcmp(arg, \"strict\"))\n \t\t\t\t\t\tabbrev_ref_strict = 1;\ndiff --git a/config.c b/config.c\nindex a59890180a3..53c68f3da61 100644\n--- a/config.c\n+++ b/config.c\n@@ -1447,11 +1447,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n-\tif (!strcmp(var, \"core.warnambiguousrefs\")) {\n-\t\twarn_ambiguous_refs = git_config_bool(var, value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.abbrev\")) {\n \t\tif (!value)\n \t\t\treturn config_error_nonbool(var);\ndiff --git a/environment.c b/environment.c\nindex 6805c7b01df..9dd000cda36 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -35,7 +35,6 @@ int minimum_abbrev = 4, default_abbrev = -1;\n int ignore_case;\n int assume_unchanged;\n int is_bare_repository_cfg = -1; /* unspecified */\n-int warn_ambiguous_refs = 1;\n int warn_on_object_refname_ambiguity = 1;\n int repository_format_precious_objects;\n char *git_commit_encoding;\ndiff --git a/environment.h b/environment.h\nindex 0cab644e2d3..aa38133da9c 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -156,7 +156,6 @@ extern int has_symlinks;\n extern int minimum_abbrev, default_abbrev;\n extern int ignore_case;\n extern int assume_unchanged;\n-extern int warn_ambiguous_refs;\n extern int warn_on_object_refname_ambiguity;\n extern char *apply_default_whitespace;\n extern char *apply_default_ignorewhitespace;\ndiff --git a/object-name.c b/object-name.c\nindex 09c1bd93a31..c892fbe80aa 100644\n--- a/object-name.c\n+++ b/object-name.c\n@@ -20,6 +20,7 @@\n #include \"pretty.h\"\n #include \"object-store-ll.h\"\n #include \"read-cache-ll.h\"\n+#include \"repo-settings.h\"\n #include \"repository.h\"\n #include \"setup.h\"\n #include \"midx.h\"\n@@ -959,7 +960,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,\n \tint fatal = !(flags & GET_OID_QUIETLY);\n \n \tif (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {\n-\t\tif (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {\n+\t\tif (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) {\n \t\t\trefs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);\n \t\t\tif (refs_found > 0) {\n \t\t\t\twarning(warn_msg, len, str);\n@@ -1020,7 +1021,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,\n \tif (!refs_found)\n \t\treturn -1;\n \n-\tif (warn_ambiguous_refs && !(flags & GET_OID_QUIETLY) &&\n+\tif (repo_settings_get_warn_ambiguous_refs(r) && !(flags & GET_OID_QUIETLY) &&\n \t    (refs_found > 1 ||\n \t     !get_short_oid(r, str, len, &tmp_oid, GET_OID_QUIETLY)))\n \t\twarning(warn_msg, len, str);\ndiff --git a/ref-filter.c b/ref-filter.c\nindex b6c6c101276..7f5cf5a1269 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -13,6 +13,7 @@\n #include \"object-name.h\"\n #include \"object-store-ll.h\"\n #include \"oid-array.h\"\n+#include \"repo-settings.h\"\n #include \"repository.h\"\n #include \"commit.h\"\n #include \"mailmap.h\"\n@@ -2160,7 +2161,7 @@ static const char *show_ref(struct refname_atom *atom, const char *refname)\n \tif (atom->option == R_SHORT)\n \t\treturn refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),\n \t\t\t\t\t\t    refname,\n-\t\t\t\t\t\t    warn_ambiguous_refs);\n+\t\t\t\t\t\t    repo_settings_get_warn_ambiguous_refs(the_repository));\n \telse if (atom->option == R_LSTRIP)\n \t\treturn lstrip_ref_components(refname, atom->lstrip);\n \telse if (atom->option == R_RSTRIP)\ndiff --git a/refs.c b/refs.c\nindex d7402bcd196..3bee3e78299 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -730,7 +730,7 @@ int expand_ref(struct repository *repo, const char *str, int len,\n \t\tif (r) {\n \t\t\tif (!refs_found++)\n \t\t\t\t*ref = xstrdup(r);\n-\t\t\tif (!warn_ambiguous_refs)\n+\t\t\tif (!repo_settings_get_warn_ambiguous_refs(repo))\n \t\t\t\tbreak;\n \t\t} else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, \"HEAD\")) {\n \t\t\twarning(_(\"ignoring dangling symref %s\"), fullref.buf);\n@@ -775,7 +775,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len,\n \t\t\tif (oid)\n \t\t\t\toidcpy(oid, &hash);\n \t\t}\n-\t\tif (!warn_ambiguous_refs)\n+\t\tif (!repo_settings_get_warn_ambiguous_refs(r))\n \t\t\tbreak;\n \t}\n \tstrbuf_release(&path);\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 1322fd2f972..4699b4b3650 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -140,3 +140,12 @@ enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *re\n \n \treturn LOG_REFS_UNSET;\n }\n+\n+int repo_settings_get_warn_ambiguous_refs(struct repository *repo)\n+{\n+\tprepare_repo_settings(repo);\n+\tif (repo->settings.warn_ambiguous_refs < 0)\n+\t\trepo_cfg_bool(repo, \"core.warnambiguousrefs\",\n+\t\t\t      &repo->settings.warn_ambiguous_refs, 1);\n+\treturn repo->settings.warn_ambiguous_refs;\n+}\ndiff --git a/repo-settings.h b/repo-settings.h\nindex 76adb96a669..51d6156a117 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -56,16 +56,20 @@ struct repo_settings {\n \tenum fetch_negotiation_setting fetch_negotiation_algorithm;\n \n \tint core_multi_pack_index;\n+\tint warn_ambiguous_refs; /* lazily loaded via accessor */\n };\n #define REPO_SETTINGS_INIT { \\\n \t.index_version = -1, \\\n \t.core_untracked_cache = UNTRACKED_CACHE_KEEP, \\\n \t.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \\\n+\t.warn_ambiguous_refs = -1, \\\n }\n \n void prepare_repo_settings(struct repository *r);\n \n /* Read the value for \"core.logAllRefUpdates\". */\n enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo);\n+/* Read the value for \"core.warnAmbiguousRefs\". */\n+int repo_settings_get_warn_ambiguous_refs(struct repository *repo);\n \n #endif /* REPO_SETTINGS_H */\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502705","messageId":"08672e8a073109e16e3522bb8b6c05e905643610.1726139990.git.ps@pks.im","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"[PATCH v3 21/21] environment: stop storing \"core.notesRef\" globally","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-09-12T11:30:26Z","receivedAt":"2024-09-12T11:30:29Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Stop storing the \"core.notesRef\" config value globally. Instead,\nretrieve the value in `default_notes_ref()`. The code is never called in\na hot loop anyway, so doing this on every invocation should be perfectly\nfine.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/notes.c | 22 ++++++++++++++--------\n config.c        |  8 --------\n environment.c   |  1 -\n environment.h   |  2 --\n notes.c         | 21 +++++++++++++--------\n notes.h         |  3 ++-\n 6 files changed, 29 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 04f9dfb7fbd..5d594a07240 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -897,6 +897,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t\t\t      1, PARSE_OPT_NONEG),\n \t\tOPT_END()\n \t};\n+\tchar *notes_ref;\n \n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_notes_merge_usage, 0);\n@@ -924,7 +925,8 @@ static int merge(int argc, const char **argv, const char *prefix)\n \tif (do_commit)\n \t\treturn merge_commit(&o);\n \n-\to.local_ref = default_notes_ref();\n+\tnotes_ref = default_notes_ref(the_repository);\n+\to.local_ref = notes_ref;\n \tstrbuf_addstr(&remote_ref, argv[0]);\n \texpand_loose_notes_ref(&remote_ref);\n \to.remote_ref = remote_ref.buf;\n@@ -953,7 +955,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t}\n \n \tstrbuf_addf(&msg, \"notes: Merged notes from %s into %s\",\n-\t\t    remote_ref.buf, default_notes_ref());\n+\t\t    remote_ref.buf, notes_ref);\n \tstrbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip \"notes: \" */\n \n \tresult = notes_merge(&o, t, &result_oid);\n@@ -961,7 +963,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \tif (result >= 0) /* Merge resulted (trivially) in result_oid */\n \t\t/* Update default notes ref with new commit */\n \t\trefs_update_ref(get_main_ref_store(the_repository), msg.buf,\n-\t\t\t\tdefault_notes_ref(), &result_oid, NULL, 0,\n+\t\t\t\tnotes_ref, &result_oid, NULL, 0,\n \t\t\t\tUPDATE_REFS_DIE_ON_ERR);\n \telse { /* Merge has unresolved conflicts */\n \t\tstruct worktree **worktrees;\n@@ -973,14 +975,14 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t\t/* Store ref-to-be-updated into .git/NOTES_MERGE_REF */\n \t\tworktrees = get_worktrees();\n \t\twt = find_shared_symref(worktrees, \"NOTES_MERGE_REF\",\n-\t\t\t\t\tdefault_notes_ref());\n+\t\t\t\t\tnotes_ref);\n \t\tif (wt)\n \t\t\tdie(_(\"a notes merge into %s is already in-progress at %s\"),\n-\t\t\t    default_notes_ref(), wt->path);\n+\t\t\t    notes_ref, wt->path);\n \t\tfree_worktrees(worktrees);\n-\t\tif (refs_update_symref(get_main_ref_store(the_repository), \"NOTES_MERGE_REF\", default_notes_ref(), NULL))\n+\t\tif (refs_update_symref(get_main_ref_store(the_repository), \"NOTES_MERGE_REF\", notes_ref, NULL))\n \t\t\tdie(_(\"failed to store link to current notes ref (%s)\"),\n-\t\t\t    default_notes_ref());\n+\t\t\t    notes_ref);\n \t\tfprintf(stderr, _(\"Automatic notes merge failed. Fix conflicts in %s \"\n \t\t\t\t  \"and commit the result with 'git notes merge --commit', \"\n \t\t\t\t  \"or abort the merge with 'git notes merge --abort'.\\n\"),\n@@ -988,6 +990,7 @@ static int merge(int argc, const char **argv, const char *prefix)\n \t}\n \n \tfree_notes(t);\n+\tfree(notes_ref);\n \tstrbuf_release(&remote_ref);\n \tstrbuf_release(&msg);\n \treturn result < 0; /* return non-zero on conflicts */\n@@ -1084,6 +1087,7 @@ static int prune(int argc, const char **argv, const char *prefix)\n static int get_ref(int argc, const char **argv, const char *prefix)\n {\n \tstruct option options[] = { OPT_END() };\n+\tchar *notes_ref;\n \targc = parse_options(argc, argv, prefix, options,\n \t\t\t     git_notes_get_ref_usage, 0);\n \n@@ -1092,7 +1096,9 @@ static int get_ref(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(git_notes_get_ref_usage, options);\n \t}\n \n-\tputs(default_notes_ref());\n+\tnotes_ref = default_notes_ref(the_repository);\n+\tputs(notes_ref);\n+\tfree(notes_ref);\n \treturn 0;\n }\n \ndiff --git a/config.c b/config.c\nindex 53c68f3da61..1266eab0860 100644\n--- a/config.c\n+++ b/config.c\n@@ -1555,14 +1555,6 @@ static int git_default_core_config(const char *var, const char *value,\n \t\treturn git_config_string(&check_roundtrip_encoding, var, value);\n \t}\n \n-\tif (!strcmp(var, \"core.notesref\")) {\n-\t\tif (!value)\n-\t\t\treturn config_error_nonbool(var);\n-\t\tfree(notes_ref_name);\n-\t\tnotes_ref_name = xstrdup(value);\n-\t\treturn 0;\n-\t}\n-\n \tif (!strcmp(var, \"core.editor\")) {\n \t\tFREE_AND_NULL(editor_program);\n \t\treturn git_config_string(&editor_program, var, value);\ndiff --git a/environment.c b/environment.c\nindex 9dd000cda36..a2ce9980818 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -67,7 +67,6 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS\n #endif\n enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n-char *notes_ref_name;\n int grafts_keep_true_parents;\n int core_apply_sparse_checkout;\n int core_sparse_checkout_cone;\ndiff --git a/environment.h b/environment.h\nindex aa38133da9c..923e12661e1 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -203,8 +203,6 @@ enum object_creation_mode {\n };\n extern enum object_creation_mode object_creation_mode;\n \n-extern char *notes_ref_name;\n-\n extern int grafts_keep_true_parents;\n \n extern int repository_format_precious_objects;\ndiff --git a/notes.c b/notes.c\nindex da42df282d5..f4f18daf07e 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -992,15 +992,16 @@ static int notes_display_config(const char *k, const char *v,\n \treturn 0;\n }\n \n-const char *default_notes_ref(void)\n+char *default_notes_ref(struct repository *repo)\n {\n-\tconst char *notes_ref = NULL;\n+\tchar *notes_ref = NULL;\n+\n \tif (!notes_ref)\n-\t\tnotes_ref = getenv(GIT_NOTES_REF_ENVIRONMENT);\n+\t\tnotes_ref = xstrdup_or_null(getenv(GIT_NOTES_REF_ENVIRONMENT));\n \tif (!notes_ref)\n-\t\tnotes_ref = notes_ref_name; /* value of core.notesRef config */\n+\t\trepo_config_get_string(repo, \"core.notesref\", &notes_ref);\n \tif (!notes_ref)\n-\t\tnotes_ref = GIT_NOTES_DEFAULT_REF;\n+\t\tnotes_ref = xstrdup(GIT_NOTES_DEFAULT_REF);\n \treturn notes_ref;\n }\n \n@@ -1010,13 +1011,14 @@ void init_notes(struct notes_tree *t, const char *notes_ref,\n \tstruct object_id oid, object_oid;\n \tunsigned short mode;\n \tstruct leaf_node root_tree;\n+\tchar *to_free = NULL;\n \n \tif (!t)\n \t\tt = &default_notes_tree;\n \tassert(!t->initialized);\n \n \tif (!notes_ref)\n-\t\tnotes_ref = default_notes_ref();\n+\t\tnotes_ref = to_free = default_notes_ref(the_repository);\n \tupdate_ref_namespace(NAMESPACE_NOTES, xstrdup(notes_ref));\n \n \tif (!combine_notes)\n@@ -1033,7 +1035,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,\n \n \tif (flags & NOTES_INIT_EMPTY ||\n \t    repo_get_oid_treeish(the_repository, notes_ref, &object_oid))\n-\t\treturn;\n+\t\tgoto out;\n \tif (flags & NOTES_INIT_WRITABLE && refs_read_ref(get_main_ref_store(the_repository), notes_ref, &object_oid))\n \t\tdie(\"Cannot use notes ref %s\", notes_ref);\n \tif (get_tree_entry(the_repository, &object_oid, \"\", &oid, &mode))\n@@ -1043,6 +1045,9 @@ void init_notes(struct notes_tree *t, const char *notes_ref,\n \toidclr(&root_tree.key_oid, the_repository->hash_algo);\n \toidcpy(&root_tree.val_oid, &oid);\n \tload_subtree(t, &root_tree, t->root, 0);\n+\n+out:\n+\tfree(to_free);\n }\n \n struct notes_tree **load_notes_trees(struct string_list *refs, int flags)\n@@ -1105,7 +1110,7 @@ void load_display_notes(struct display_notes_opt *opt)\n \n \tif (!opt || opt->use_default_notes > 0 ||\n \t    (opt->use_default_notes == -1 && !opt->extra_notes_refs.nr)) {\n-\t\tstring_list_append(&display_notes_refs, default_notes_ref());\n+\t\tstring_list_append_nodup(&display_notes_refs, default_notes_ref(the_repository));\n \t\tdisplay_ref_env = getenv(GIT_NOTES_DISPLAY_REF_ENVIRONMENT);\n \t\tif (display_ref_env) {\n \t\t\tstring_list_add_refs_from_colon_sep(&display_notes_refs,\ndiff --git a/notes.h b/notes.h\nindex 235216944bc..6dc6d7b2654 100644\n--- a/notes.h\n+++ b/notes.h\n@@ -4,6 +4,7 @@\n #include \"string-list.h\"\n \n struct object_id;\n+struct repository;\n struct strbuf;\n \n /*\n@@ -70,7 +71,7 @@ extern struct notes_tree {\n  * 3. The value of the core.notesRef config variable, if set\n  * 4. GIT_NOTES_DEFAULT_REF (i.e. \"refs/notes/commits\")\n  */\n-const char *default_notes_ref(void);\n+char *default_notes_ref(struct repository *repo);\n \n /*\n  * Flags controlling behaviour of notes tree initialization\n-- \n2.46.0.551.gc5ee8f2d1c.dirty\n\n"},{"id":"502716","messageId":"xmqqseu438s0.fsf@gitster.g","threadId":"62019","inReplyTo":"cover.1726139990.git.ps@pks.im","subject":"Re: [PATCH v3 00/21] environment: guard reliance on `the_repository`","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-09-12T20:40:47Z","receivedAt":"2024-09-12T20:40:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> this is the third version of my patch series which guards functions and\n> variables in the environment subsystem that rely on `the_repository`\n> with the `USE_THE_REPOSITORY_VARIABLE` define.\n>\n> Changes compared to v2:\n>\n>   - Adapt BUG messages in the first 5 commits to better match the new\n>     semantics of this function.\n>\n>   - Adapt commit message to mention that we don't only move over\n>     `odb_mkstemp()`, but also `odb_pack_keep()`.\n>\n>   - Explain why setting REF_FORCE_CREATE_REFLOG is equivalent to setting\n>     LOG_REFS_NORMAL.\n\nLooking good.  Let me mark the topic for 'next' soonish.\n\nThanks, all.\n"}]}