{"thread":{"id":"61914","subject":"[PATCH 00/20] Stop using `the_repository` in \"config.c\"","startedAt":"2024-08-07T06:56:49Z","lastAt":"2024-08-15T05:26:07Z","messageCount":69,"participants":["Patrick Steinhardt","Ghanshyam Thakkar","Justin Tobler","Junio C Hamano","Calvin Wan"],"isPatch":true,"patchVersion":1,"patchTotal":20},"messages":[{"id":"500270","messageId":"cover.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":null,"subject":"[PATCH 00/20] Stop using `the_repository` in \"config.c\"","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:56:43Z","receivedAt":"2024-08-07T06:56:49Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nI found that there had been a bunch of callsites in code\nnot marked with `USE_THE_REPOSITORY_VARIABLE` that still implicitly\nrelied on `the_repository` due to calling interfaces of \"config.c\".\nThis patch series has the goal of fixing that and making the dependency\nimplicit. This is done by making \"config.c\" stop using `the_repository`\nwhile moving its interfaces that do use it into \"config.h\", guarded by\nthe `USE_THE_REPOSITORY_VARIABLE` macro.\n\nThe series is structured as follows:\n\n  - Patches 1 to 7 adapt \"path.{c,h}\" to become `the_repository`-clean.\n    This is required because \"config.c\" relies on the \"path\" subsystem\n    quite a lot.\n\n  - Patches 8 and 9 introduce functions that take a `struct repository`\n    where we didn't yet equivalents for the repo-less variants.\n\n  - Patches 10 to 16 adapt various functions to take a `struct\n    repository` as input.\n\n  - Patches 17 and 18 fix up some functions that take a `struct\n    repository`, but still rely on `the_repository`.\n\n  - Patches 19 and 20 then hide config functions that rely on\n    `the_repository` behind `USE_THE_REPOSITORY_VARIABLE`.\n\nThe series is built on top of `master` at 406f326d27 (The second batch,\n2024-08-01) with ps/refs-wo-the-repository at 9d36dbd1ff (refs/reftable:\nstop using `the_repository`, 2024-07-30) merged into it.\n\nThanks!\n\nPatrick\n\nPatrick Steinhardt (20):\n  path: expose `do_git_path()` as `repo_git_pathv()`\n  path: expose `do_git_common_path()` as `strbuf_git_common_pathv()`\n  editor: do not rely on `the_repository` for interactive edits\n  hooks: remove implicit dependency on `the_repository`\n  path: stop relying on `the_repository` when reporting garbage\n  path: stop relying on `the_repository` in `worktree_git_path()`\n  path: hide functions using `the_repository` by default\n  config: introduce missing setters that take repo as parameter\n  config: expose `repo_config_clear()`\n  config: pass repo to `git_config_get_index_threads()`\n  config: pass repo to `git_config_get_split_index()`\n  config: pass repo to `git_config_get_max_percent_split_change()`\n  config: pass repo to `git_config_get_expiry()`\n  config: pass repo to `git_config_get_expiry_in_days()`\n  config: pass repo to `git_die_config()`\n  config: pass repo to functions that rename or copy sections\n  config: don't have setters depend on `the_repository`\n  config: don't depend on `the_repository` with branch conditions\n  global: prepare for hiding away repo-less config functions\n  config: hide functions using `the_repository` by default\n\n add-patch.c                       |   3 +-\n builtin/am.c                      |   9 +-\n builtin/branch.c                  |   7 +-\n builtin/bugreport.c               |   2 +-\n builtin/checkout.c                |   2 +-\n builtin/clone.c                   |   2 +-\n builtin/config.c                  |  16 +-\n builtin/count-objects.c           |   2 +-\n builtin/fast-import.c             |   4 +-\n builtin/fsck.c                    |   2 +-\n builtin/gc.c                      |   8 +-\n builtin/hook.c                    |   2 +-\n builtin/merge.c                   |   2 +-\n builtin/notes.c                   |   2 +-\n builtin/rebase.c                  |   2 +-\n builtin/receive-pack.c            |  10 +-\n builtin/remote.c                  |   4 +-\n builtin/submodule--helper.c       |   2 +-\n builtin/update-index.c            |   4 +-\n builtin/worktree.c                |   6 +-\n commit.c                          |   2 +-\n compat/fsmonitor/fsm-ipc-darwin.c |   2 +\n compat/precompose_utf8.c          |   1 +\n config.c                          | 225 ++++++++---------------\n config.h                          | 285 +++++++++++++++++++++---------\n connect.c                         |   2 +\n credential.c                      |   2 +\n daemon.c                          |   2 +\n editor.c                          |  14 +-\n editor.h                          |   3 +-\n fsmonitor.c                       |   2 +\n gpg-interface.c                   |   2 +\n graph.c                           |   2 +\n hook.c                            |  21 +--\n hook.h                            |  13 +-\n imap-send.c                       |   2 +\n mailinfo.c                        |   2 +\n merge-ll.c                        |   2 +\n parallel-checkout.c               |   2 +\n path.c                            |  97 +++-------\n path.h                            | 167 +++++++++++------\n protocol.c                        |   2 +\n read-cache.c                      |  22 +--\n refs.c                            |   4 +-\n refs/packed-backend.c             |   2 +\n refs/reftable-backend.c           |   2 +\n rerere.c                          |   4 +-\n reset.c                           |   2 +-\n revision.c                        |   2 +-\n sequencer.c                       |   6 +-\n sideband.c                        |   2 +\n submodule.c                       |   2 +-\n t/helper/test-advise.c            |   2 +\n t/helper/test-config.c            |   2 +\n t/helper/test-userdiff.c          |   2 +\n trailer.c                         |   2 +\n transport.c                       |   2 +-\n versioncmp.c                      |   2 +\n worktree.c                        |   2 +-\n wt-status.c                       |  14 +-\n 60 files changed, 564 insertions(+), 455 deletions(-)\n\n-- \n2.46.0.dirty\n\n"},{"id":"500271","messageId":"7ce3278f649ce70453242e5458d28c5fd54576ba.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 01/20] path: expose `do_git_path()` as `repo_git_pathv()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:56:47Z","receivedAt":"2024-08-07T06:56:51Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to move functions of the \"path\" subsytem that do not use a\n`struct repository` into \"path.h\" as static inlined functions. This will\nrequire us to call `do_git_path()`, which is internal to \"path.c\".\n\nExpose the function as `repo_git_pathv()` to prepare for the change.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n path.c | 20 ++++++++++----------\n path.h |  8 ++++++++\n 2 files changed, 18 insertions(+), 10 deletions(-)\n\ndiff --git a/path.c b/path.c\nindex 19f7684f38..71f1cb4dfb 100644\n--- a/path.c\n+++ b/path.c\n@@ -417,9 +417,9 @@ static void strbuf_worktree_gitdir(struct strbuf *buf,\n \t\tstrbuf_git_common_path(buf, repo, \"worktrees/%s\", wt->id);\n }\n \n-static void do_git_path(const struct repository *repo,\n-\t\t\tconst struct worktree *wt, struct strbuf *buf,\n-\t\t\tconst char *fmt, va_list args)\n+void repo_git_pathv(const struct repository *repo,\n+\t\t    const struct worktree *wt, struct strbuf *buf,\n+\t\t    const char *fmt, va_list args)\n {\n \tint gitdir_len;\n \tstrbuf_worktree_gitdir(buf, repo, wt);\n@@ -438,7 +438,7 @@ char *repo_git_path(const struct repository *repo,\n \tstruct strbuf path = STRBUF_INIT;\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(repo, NULL, &path, fmt, args);\n+\trepo_git_pathv(repo, NULL, &path, fmt, args);\n \tva_end(args);\n \treturn strbuf_detach(&path, NULL);\n }\n@@ -449,7 +449,7 @@ void strbuf_repo_git_path(struct strbuf *sb,\n {\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(repo, NULL, sb, fmt, args);\n+\trepo_git_pathv(repo, NULL, sb, fmt, args);\n \tva_end(args);\n }\n \n@@ -458,7 +458,7 @@ char *git_path_buf(struct strbuf *buf, const char *fmt, ...)\n \tva_list args;\n \tstrbuf_reset(buf);\n \tva_start(args, fmt);\n-\tdo_git_path(the_repository, NULL, buf, fmt, args);\n+\trepo_git_pathv(the_repository, NULL, buf, fmt, args);\n \tva_end(args);\n \treturn buf->buf;\n }\n@@ -467,7 +467,7 @@ void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)\n {\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(the_repository, NULL, sb, fmt, args);\n+\trepo_git_pathv(the_repository, NULL, sb, fmt, args);\n \tva_end(args);\n }\n \n@@ -476,7 +476,7 @@ const char *git_path(const char *fmt, ...)\n \tstruct strbuf *pathname = get_pathname();\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(the_repository, NULL, pathname, fmt, args);\n+\trepo_git_pathv(the_repository, NULL, pathname, fmt, args);\n \tva_end(args);\n \treturn pathname->buf;\n }\n@@ -486,7 +486,7 @@ char *git_pathdup(const char *fmt, ...)\n \tstruct strbuf path = STRBUF_INIT;\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(the_repository, NULL, &path, fmt, args);\n+\trepo_git_pathv(the_repository, NULL, &path, fmt, args);\n \tva_end(args);\n \treturn strbuf_detach(&path, NULL);\n }\n@@ -517,7 +517,7 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)\n \tstruct strbuf *pathname = get_pathname();\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(the_repository, wt, pathname, fmt, args);\n+\trepo_git_pathv(the_repository, wt, pathname, fmt, args);\n \tva_end(args);\n \treturn pathname->buf;\n }\ndiff --git a/path.h b/path.h\nindex a6f0b70692..94e7030f0b 100644\n--- a/path.h\n+++ b/path.h\n@@ -66,6 +66,14 @@ char *repo_git_path(const struct repository *repo,\n \t\t    const char *fmt, ...)\n \t__attribute__((format (printf, 2, 3)));\n \n+/*\n+ * Print a path into the git directory of repository `repo` into the provided\n+ * buffer.\n+ */\n+void repo_git_pathv(const struct repository *repo,\n+\t\t    const struct worktree *wt, struct strbuf *buf,\n+\t\t    const char *fmt, va_list args);\n+\n /*\n  * Construct a path into the git directory of repository `repo` and append it\n  * to the provided buffer `sb`.\n-- \n2.46.0.dirty\n\n"},{"id":"500272","messageId":"e7a143c30dd95d8192eacc35c876e7926cb7c6a4.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 02/20] path: expose `do_git_common_path()` as `strbuf_git_common_pathv()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:56:52Z","receivedAt":"2024-08-07T06:56:56Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"With the same reasoning as the preceding commit, expose the function\n`do_git_common_path()` as `strbuf_git_common_pathv()`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n path.c | 22 +++++++++++-----------\n path.h |  5 ++++-\n 2 files changed, 15 insertions(+), 12 deletions(-)\n\ndiff --git a/path.c b/path.c\nindex 71f1cb4dfb..bff98b255e 100644\n--- a/path.c\n+++ b/path.c\n@@ -617,16 +617,16 @@ int strbuf_git_path_submodule(struct strbuf *buf, const char *path,\n \treturn err;\n }\n \n-static void do_git_common_path(const struct repository *repo,\n-\t\t\t       struct strbuf *buf,\n-\t\t\t       const char *fmt,\n-\t\t\t       va_list args)\n+void strbuf_git_common_pathv(struct strbuf *sb,\n+\t\t\t     const struct repository *repo,\n+\t\t\t     const char *fmt,\n+\t\t\t     va_list args)\n {\n-\tstrbuf_addstr(buf, repo->commondir);\n-\tif (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))\n-\t\tstrbuf_addch(buf, '/');\n-\tstrbuf_vaddf(buf, fmt, args);\n-\tstrbuf_cleanup_path(buf);\n+\tstrbuf_addstr(sb, repo->commondir);\n+\tif (sb->len && !is_dir_sep(sb->buf[sb->len - 1]))\n+\t\tstrbuf_addch(sb, '/');\n+\tstrbuf_vaddf(sb, fmt, args);\n+\tstrbuf_cleanup_path(sb);\n }\n \n const char *git_common_path(const char *fmt, ...)\n@@ -634,7 +634,7 @@ const char *git_common_path(const char *fmt, ...)\n \tstruct strbuf *pathname = get_pathname();\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_common_path(the_repository, pathname, fmt, args);\n+\tstrbuf_git_common_pathv(pathname, the_repository, fmt, args);\n \tva_end(args);\n \treturn pathname->buf;\n }\n@@ -645,7 +645,7 @@ void strbuf_git_common_path(struct strbuf *sb,\n {\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_common_path(repo, sb, fmt, args);\n+\tstrbuf_git_common_pathv(sb, repo, fmt, args);\n \tva_end(args);\n }\n \ndiff --git a/path.h b/path.h\nindex 94e7030f0b..77eb0e6543 100644\n--- a/path.h\n+++ b/path.h\n@@ -37,6 +37,10 @@ void strbuf_git_common_path(struct strbuf *sb,\n \t\t\t    const struct repository *repo,\n \t\t\t    const char *fmt, ...)\n \t__attribute__((format (printf, 3, 4)));\n+void strbuf_git_common_pathv(struct strbuf *sb,\n+\t\t\t     const struct repository *repo,\n+\t\t\t     const char *fmt,\n+\t\t\t     va_list args);\n \n /*\n  * Return a statically allocated path into the main repository's\n@@ -45,7 +49,6 @@ void strbuf_git_common_path(struct strbuf *sb,\n const char *git_common_path(const char *fmt, ...)\n \t__attribute__((format (printf, 1, 2)));\n \n-\n /*\n  * The `git_path` family of functions will construct a path into a repository's\n  * git directory.\n-- \n2.46.0.dirty\n\n"},{"id":"500273","messageId":"c2556fff9e25aabab237c5902aff64f65b0a953f.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 03/20] editor: do not rely on `the_repository` for interactive edits","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:56:56Z","receivedAt":"2024-08-07T06:57:01Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We implicitly rely on `the_repository` when editing a file interactively\nbecause we call `git_path()`. Adapt the function to instead take a\n`sturct repository` as parameter so that we can remove this hidden\ndependency.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n add-patch.c |  3 ++-\n editor.c    | 12 +++++++-----\n editor.h    |  3 ++-\n 3 files changed, 11 insertions(+), 7 deletions(-)\n\ndiff --git a/add-patch.c b/add-patch.c\nindex 46f6bddfe5..4e3aa02ed8 100644\n--- a/add-patch.c\n+++ b/add-patch.c\n@@ -1140,7 +1140,8 @@ static int edit_hunk_manually(struct add_p_state *s, struct hunk *hunk)\n \t\t\t\t\"removed, then the edit is\\n\"\n \t\t\t\t\"aborted and the hunk is left unchanged.\\n\"));\n \n-\tif (strbuf_edit_interactively(&s->buf, \"addp-hunk-edit.diff\", NULL) < 0)\n+\tif (strbuf_edit_interactively(&s->buf, \"addp-hunk-edit.diff\", NULL,\n+\t\t\t\t      the_repository) < 0)\n \t\treturn -1;\n \n \t/* strip out commented lines */\ndiff --git a/editor.c b/editor.c\nindex d1ba2d7c34..6c461dd253 100644\n--- a/editor.c\n+++ b/editor.c\n@@ -134,13 +134,15 @@ int launch_sequence_editor(const char *path, struct strbuf *buffer,\n }\n \n int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n-\t\t\t      const char *const *env)\n+\t\t\t      const char *const *env, struct repository *r)\n {\n-\tchar *path2 = NULL;\n+\tstruct strbuf sb = STRBUF_INIT;\n \tint fd, res = 0;\n \n-\tif (!is_absolute_path(path))\n-\t\tpath = path2 = xstrdup(git_path(\"%s\", path));\n+\tif (!is_absolute_path(path)) {\n+\t\tstrbuf_repo_git_path(&sb, r, \"%s\", path);\n+\t\tpath = sb.buf;\n+\t}\n \n \tfd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);\n \tif (fd < 0)\n@@ -157,6 +159,6 @@ int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n \t\tunlink(path);\n \t}\n \n-\tfree(path2);\n+\tstrbuf_release(&sb);\n \treturn res;\n }\ndiff --git a/editor.h b/editor.h\nindex 8016bb5e00..d4c4d216ac 100644\n--- a/editor.h\n+++ b/editor.h\n@@ -1,6 +1,7 @@\n #ifndef EDITOR_H\n #define EDITOR_H\n \n+struct repository;\n struct strbuf;\n \n const char *git_editor(void);\n@@ -29,6 +30,6 @@ int launch_sequence_editor(const char *path, struct strbuf *buffer,\n  * If `path` is relative, it refers to a file in the `.git` directory.\n  */\n int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n-\t\t\t      const char *const *env);\n+\t\t\t      const char *const *env, struct repository *r);\n \n #endif\n-- \n2.46.0.dirty\n\n"},{"id":"500274","messageId":"9a0964aff3a91fe017992ad2d0266c18b7262ee1.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 04/20] hooks: remove implicit dependency on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:01Z","receivedAt":"2024-08-07T06:57:05Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We implicitly depend on `the_repository` in our hook subsystem because\nwe use `strbuf_git_path()` to compute hook paths. Remove this dependency\nby accepting a `struct repository` as parameter instead.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/am.c           |  9 +++++----\n builtin/bugreport.c    |  2 +-\n builtin/checkout.c     |  2 +-\n builtin/clone.c        |  2 +-\n builtin/gc.c           |  2 +-\n builtin/hook.c         |  2 +-\n builtin/merge.c        |  2 +-\n builtin/rebase.c       |  2 +-\n builtin/receive-pack.c | 10 +++++-----\n builtin/worktree.c     |  2 +-\n commit.c               |  2 +-\n hook.c                 | 21 +++++++++++----------\n hook.h                 | 13 ++++++++-----\n read-cache.c           |  6 +++---\n refs.c                 |  2 +-\n reset.c                |  2 +-\n sequencer.c            |  6 +++---\n transport.c            |  2 +-\n 18 files changed, 47 insertions(+), 42 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex a12be088f7..d8875ad402 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -490,7 +490,8 @@ static int run_applypatch_msg_hook(struct am_state *state)\n \tassert(state->msg);\n \n \tif (!state->no_verify)\n-\t\tret = run_hooks_l(\"applypatch-msg\", am_path(state, \"final-commit\"), NULL);\n+\t\tret = run_hooks_l(the_repository, \"applypatch-msg\",\n+\t\t\t\t  am_path(state, \"final-commit\"), NULL);\n \n \tif (!ret) {\n \t\tFREE_AND_NULL(state->msg);\n@@ -512,7 +513,7 @@ static int run_post_rewrite_hook(const struct am_state *state)\n \tstrvec_push(&opt.args, \"rebase\");\n \topt.path_to_stdin = am_path(state, \"rewritten\");\n \n-\treturn run_hooks_opt(\"post-rewrite\", &opt);\n+\treturn run_hooks_opt(the_repository, \"post-rewrite\", &opt);\n }\n \n /**\n@@ -1663,7 +1664,7 @@ static void do_commit(const struct am_state *state)\n \tconst char *reflog_msg, *author, *committer = NULL;\n \tstruct strbuf sb = STRBUF_INIT;\n \n-\tif (!state->no_verify && run_hooks(\"pre-applypatch\"))\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@@ -1716,7 +1717,7 @@ static void do_commit(const struct am_state *state)\n \t\tfclose(fp);\n \t}\n \n-\trun_hooks(\"post-applypatch\");\n+\trun_hooks(the_repository, \"post-applypatch\");\n \n \tfree_commit_list(parents);\n \tstrbuf_release(&sb);\ndiff --git a/builtin/bugreport.c b/builtin/bugreport.c\nindex b3cc77af53..bdfed3d8f1 100644\n--- a/builtin/bugreport.c\n+++ b/builtin/bugreport.c\n@@ -58,7 +58,7 @@ static void get_populated_hooks(struct strbuf *hook_info, int nongit)\n \tfor (p = hook_name_list; *p; p++) {\n \t\tconst char *hook = *p;\n \n-\t\tif (hook_exists(hook))\n+\t\tif (hook_exists(the_repository, hook))\n \t\t\tstrbuf_addf(hook_info, \"%s\\n\", hook);\n \t}\n }\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 0f21ddd2c6..89543b3054 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -125,7 +125,7 @@ static void branch_info_release(struct branch_info *info)\n static int post_checkout_hook(struct commit *old_commit, struct commit *new_commit,\n \t\t\t      int changed)\n {\n-\treturn run_hooks_l(\"post-checkout\",\n+\treturn run_hooks_l(the_repository, \"post-checkout\",\n \t\t\t   oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()),\n \t\t\t   oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),\n \t\t\t   changed ? \"1\" : \"0\", NULL);\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex af6017d41a..29d4b79eb5 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -788,7 +788,7 @@ static int checkout(int submodule_progress, int filter_submodules)\n \tif (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))\n \t\tdie(_(\"unable to write new index file\"));\n \n-\terr |= run_hooks_l(\"post-checkout\", oid_to_hex(null_oid()),\n+\terr |= run_hooks_l(the_repository, \"post-checkout\", oid_to_hex(null_oid()),\n \t\t\t   oid_to_hex(&oid), \"1\", NULL);\n \n \tif (!err && (option_recurse_submodules.nr > 0)) {\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex 72bac2554f..2ca6288c6b 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -463,7 +463,7 @@ static int need_to_gc(void)\n \telse\n \t\treturn 0;\n \n-\tif (run_hooks(\"pre-auto-gc\"))\n+\tif (run_hooks(the_repository, \"pre-auto-gc\"))\n \t\treturn 0;\n \treturn 1;\n }\ndiff --git a/builtin/hook.c b/builtin/hook.c\nindex 5234693a94..cc37438fde 100644\n--- a/builtin/hook.c\n+++ b/builtin/hook.c\n@@ -58,7 +58,7 @@ static int run(int argc, const char **argv, const char *prefix)\n \thook_name = argv[0];\n \tif (!ignore_missing)\n \t\topt.error_if_missing = 1;\n-\tret = run_hooks_opt(hook_name, &opt);\n+\tret = run_hooks_opt(the_repository, hook_name, &opt);\n \tif (ret < 0) /* error() return */\n \t\tret = 1;\n \treturn ret;\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex c896b18d1a..662a49a0e8 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -478,7 +478,7 @@ static void finish(struct commit *head_commit,\n \t}\n \n \t/* Run a post-merge hook */\n-\trun_hooks_l(\"post-merge\", squash ? \"1\" : \"0\", NULL);\n+\trun_hooks_l(the_repository, \"post-merge\", squash ? \"1\" : \"0\", NULL);\n \n \tif (new_head)\n \t\tapply_autostash_ref(the_repository, \"MERGE_AUTOSTASH\");\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex e3a8e74cfc..fa0ca613e1 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1774,7 +1774,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \n \t/* If a hook exists, give it a chance to interrupt*/\n \tif (!ok_to_skip_pre_rebase &&\n-\t    run_hooks_l(\"pre-rebase\", options.upstream_arg,\n+\t    run_hooks_l(the_repository, \"pre-rebase\", options.upstream_arg,\n \t\t\targc ? argv[0] : NULL, NULL))\n \t\tdie(_(\"The pre-rebase hook refused to rebase.\"));\n \ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex 339524ae2a..4ff22d8b15 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -792,7 +792,7 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed,\n \tstruct child_process proc = CHILD_PROCESS_INIT;\n \tstruct async muxer;\n \tint code;\n-\tconst char *hook_path = find_hook(hook_name);\n+\tconst char *hook_path = find_hook(the_repository, hook_name);\n \n \tif (!hook_path)\n \t\treturn 0;\n@@ -922,7 +922,7 @@ static int run_update_hook(struct command *cmd)\n {\n \tstruct child_process proc = CHILD_PROCESS_INIT;\n \tint code;\n-\tconst char *hook_path = find_hook(\"update\");\n+\tconst char *hook_path = find_hook(the_repository, \"update\");\n \n \tif (!hook_path)\n \t\treturn 0;\n@@ -1098,7 +1098,7 @@ static int run_proc_receive_hook(struct command *commands,\n \tint hook_use_push_options = 0;\n \tint version = 0;\n \tint code;\n-\tconst char *hook_path = find_hook(\"proc-receive\");\n+\tconst char *hook_path = find_hook(the_repository, \"proc-receive\");\n \n \tif (!hook_path) {\n \t\trp_error(\"cannot find hook 'proc-receive'\");\n@@ -1409,7 +1409,7 @@ static const char *push_to_checkout(unsigned char *hash,\n \tstrvec_pushf(env, \"GIT_WORK_TREE=%s\", absolute_path(work_tree));\n \tstrvec_pushv(&opt.env, env->v);\n \tstrvec_push(&opt.args, hash_to_hex(hash));\n-\tif (run_hooks_opt(push_to_checkout_hook, &opt))\n+\tif (run_hooks_opt(the_repository, push_to_checkout_hook, &opt))\n \t\treturn \"push-to-checkout hook declined\";\n \telse\n \t\treturn NULL;\n@@ -1618,7 +1618,7 @@ static void run_update_post_hook(struct command *commands)\n \tstruct child_process proc = CHILD_PROCESS_INIT;\n \tconst char *hook;\n \n-\thook = find_hook(\"post-update\");\n+\thook = find_hook(the_repository, \"post-update\");\n \tif (!hook)\n \t\treturn;\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 1d51e54fcd..a4b7f24e1e 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -573,7 +573,7 @@ static int add_worktree(const char *path, const char *refname,\n \t\t\t     NULL);\n \t\topt.dir = path;\n \n-\t\tret = run_hooks_opt(\"post-checkout\", &opt);\n+\t\tret = run_hooks_opt(the_repository, \"post-checkout\", &opt);\n \t}\n \n \tstrvec_clear(&child_env);\ndiff --git a/commit.c b/commit.c\nindex 087cb19f4f..24ab5c1b50 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1960,5 +1960,5 @@ int run_commit_hook(int editor_is_used, const char *index_file,\n \tva_end(args);\n \n \topt.invoked_hook = invoked_hook;\n-\treturn run_hooks_opt(name, &opt);\n+\treturn run_hooks_opt(the_repository, name, &opt);\n }\ndiff --git a/hook.c b/hook.c\nindex 7e90787bca..a9320cb0ce 100644\n--- a/hook.c\n+++ b/hook.c\n@@ -10,14 +10,14 @@\n #include \"environment.h\"\n #include \"setup.h\"\n \n-const char *find_hook(const char *name)\n+const char *find_hook(struct repository *r, const char *name)\n {\n \tstatic struct strbuf path = STRBUF_INIT;\n \n \tint found_hook;\n \n \tstrbuf_reset(&path);\n-\tstrbuf_git_path(&path, \"hooks/%s\", name);\n+\tstrbuf_repo_git_path(&path, r, \"hooks/%s\", name);\n \tfound_hook = access(path.buf, X_OK) >= 0;\n #ifdef STRIP_EXTENSION\n \tif (!found_hook) {\n@@ -48,9 +48,9 @@ const char *find_hook(const char *name)\n \treturn path.buf;\n }\n \n-int hook_exists(const char *name)\n+int hook_exists(struct repository *r, const char *name)\n {\n-\treturn !!find_hook(name);\n+\treturn !!find_hook(r, name);\n }\n \n static int pick_next_hook(struct child_process *cp,\n@@ -121,7 +121,8 @@ static void run_hooks_opt_clear(struct run_hooks_opt *options)\n \tstrvec_clear(&options->args);\n }\n \n-int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)\n+int run_hooks_opt(struct repository *r, const char *hook_name,\n+\t\t  struct run_hooks_opt *options)\n {\n \tstruct strbuf abs_path = STRBUF_INIT;\n \tstruct hook_cb_data cb_data = {\n@@ -129,7 +130,7 @@ int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)\n \t\t.hook_name = hook_name,\n \t\t.options = options,\n \t};\n-\tconst char *const hook_path = find_hook(hook_name);\n+\tconst char *const hook_path = find_hook(r, hook_name);\n \tint ret = 0;\n \tconst struct run_process_parallel_opts opts = {\n \t\t.tr2_category = \"hook\",\n@@ -173,14 +174,14 @@ int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)\n \treturn ret;\n }\n \n-int run_hooks(const char *hook_name)\n+int run_hooks(struct repository *r, const char *hook_name)\n {\n \tstruct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;\n \n-\treturn run_hooks_opt(hook_name, &opt);\n+\treturn run_hooks_opt(r, hook_name, &opt);\n }\n \n-int run_hooks_l(const char *hook_name, ...)\n+int run_hooks_l(struct repository *r, const char *hook_name, ...)\n {\n \tstruct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;\n \tva_list ap;\n@@ -191,5 +192,5 @@ int run_hooks_l(const char *hook_name, ...)\n \t\tstrvec_push(&opt.args, arg);\n \tva_end(ap);\n \n-\treturn run_hooks_opt(hook_name, &opt);\n+\treturn run_hooks_opt(r, hook_name, &opt);\n }\ndiff --git a/hook.h b/hook.h\nindex 6511525aeb..11863fa734 100644\n--- a/hook.h\n+++ b/hook.h\n@@ -2,6 +2,8 @@\n #define HOOK_H\n #include \"strvec.h\"\n \n+struct repository;\n+\n struct run_hooks_opt\n {\n \t/* Environment vars to be set for each hook */\n@@ -55,12 +57,12 @@ struct hook_cb_data {\n  * or disabled. Note that this points to static storage that will be\n  * overwritten by further calls to find_hook and run_hook_*.\n  */\n-const char *find_hook(const char *name);\n+const char *find_hook(struct repository *r, const char *name);\n \n /**\n  * A boolean version of find_hook()\n  */\n-int hook_exists(const char *hookname);\n+int hook_exists(struct repository *r, const char *hookname);\n \n /**\n  * Takes a `hook_name`, resolves it to a path with find_hook(), and\n@@ -70,13 +72,14 @@ int hook_exists(const char *hookname);\n  * Returns the status code of the run hook, or a negative value on\n  * error().\n  */\n-int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options);\n+int run_hooks_opt(struct repository *r, const char *hook_name,\n+\t\t  struct run_hooks_opt *options);\n \n /**\n  * A wrapper for run_hooks_opt() which provides a dummy \"struct\n  * run_hooks_opt\" initialized with \"RUN_HOOKS_OPT_INIT\".\n  */\n-int run_hooks(const char *hook_name);\n+int run_hooks(struct repository *r, const char *hook_name);\n \n /**\n  * Like run_hooks(), a wrapper for run_hooks_opt().\n@@ -87,5 +90,5 @@ int run_hooks(const char *hook_name);\n  * hook. This function behaves like the old run_hook_le() API.\n  */\n LAST_ARG_MUST_BE_NULL\n-int run_hooks_l(const char *hook_name, ...);\n+int run_hooks_l(struct repository *r, const char *hook_name, ...);\n #endif\ndiff --git a/read-cache.c b/read-cache.c\nindex 48bf24f87c..742369b295 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -3156,9 +3156,9 @@ static int do_write_locked_index(struct index_state *istate,\n \telse\n \t\tret = close_lock_file_gently(lock);\n \n-\trun_hooks_l(\"post-index-change\",\n-\t\t\tistate->updated_workdir ? \"1\" : \"0\",\n-\t\t\tistate->updated_skipworktree ? \"1\" : \"0\", NULL);\n+\trun_hooks_l(the_repository, \"post-index-change\",\n+\t\t    istate->updated_workdir ? \"1\" : \"0\",\n+\t\t    istate->updated_skipworktree ? \"1\" : \"0\", NULL);\n \tistate->updated_workdir = 0;\n \tistate->updated_skipworktree = 0;\n \ndiff --git a/refs.c b/refs.c\nindex e082fc59b0..0afc70b51b 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -2132,7 +2132,7 @@ static int run_transaction_hook(struct ref_transaction *transaction,\n \tconst char *hook;\n \tint ret = 0, i;\n \n-\thook = find_hook(\"reference-transaction\");\n+\thook = find_hook(transaction->ref_store->repo, \"reference-transaction\");\n \tif (!hook)\n \t\treturn ret;\n \ndiff --git a/reset.c b/reset.c\nindex 9550dea03d..b22b1be792 100644\n--- a/reset.c\n+++ b/reset.c\n@@ -79,7 +79,7 @@ static int update_refs(const struct reset_head_opts *opts,\n \t\t\t\t\t\t reflog_head);\n \t}\n \tif (!ret && run_hook)\n-\t\trun_hooks_l(\"post-checkout\",\n+\t\trun_hooks_l(the_repository, \"post-checkout\",\n \t\t\t    oid_to_hex(head ? head : null_oid()),\n \t\t\t    oid_to_hex(oid), \"1\", NULL);\n \tstrbuf_release(&msg);\ndiff --git a/sequencer.c b/sequencer.c\nindex 0291920f0b..edeeec6f15 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1316,7 +1316,7 @@ static int run_rewrite_hook(const struct object_id *oldoid,\n \tstruct child_process proc = CHILD_PROCESS_INIT;\n \tint code;\n \tstruct strbuf sb = STRBUF_INIT;\n-\tconst char *hook_path = find_hook(\"post-rewrite\");\n+\tconst char *hook_path = find_hook(the_repository, \"post-rewrite\");\n \n \tif (!hook_path)\n \t\treturn 0;\n@@ -1614,7 +1614,7 @@ static int try_to_commit(struct repository *r,\n \t\t}\n \t}\n \n-\tif (hook_exists(\"prepare-commit-msg\")) {\n+\tif (hook_exists(r, \"prepare-commit-msg\")) {\n \t\tres = run_prepare_commit_msg_hook(r, msg, hook_commit);\n \t\tif (res)\n \t\t\tgoto out;\n@@ -5149,7 +5149,7 @@ static int pick_commits(struct repository *r,\n \n \t\t\thook_opt.path_to_stdin = rebase_path_rewritten_list();\n \t\t\tstrvec_push(&hook_opt.args, \"rebase\");\n-\t\t\trun_hooks_opt(\"post-rewrite\", &hook_opt);\n+\t\t\trun_hooks_opt(r, \"post-rewrite\", &hook_opt);\n \t\t}\n \t\tapply_autostash(rebase_path_autostash());\n \ndiff --git a/transport.c b/transport.c\nindex 12cc5b4d96..f8cd2810a5 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -1271,7 +1271,7 @@ static int run_pre_push_hook(struct transport *transport,\n \tstruct ref *r;\n \tstruct child_process proc = CHILD_PROCESS_INIT;\n \tstruct strbuf buf;\n-\tconst char *hook_path = find_hook(\"pre-push\");\n+\tconst char *hook_path = find_hook(the_repository, \"pre-push\");\n \n \tif (!hook_path)\n \t\treturn 0;\n-- \n2.46.0.dirty\n\n"},{"id":"500275","messageId":"4368b32f6526b54faf50efaa8b4fb5db6ec31c50.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 05/20] path: stop relying on `the_repository` when reporting garbage","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:06Z","receivedAt":"2024-08-07T06:57:09Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We access `the_repository` in `report_linked_checkout_garbage()` both\ndirectly and indirectly via `get_git_dir()`. Remove this dependency by\ninstead passing a `struct repository` as parameter.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/count-objects.c | 2 +-\n path.c                  | 6 +++---\n path.h                  | 2 +-\n 3 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/count-objects.c b/builtin/count-objects.c\nindex 2d4bb5e8d0..ec6098a149 100644\n--- a/builtin/count-objects.c\n+++ b/builtin/count-objects.c\n@@ -113,7 +113,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(count_objects_usage, opts);\n \tif (verbose) {\n \t\treport_garbage = real_report_garbage;\n-\t\treport_linked_checkout_garbage();\n+\t\treport_linked_checkout_garbage(the_repository);\n \t}\n \n \tfor_each_loose_file_in_objdir(get_object_directory(),\ndiff --git a/path.c b/path.c\nindex bff98b255e..d6bdb992ba 100644\n--- a/path.c\n+++ b/path.c\n@@ -365,15 +365,15 @@ static void update_common_dir(struct strbuf *buf, int git_dir_len,\n \t\tstrbuf_addstr(buf, LOCK_SUFFIX);\n }\n \n-void report_linked_checkout_garbage(void)\n+void report_linked_checkout_garbage(struct repository *r)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n \tconst struct common_dir *p;\n \tint len;\n \n-\tif (!the_repository->different_commondir)\n+\tif (!r->different_commondir)\n \t\treturn;\n-\tstrbuf_addf(&sb, \"%s/\", get_git_dir());\n+\tstrbuf_addf(&sb, \"%s/\", r->gitdir);\n \tlen = sb.len;\n \tfor (p = common_list; p->path; p++) {\n \t\tconst char *path = p->path;\ndiff --git a/path.h b/path.h\nindex 77eb0e6543..3d21b9cd16 100644\n--- a/path.h\n+++ b/path.h\n@@ -158,7 +158,7 @@ int strbuf_git_path_submodule(struct strbuf *sb, const char *path,\n \t\t\t\t     const char *fmt, ...)\n \t__attribute__((format (printf, 3, 4)));\n \n-void report_linked_checkout_garbage(void);\n+void report_linked_checkout_garbage(struct repository *r);\n \n /*\n  * You can define a static memoized git path like:\n-- \n2.46.0.dirty\n\n"},{"id":"500276","messageId":"67405dcd0a121aee971f854dc35ba89bd4f808c4.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 06/20] path: stop relying on `the_repository` in `worktree_git_path()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:10Z","receivedAt":"2024-08-07T06:57:14Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"When not provided a worktree, then `worktree_git_path()` will fall back\nto returning a path relative to the main repository. In this case, we\nimplicitly rely on `the_repository` to derive the path. Remove this\ndependency by passing a `struct repository` as parameter.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fsck.c     |  2 +-\n builtin/worktree.c |  4 ++--\n path.c             |  9 +++++++--\n path.h             |  5 +++--\n revision.c         |  2 +-\n worktree.c         |  2 +-\n wt-status.c        | 14 +++++++-------\n 7 files changed, 22 insertions(+), 16 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex d13a226c2e..ad36df9628 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -1050,7 +1050,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \t\t\t * and may get overwritten by other calls\n \t\t\t * while we're examining the index.\n \t\t\t */\n-\t\t\tpath = xstrdup(worktree_git_path(wt, \"index\"));\n+\t\t\tpath = xstrdup(worktree_git_path(the_repository, wt, \"index\"));\n \t\t\tread_index_from(&istate, path, get_worktree_git_dir(wt));\n \t\t\tfsck_index(&istate, path, wt->is_current);\n \t\t\tdiscard_index(&istate);\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex a4b7f24e1e..eb0a386992 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -1146,14 +1146,14 @@ static void validate_no_submodules(const struct worktree *wt)\n \tstruct strbuf path = STRBUF_INIT;\n \tint i, found_submodules = 0;\n \n-\tif (is_directory(worktree_git_path(wt, \"modules\"))) {\n+\tif (is_directory(worktree_git_path(the_repository, wt, \"modules\"))) {\n \t\t/*\n \t\t * There could be false positives, e.g. the \"modules\"\n \t\t * directory exists but is empty. But it's a rare case and\n \t\t * this simpler check is probably good enough for now.\n \t\t */\n \t\tfound_submodules = 1;\n-\t} else if (read_index_from(&istate, worktree_git_path(wt, \"index\"),\n+\t} else if (read_index_from(&istate, worktree_git_path(the_repository, wt, \"index\"),\n \t\t\t\t   get_worktree_git_dir(wt)) > 0) {\n \t\tfor (i = 0; i < istate.cache_nr; i++) {\n \t\t\tstruct cache_entry *ce = istate.cache[i];\ndiff --git a/path.c b/path.c\nindex d6bdb992ba..567eff5253 100644\n--- a/path.c\n+++ b/path.c\n@@ -512,12 +512,17 @@ const char *mkpath(const char *fmt, ...)\n \treturn cleanup_path(pathname->buf);\n }\n \n-const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)\n+const char *worktree_git_path(struct repository *r,\n+\t\t\t      const struct worktree *wt, const char *fmt, ...)\n {\n \tstruct strbuf *pathname = get_pathname();\n \tva_list args;\n+\n+\tif (wt && wt->repo != r)\n+\t\tBUG(\"worktree not connected to expected repository\");\n+\n \tva_start(args, fmt);\n-\trepo_git_pathv(the_repository, wt, pathname, fmt, args);\n+\trepo_git_pathv(r, wt, pathname, fmt, args);\n \tva_end(args);\n \treturn pathname->buf;\n }\ndiff --git a/path.h b/path.h\nindex 3d21b9cd16..6228ca03d7 100644\n--- a/path.h\n+++ b/path.h\n@@ -97,9 +97,10 @@ const char *git_path(const char *fmt, ...)\n  * Similar to git_path() but can produce paths for a specified\n  * worktree instead of current one\n  */\n-const char *worktree_git_path(const struct worktree *wt,\n+const char *worktree_git_path(struct repository *r,\n+\t\t\t      const struct worktree *wt,\n \t\t\t      const char *fmt, ...)\n-\t__attribute__((format (printf, 2, 3)));\n+\t__attribute__((format (printf, 3, 4)));\n \n /*\n  * Return a path into the main repository's (the_repository) git directory.\ndiff --git a/revision.c b/revision.c\nindex 1c0192f522..0b92a13af5 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1872,7 +1872,7 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)\n \t\t\tcontinue; /* current index already taken care of */\n \n \t\tif (read_index_from(&istate,\n-\t\t\t\t    worktree_git_path(wt, \"index\"),\n+\t\t\t\t    worktree_git_path(the_repository, wt, \"index\"),\n \t\t\t\t    get_worktree_git_dir(wt)) > 0)\n \t\t\tdo_add_index_objects_to_pending(revs, &istate, flags);\n \t\tdiscard_index(&istate);\ndiff --git a/worktree.c b/worktree.c\nindex f3c4c8ec54..886c5db691 100644\n--- a/worktree.c\n+++ b/worktree.c\n@@ -252,7 +252,7 @@ const char *worktree_lock_reason(struct worktree *wt)\n \tif (!wt->lock_reason_valid) {\n \t\tstruct strbuf path = STRBUF_INIT;\n \n-\t\tstrbuf_addstr(&path, worktree_git_path(wt, \"locked\"));\n+\t\tstrbuf_addstr(&path, worktree_git_path(the_repository, wt, \"locked\"));\n \t\tif (file_exists(path.buf)) {\n \t\t\tstruct strbuf lock_reason = STRBUF_INIT;\n \t\t\tif (strbuf_read_file(&lock_reason, path.buf, 0) < 0)\ndiff --git a/wt-status.c b/wt-status.c\nindex b778eef989..b477239039 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1618,7 +1618,7 @@ static char *get_branch(const struct worktree *wt, const char *path)\n \tstruct object_id oid;\n \tconst char *branch_name;\n \n-\tif (strbuf_read_file(&sb, worktree_git_path(wt, \"%s\", path), 0) <= 0)\n+\tif (strbuf_read_file(&sb, worktree_git_path(the_repository, wt, \"%s\", path), 0) <= 0)\n \t\tgoto got_nothing;\n \n \twhile (sb.len && sb.buf[sb.len - 1] == '\\n')\n@@ -1716,18 +1716,18 @@ int wt_status_check_rebase(const struct worktree *wt,\n {\n \tstruct stat st;\n \n-\tif (!stat(worktree_git_path(wt, \"rebase-apply\"), &st)) {\n-\t\tif (!stat(worktree_git_path(wt, \"rebase-apply/applying\"), &st)) {\n+\tif (!stat(worktree_git_path(the_repository, wt, \"rebase-apply\"), &st)) {\n+\t\tif (!stat(worktree_git_path(the_repository, wt, \"rebase-apply/applying\"), &st)) {\n \t\t\tstate->am_in_progress = 1;\n-\t\t\tif (!stat(worktree_git_path(wt, \"rebase-apply/patch\"), &st) && !st.st_size)\n+\t\t\tif (!stat(worktree_git_path(the_repository, wt, \"rebase-apply/patch\"), &st) && !st.st_size)\n \t\t\t\tstate->am_empty_patch = 1;\n \t\t} else {\n \t\t\tstate->rebase_in_progress = 1;\n \t\t\tstate->branch = get_branch(wt, \"rebase-apply/head-name\");\n \t\t\tstate->onto = get_branch(wt, \"rebase-apply/onto\");\n \t\t}\n-\t} else if (!stat(worktree_git_path(wt, \"rebase-merge\"), &st)) {\n-\t\tif (!stat(worktree_git_path(wt, \"rebase-merge/interactive\"), &st))\n+\t} else if (!stat(worktree_git_path(the_repository, wt, \"rebase-merge\"), &st)) {\n+\t\tif (!stat(worktree_git_path(the_repository, wt, \"rebase-merge/interactive\"), &st))\n \t\t\tstate->rebase_interactive_in_progress = 1;\n \t\telse\n \t\t\tstate->rebase_in_progress = 1;\n@@ -1743,7 +1743,7 @@ int wt_status_check_bisect(const struct worktree *wt,\n {\n \tstruct stat st;\n \n-\tif (!stat(worktree_git_path(wt, \"BISECT_LOG\"), &st)) {\n+\tif (!stat(worktree_git_path(the_repository, wt, \"BISECT_LOG\"), &st)) {\n \t\tstate->bisect_in_progress = 1;\n \t\tstate->bisecting_from = get_branch(wt, \"BISECT_START\");\n \t\treturn 1;\n-- \n2.46.0.dirty\n\n"},{"id":"500277","messageId":"b4e973a2804ba09149224a2e18a359717228607e.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 07/20] path: hide functions using `the_repository` by default","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:15Z","receivedAt":"2024-08-07T06:57:19Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The path subsytem provides a bunch of legacy functions that compute\npaths relative to the \"gitdir\" and \"commondir\" directories of the global\n`the_repository` variable. Use of those functions is discouraged, and it\nis easy to miss the implicit dependency on `the_repository` that calls\nto those functions may cause.\n\nWith `USE_THE_REPOSITORY_VARIABLE`, we have recently introduced a tool\nthat allows us to get rid of such functions over time. With this define,\nwe can hide away functions that have such implicit dependency such that\nother subsystems that want to be free of `the_repository` will not use\nthem by accident.\n\nMove all path-related functions that use `the_repository` into a block\nthat gets only conditionally compiled depending on whether or not the\nmacro has been defined. This also removes all dependencies on that\nvariable in \"path.c\", allowing us to remove the definition of said\npreprocessor macro.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n path.c |  52 +-------------------\n path.h | 147 ++++++++++++++++++++++++++++++++++++++-------------------\n 2 files changed, 100 insertions(+), 99 deletions(-)\n\ndiff --git a/path.c b/path.c\nindex 567eff5253..d073ae6449 100644\n--- a/path.c\n+++ b/path.c\n@@ -2,8 +2,6 @@\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\"\n@@ -30,7 +28,7 @@ static int get_st_mode_bits(const char *path, int *mode)\n \treturn 0;\n }\n \n-static struct strbuf *get_pathname(void)\n+struct strbuf *get_pathname(void)\n {\n \tstatic struct strbuf pathname_array[4] = {\n \t\tSTRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT\n@@ -453,44 +451,6 @@ void strbuf_repo_git_path(struct strbuf *sb,\n \tva_end(args);\n }\n \n-char *git_path_buf(struct strbuf *buf, const char *fmt, ...)\n-{\n-\tva_list args;\n-\tstrbuf_reset(buf);\n-\tva_start(args, fmt);\n-\trepo_git_pathv(the_repository, NULL, buf, fmt, args);\n-\tva_end(args);\n-\treturn buf->buf;\n-}\n-\n-void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)\n-{\n-\tva_list args;\n-\tva_start(args, fmt);\n-\trepo_git_pathv(the_repository, NULL, sb, fmt, args);\n-\tva_end(args);\n-}\n-\n-const char *git_path(const char *fmt, ...)\n-{\n-\tstruct strbuf *pathname = get_pathname();\n-\tva_list args;\n-\tva_start(args, fmt);\n-\trepo_git_pathv(the_repository, NULL, pathname, fmt, args);\n-\tva_end(args);\n-\treturn pathname->buf;\n-}\n-\n-char *git_pathdup(const char *fmt, ...)\n-{\n-\tstruct strbuf path = STRBUF_INIT;\n-\tva_list args;\n-\tva_start(args, fmt);\n-\trepo_git_pathv(the_repository, NULL, &path, fmt, args);\n-\tva_end(args);\n-\treturn strbuf_detach(&path, NULL);\n-}\n-\n char *mkpathdup(const char *fmt, ...)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n@@ -634,16 +594,6 @@ void strbuf_git_common_pathv(struct strbuf *sb,\n \tstrbuf_cleanup_path(sb);\n }\n \n-const char *git_common_path(const char *fmt, ...)\n-{\n-\tstruct strbuf *pathname = get_pathname();\n-\tva_list args;\n-\tva_start(args, fmt);\n-\tstrbuf_git_common_pathv(pathname, the_repository, fmt, args);\n-\tva_end(args);\n-\treturn pathname->buf;\n-}\n-\n void strbuf_git_common_path(struct strbuf *sb,\n \t\t\t    const struct repository *repo,\n \t\t\t    const char *fmt, ...)\ndiff --git a/path.h b/path.h\nindex 6228ca03d7..22fdfc3d3a 100644\n--- a/path.h\n+++ b/path.h\n@@ -25,7 +25,7 @@ char *mkpathdup(const char *fmt, ...)\n \t__attribute__((format (printf, 1, 2)));\n \n /*\n- * The `git_common_path` family of functions will construct a path into a\n+ * The `strbuf_git_common_path` family of functions will construct a path into a\n  * repository's common git directory, which is shared by all worktrees.\n  */\n \n@@ -43,14 +43,7 @@ void strbuf_git_common_pathv(struct strbuf *sb,\n \t\t\t     va_list args);\n \n /*\n- * Return a statically allocated path into the main repository's\n- * (the_repository) common git directory.\n- */\n-const char *git_common_path(const char *fmt, ...)\n-\t__attribute__((format (printf, 1, 2)));\n-\n-/*\n- * The `git_path` family of functions will construct a path into a repository's\n+ * The `repo_git_path` family of functions will construct a path into a repository's\n  * git directory.\n  *\n  * These functions will perform adjustments to the resultant path to account\n@@ -87,14 +80,7 @@ void strbuf_repo_git_path(struct strbuf *sb,\n \t__attribute__((format (printf, 3, 4)));\n \n /*\n- * Return a statically allocated path into the main repository's\n- * (the_repository) git directory.\n- */\n-const char *git_path(const char *fmt, ...)\n-\t__attribute__((format (printf, 1, 2)));\n-\n-/*\n- * Similar to git_path() but can produce paths for a specified\n+ * Similar to repo_git_path() but can produce paths for a specified\n  * worktree instead of current one\n  */\n const char *worktree_git_path(struct repository *r,\n@@ -102,27 +88,6 @@ const char *worktree_git_path(struct repository *r,\n \t\t\t      const char *fmt, ...)\n \t__attribute__((format (printf, 3, 4)));\n \n-/*\n- * Return a path into the main repository's (the_repository) git directory.\n- */\n-char *git_pathdup(const char *fmt, ...)\n-\t__attribute__((format (printf, 1, 2)));\n-\n-/*\n- * Construct a path into the main repository's (the_repository) git directory\n- * and place it in the provided buffer `buf`, the contents of the buffer will\n- * be overridden.\n- */\n-char *git_path_buf(struct strbuf *buf, const char *fmt, ...)\n-\t__attribute__((format (printf, 2, 3)));\n-\n-/*\n- * Construct a path into the main repository's (the_repository) git directory\n- * and append it to the provided buffer `sb`.\n- */\n-void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)\n-\t__attribute__((format (printf, 2, 3)));\n-\n /*\n  * Return a path into the worktree of repository `repo`.\n  *\n@@ -164,19 +129,10 @@ void report_linked_checkout_garbage(struct repository *r);\n /*\n  * You can define a static memoized git path like:\n  *\n- *    static GIT_PATH_FUNC(git_path_foo, \"FOO\")\n+ *    static REPO_GIT_PATH_FUNC(git_path_foo, \"FOO\")\n  *\n  * or use one of the global ones below.\n  */\n-#define GIT_PATH_FUNC(func, filename) \\\n-\tconst char *func(void) \\\n-\t{ \\\n-\t\tstatic char *ret; \\\n-\t\tif (!ret) \\\n-\t\t\tret = git_pathdup(filename); \\\n-\t\treturn ret; \\\n-\t}\n-\n #define REPO_GIT_PATH_FUNC(var, filename) \\\n \tconst char *git_path_##var(struct repository *r) \\\n \t{ \\\n@@ -260,4 +216,99 @@ char *xdg_cache_home(const char *filename);\n  */\n void safe_create_dir(const char *dir, int share);\n \n+/*\n+ * Do not use this function. It is only exported to other subsystems until we\n+ * can get rid of the below block of functions that implicitly rely on\n+ * `the_repository`.\n+ */\n+struct strbuf *get_pathname(void);\n+\n+# ifdef USE_THE_REPOSITORY_VARIABLE\n+#  include \"strbuf.h\"\n+#  include \"repository.h\"\n+\n+/*\n+ * Return a statically allocated path into the main repository's\n+ * (the_repository) common git directory.\n+ */\n+__attribute__((format (printf, 1, 2)))\n+static inline const char *git_common_path(const char *fmt, ...)\n+{\n+\tstruct strbuf *pathname = get_pathname();\n+\tva_list args;\n+\tva_start(args, fmt);\n+\tstrbuf_git_common_pathv(pathname, the_repository, fmt, args);\n+\tva_end(args);\n+\treturn pathname->buf;\n+}\n+\n+/*\n+ * Construct a path into the main repository's (the_repository) git directory\n+ * and place it in the provided buffer `buf`, the contents of the buffer will\n+ * be overridden.\n+ */\n+__attribute__((format (printf, 2, 3)))\n+static inline char *git_path_buf(struct strbuf *buf, const char *fmt, ...)\n+{\n+\tva_list args;\n+\tstrbuf_reset(buf);\n+\tva_start(args, fmt);\n+\trepo_git_pathv(the_repository, NULL, buf, fmt, args);\n+\tva_end(args);\n+\treturn buf->buf;\n+}\n+\n+/*\n+ * Construct a path into the main repository's (the_repository) git directory\n+ * and append it to the provided buffer `sb`.\n+ */\n+__attribute__((format (printf, 2, 3)))\n+static inline void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)\n+{\n+\tva_list args;\n+\tva_start(args, fmt);\n+\trepo_git_pathv(the_repository, NULL, sb, fmt, args);\n+\tva_end(args);\n+}\n+\n+/*\n+ * Return a statically allocated path into the main repository's\n+ * (the_repository) git directory.\n+ */\n+__attribute__((format (printf, 1, 2)))\n+static inline const char *git_path(const char *fmt, ...)\n+{\n+\tstruct strbuf *pathname = get_pathname();\n+\tva_list args;\n+\tva_start(args, fmt);\n+\trepo_git_pathv(the_repository, NULL, pathname, fmt, args);\n+\tva_end(args);\n+\treturn pathname->buf;\n+}\n+\n+#define GIT_PATH_FUNC(func, filename) \\\n+\tconst char *func(void) \\\n+\t{ \\\n+\t\tstatic char *ret; \\\n+\t\tif (!ret) \\\n+\t\t\tret = git_pathdup(filename); \\\n+\t\treturn ret; \\\n+\t}\n+\n+/*\n+ * Return a path into the main repository's (the_repository) git directory.\n+ */\n+__attribute__((format (printf, 1, 2)))\n+static inline char *git_pathdup(const char *fmt, ...)\n+{\n+\tstruct strbuf path = STRBUF_INIT;\n+\tva_list args;\n+\tva_start(args, fmt);\n+\trepo_git_pathv(the_repository, NULL, &path, fmt, args);\n+\tva_end(args);\n+\treturn strbuf_detach(&path, NULL);\n+}\n+\n+# endif /* USE_THE_REPOSITORY_VARIABLE */\n+\n #endif /* PATH_H */\n-- \n2.46.0.dirty\n\n"},{"id":"500278","messageId":"feae2ad31ac91baae75c46c22c5c3ef3b58c1897.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 08/20] config: introduce missing setters that take repo as parameter","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:19Z","receivedAt":"2024-08-07T06:57:25Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"While we already provide some of the config-setting interfaces with a\n`struct repository` as parameter, others only have a variant that\nimplicitly depend on `the_repository`. Fill in those gaps such that we\ncan start to deprecate the repo-less variants.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 93 ++++++++++++++++++++++++++++++++++++++++++++------------\n config.h | 15 ++++++++-\n 2 files changed, 87 insertions(+), 21 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 6421894614..ac89b708e7 100644\n--- a/config.c\n+++ b/config.c\n@@ -3178,21 +3178,39 @@ static void maybe_remove_section(struct config_store_data *store,\n \t\t*end_offset = store->parsed[store->parsed_nr - 1].end;\n }\n \n+int repo_config_set_in_file_gently(struct repository *r, const char *config_filename,\n+\t\t\t\t   const char *key, const char *comment, const char *value)\n+{\n+\treturn repo_config_set_multivar_in_file_gently(r, config_filename, key, value, NULL, comment, 0);\n+}\n+\n int git_config_set_in_file_gently(const char *config_filename,\n \t\t\t\t  const char *key, const char *comment, const char *value)\n {\n-\treturn git_config_set_multivar_in_file_gently(config_filename, key, value, NULL, comment, 0);\n+\treturn repo_config_set_in_file_gently(the_repository, config_filename,\n+\t\t\t\t\t      key, comment, value);\n+}\n+\n+void repo_config_set_in_file(struct repository *r, const char *config_filename,\n+\t\t\t     const char *key, const char *value)\n+{\n+\trepo_config_set_multivar_in_file(r, config_filename, key, value, NULL, 0);\n }\n \n void git_config_set_in_file(const char *config_filename,\n \t\t\t    const char *key, const char *value)\n {\n-\tgit_config_set_multivar_in_file(config_filename, key, value, NULL, 0);\n+\trepo_config_set_in_file(the_repository, config_filename, key, value);\n+}\n+\n+int repo_config_set_gently(struct repository *r, const char *key, const char *value)\n+{\n+\treturn repo_config_set_multivar_gently(r, key, value, NULL, 0);\n }\n \n int git_config_set_gently(const char *key, const char *value)\n {\n-\treturn git_config_set_multivar_gently(key, value, NULL, 0);\n+\treturn repo_config_set_gently(the_repository, key, value);\n }\n \n int repo_config_set_worktree_gently(struct repository *r,\n@@ -3209,13 +3227,18 @@ int repo_config_set_worktree_gently(struct repository *r,\n \treturn repo_config_set_multivar_gently(r, key, value, NULL, 0);\n }\n \n-void git_config_set(const char *key, const char *value)\n+void repo_config_set(struct repository *r, const char *key, const char *value)\n {\n-\tgit_config_set_multivar(key, value, NULL, 0);\n+\trepo_config_set_multivar(r, key, value, NULL, 0);\n \n \ttrace2_cmd_set_config(key, value);\n }\n \n+void git_config_set(const char *key, const char *value)\n+{\n+\trepo_config_set(the_repository, key, value);\n+}\n+\n char *git_config_prepare_comment_string(const char *comment)\n {\n \tsize_t leading_blanks;\n@@ -3293,11 +3316,12 @@ static void validate_comment_string(const char *comment)\n  * - the config file is removed and the lock file rename()d to it.\n  *\n  */\n-int git_config_set_multivar_in_file_gently(const char *config_filename,\n-\t\t\t\t\t   const char *key, const char *value,\n-\t\t\t\t\t   const char *value_pattern,\n-\t\t\t\t\t   const char *comment,\n-\t\t\t\t\t   unsigned flags)\n+int repo_config_set_multivar_in_file_gently(struct repository *r,\n+\t\t\t\t\t    const char *config_filename,\n+\t\t\t\t\t    const char *key, const char *value,\n+\t\t\t\t\t    const char *value_pattern,\n+\t\t\t\t\t    const char *comment,\n+\t\t\t\t\t    unsigned flags)\n {\n \tint fd = -1, in_fd = -1;\n \tint ret;\n@@ -3317,7 +3341,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,\n \tstore.multi_replace = (flags & CONFIG_FLAGS_MULTI_REPLACE) != 0;\n \n \tif (!config_filename)\n-\t\tconfig_filename = filename_buf = git_pathdup(\"config\");\n+\t\tconfig_filename = filename_buf = repo_git_path(r, \"config\");\n \n \t/*\n \t * The lock serves a purpose in addition to locking: the new\n@@ -3526,7 +3550,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,\n \tret = 0;\n \n \t/* Invalidate the config cache */\n-\tgit_config_clear();\n+\trepo_config_clear(r);\n \n out_free:\n \trollback_lock_file(&lock);\n@@ -3543,12 +3567,24 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,\n \tgoto out_free;\n }\n \n-void git_config_set_multivar_in_file(const char *config_filename,\n-\t\t\t\t     const char *key, const char *value,\n-\t\t\t\t     const char *value_pattern, unsigned flags)\n+int git_config_set_multivar_in_file_gently(const char *config_filename,\n+\t\t\t\t\t   const char *key, const char *value,\n+\t\t\t\t\t   const char *value_pattern,\n+\t\t\t\t\t   const char *comment,\n+\t\t\t\t\t   unsigned flags)\n {\n-\tif (!git_config_set_multivar_in_file_gently(config_filename, key, value,\n-\t\t\t\t\t\t    value_pattern, NULL, flags))\n+\treturn repo_config_set_multivar_in_file_gently(the_repository, config_filename,\n+\t\t\t\t\t\t       key, value, value_pattern,\n+\t\t\t\t\t\t       comment, flags);\n+}\n+\n+void repo_config_set_multivar_in_file(struct repository *r,\n+\t\t\t\t      const char *config_filename,\n+\t\t\t\t      const char *key, const char *value,\n+\t\t\t\t      const char *value_pattern, unsigned flags)\n+{\n+\tif (!repo_config_set_multivar_in_file_gently(r, config_filename, key, value,\n+\t\t\t\t\t\t     value_pattern, NULL, flags))\n \t\treturn;\n \tif (value)\n \t\tdie(_(\"could not set '%s' to '%s'\"), key, value);\n@@ -3556,6 +3592,14 @@ void git_config_set_multivar_in_file(const char *config_filename,\n \t\tdie(_(\"could not unset '%s'\"), key);\n }\n \n+void git_config_set_multivar_in_file(const char *config_filename,\n+\t\t\t\t     const char *key, const char *value,\n+\t\t\t\t     const char *value_pattern, unsigned flags)\n+{\n+\trepo_config_set_multivar_in_file(the_repository, config_filename,\n+\t\t\t\t\t key, value, value_pattern, flags);\n+}\n+\n int git_config_set_multivar_gently(const char *key, const char *value,\n \t\t\t\t   const char *value_pattern, unsigned flags)\n {\n@@ -3576,12 +3620,21 @@ int repo_config_set_multivar_gently(struct repository *r, const char *key,\n \treturn res;\n }\n \n+void repo_config_set_multivar(struct repository *r,\n+\t\t\t      const char *key, const char *value,\n+\t\t\t      const char *value_pattern, unsigned flags)\n+{\n+\tchar *file = repo_git_path(r, \"config\");\n+\tgit_config_set_multivar_in_file(file, key, value,\n+\t\t\t\t\tvalue_pattern, flags);\n+\tfree(file);\n+}\n+\n void git_config_set_multivar(const char *key, const char *value,\n \t\t\t     const char *value_pattern, unsigned flags)\n {\n-\tgit_config_set_multivar_in_file(git_path(\"config\"),\n-\t\t\t\t\tkey, value, value_pattern,\n-\t\t\t\t\tflags);\n+\trepo_config_set_multivar(the_repository, key, value,\n+\t\t\t\t value_pattern, flags);\n }\n \n static size_t section_name_match (const char *buf, const char *name)\ndiff --git a/config.h b/config.h\nindex 54b47dec9e..b13e1bfb8d 100644\n--- a/config.h\n+++ b/config.h\n@@ -298,14 +298,18 @@ int git_config_pathname(char **, const char *, const char *);\n int git_config_expiry_date(timestamp_t *, const char *, const char *);\n int git_config_color(char *, const char *, const char *);\n int git_config_set_in_file_gently(const char *, const char *, const char *, const char *);\n+int repo_config_set_in_file_gently(struct repository *r, const char *config_filename,\n+\t\t\t\t   const char *key, const char *comment, const char *value);\n \n /**\n  * write config values to a specific config file, takes a key/value pair as\n  * parameter.\n  */\n void git_config_set_in_file(const char *, const char *, const char *);\n+void repo_config_set_in_file(struct repository *, const char *, const char *, const char *);\n \n int git_config_set_gently(const char *, const char *);\n+int repo_config_set_gently(struct repository *r, const char *, const char *);\n \n /**\n  * Write a config value that should apply to the current worktree. If\n@@ -318,6 +322,7 @@ int repo_config_set_worktree_gently(struct repository *, const char *, const cha\n  * write config values to `.git/config`, takes a key/value pair as parameter.\n  */\n void git_config_set(const char *, const char *);\n+void repo_config_set(struct repository *, const char *, const char *);\n \n int git_config_parse_key(const char *, char **, size_t *);\n \n@@ -341,9 +346,11 @@ int git_config_parse_key(const char *, char **, size_t *);\n #define CONFIG_FLAGS_FIXED_VALUE (1 << 1)\n \n int git_config_set_multivar_gently(const char *, const char *, const char *, unsigned);\n-void git_config_set_multivar(const char *, const char *, const char *, unsigned);\n int repo_config_set_multivar_gently(struct repository *, const char *, const char *, const char *, unsigned);\n+void git_config_set_multivar(const char *, const char *, const char *, unsigned);\n+void repo_config_set_multivar(struct repository *r, const char *, const char *, const char *, unsigned);\n int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, const char *, unsigned);\n+int repo_config_set_multivar_in_file_gently(struct repository *, const char *, const char *, const char *, const char *, const char *, unsigned);\n \n char *git_config_prepare_comment_string(const char *);\n \n@@ -372,6 +379,12 @@ void git_config_set_multivar_in_file(const char *config_filename,\n \t\t\t\t     const char *value,\n \t\t\t\t     const char *value_pattern,\n \t\t\t\t     unsigned flags);\n+void repo_config_set_multivar_in_file(struct repository *r,\n+\t\t\t\t      const char *config_filename,\n+\t\t\t\t      const char *key,\n+\t\t\t\t      const char *value,\n+\t\t\t\t      const char *value_pattern,\n+\t\t\t\t      unsigned flags);\n \n /**\n  * rename or remove sections in the config file\n-- \n2.46.0.dirty\n\n"},{"id":"500279","messageId":"63da87696eb361cd4c6952523941172f2f50f438.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 09/20] config: expose `repo_config_clear()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:24Z","receivedAt":"2024-08-07T06:57:28Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"While we already have `repo_config_clear()` as an alternative to\n`git_config_clear()` that doesn't rely on `the_repository`, it is not\nexposed to callers outside of the config subsystem. Do so.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 2 +-\n config.h | 1 +\n 2 files changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/config.c b/config.c\nindex ac89b708e7..476cd73c9e 100644\n--- a/config.c\n+++ b/config.c\n@@ -2564,7 +2564,7 @@ static void git_config_check_init(struct repository *repo)\n \trepo_read_config(repo);\n }\n \n-static void repo_config_clear(struct repository *repo)\n+void repo_config_clear(struct repository *repo)\n {\n \tif (!repo->config || !repo->config->hash_initialized)\n \t\treturn;\ndiff --git a/config.h b/config.h\nindex b13e1bfb8d..8eb3efa0c4 100644\n--- a/config.h\n+++ b/config.h\n@@ -651,6 +651,7 @@ int git_config_get_string_multi(const char *key,\n  * Resets and invalidates the config cache.\n  */\n void git_config_clear(void);\n+void repo_config_clear(struct repository *repo);\n \n /**\n  * Allocates and copies the retrieved string into the `dest` parameter for\n-- \n2.46.0.dirty\n\n"},{"id":"500280","messageId":"03df1277f70faaaf52df24bcb10732c107c2294c.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 10/20] config: pass repo to `git_config_get_index_threads()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:29Z","receivedAt":"2024-08-07T06:57:32Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_config_get_index_threads()` to accept a `struct\nrepository` such that we can get rid of the implicit dependency on\n`the_repository`. Rename the function accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c     | 4 ++--\n config.h     | 2 +-\n read-cache.c | 8 ++++----\n 3 files changed, 7 insertions(+), 7 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 476cd73c9e..387c7282e9 100644\n--- a/config.c\n+++ b/config.c\n@@ -2826,7 +2826,7 @@ int git_config_get_max_percent_split_change(void)\n \treturn -1; /* default value */\n }\n \n-int git_config_get_index_threads(int *dest)\n+int repo_config_get_index_threads(struct repository *r, int *dest)\n {\n \tint is_bool, val;\n \n@@ -2836,7 +2836,7 @@ int git_config_get_index_threads(int *dest)\n \t\treturn 0;\n \t}\n \n-\tif (!git_config_get_bool_or_int(\"index.threads\", &is_bool, &val)) {\n+\tif (!repo_config_get_bool_or_int(r, \"index.threads\", &is_bool, &val)) {\n \t\tif (is_bool)\n \t\t\t*dest = val ? 0 : 1;\n \t\telse\ndiff --git a/config.h b/config.h\nindex 8eb3efa0c4..3f68b30047 100644\n--- a/config.h\n+++ b/config.h\n@@ -710,7 +710,7 @@ int git_config_get_maybe_bool(const char *key, int *dest);\n  */\n int git_config_get_pathname(const char *key, char **dest);\n \n-int git_config_get_index_threads(int *dest);\n+int repo_config_get_index_threads(struct repository *r, int *dest);\n int git_config_get_split_index(void);\n int git_config_get_max_percent_split_change(void);\n \ndiff --git a/read-cache.c b/read-cache.c\nindex 742369b295..ad09950153 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -2267,7 +2267,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n \n \tsrc_offset = sizeof(*hdr);\n \n-\tif (git_config_get_index_threads(&nr_threads))\n+\tif (repo_config_get_index_threads(the_repository, &nr_threads))\n \t\tnr_threads = 1;\n \n \t/* TODO: does creating more threads than cores help? */\n@@ -2787,7 +2787,7 @@ static int record_eoie(void)\n \t * used for threading is written by default if the user\n \t * explicitly requested threaded index reads.\n \t */\n-\treturn !git_config_get_index_threads(&val) && val != 1;\n+\treturn !repo_config_get_index_threads(the_repository, &val) && val != 1;\n }\n \n static int record_ieot(void)\n@@ -2802,7 +2802,7 @@ static int record_ieot(void)\n \t * written by default if the user explicitly requested\n \t * threaded index reads.\n \t */\n-\treturn !git_config_get_index_threads(&val) && val != 1;\n+\treturn !repo_config_get_index_threads(the_repository, &val) && val != 1;\n }\n \n enum write_extensions {\n@@ -2875,7 +2875,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,\n \n \thashwrite(f, &hdr, sizeof(hdr));\n \n-\tif (!HAVE_THREADS || git_config_get_index_threads(&nr_threads))\n+\tif (!HAVE_THREADS || repo_config_get_index_threads(the_repository, &nr_threads))\n \t\tnr_threads = 1;\n \n \tif (nr_threads != 1 && record_ieot()) {\n-- \n2.46.0.dirty\n\n"},{"id":"500281","messageId":"85311d686e0b747a902efc55546246fc36faa05f.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 11/20] config: pass repo to `git_config_get_split_index()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:33Z","receivedAt":"2024-08-07T06:57:37Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_config_get_split_index()` to accept a `struct repository`\nsuch that we can get rid of the implicit dependency on `the_repository`.\nRename the function accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/update-index.c | 4 ++--\n config.c               | 4 ++--\n config.h               | 2 +-\n read-cache.c           | 2 +-\n 4 files changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex d343416ae2..35a1f957ad 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -1156,7 +1156,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \tend_odb_transaction();\n \n \tif (split_index > 0) {\n-\t\tif (git_config_get_split_index() == 0)\n+\t\tif (repo_config_get_split_index(the_repository) == 0)\n \t\t\twarning(_(\"core.splitIndex is set to false; \"\n \t\t\t\t  \"remove or change it, if you really want to \"\n \t\t\t\t  \"enable split index\"));\n@@ -1165,7 +1165,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t\telse\n \t\t\tadd_split_index(the_repository->index);\n \t} else if (!split_index) {\n-\t\tif (git_config_get_split_index() == 1)\n+\t\tif (repo_config_get_split_index(the_repository) == 1)\n \t\t\twarning(_(\"core.splitIndex is set to true; \"\n \t\t\t\t  \"remove or change it, if you really want to \"\n \t\t\t\t  \"disable split index\"));\ndiff --git a/config.c b/config.c\nindex 387c7282e9..89fb7ce6b1 100644\n--- a/config.c\n+++ b/config.c\n@@ -2801,11 +2801,11 @@ int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestam\n \treturn -1; /* thing exists but cannot be parsed */\n }\n \n-int git_config_get_split_index(void)\n+int repo_config_get_split_index(struct repository *r)\n {\n \tint val;\n \n-\tif (!git_config_get_maybe_bool(\"core.splitindex\", &val))\n+\tif (!repo_config_get_maybe_bool(r, \"core.splitindex\", &val))\n \t\treturn val;\n \n \treturn -1; /* default value */\ndiff --git a/config.h b/config.h\nindex 3f68b30047..35cee9d4ca 100644\n--- a/config.h\n+++ b/config.h\n@@ -711,7 +711,7 @@ int git_config_get_maybe_bool(const char *key, int *dest);\n int git_config_get_pathname(const char *key, char **dest);\n \n int repo_config_get_index_threads(struct repository *r, int *dest);\n-int git_config_get_split_index(void);\n+int repo_config_get_split_index(struct repository *r);\n int git_config_get_max_percent_split_change(void);\n \n /* This dies if the configured or default date is in the future */\ndiff --git a/read-cache.c b/read-cache.c\nindex ad09950153..12c2da5a8b 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1945,7 +1945,7 @@ static void tweak_untracked_cache(struct index_state *istate)\n \n static void tweak_split_index(struct index_state *istate)\n {\n-\tswitch (git_config_get_split_index()) {\n+\tswitch (repo_config_get_split_index(the_repository)) {\n \tcase -1: /* unset: do nothing */\n \t\tbreak;\n \tcase 0: /* false */\n-- \n2.46.0.dirty\n\n"},{"id":"500282","messageId":"b95ed05f883f771274d0af367c368e87f84895e2.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 12/20] config: pass repo to `git_config_get_max_percent_split_change()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:38Z","receivedAt":"2024-08-07T06:57:42Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_config_get_max_percent_split_change()` to accept a `struct\nrepository` such that we can get rid of the implicit dependency on\n`the_repository`. Rename the function accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c     | 4 ++--\n config.h     | 2 +-\n read-cache.c | 2 +-\n 3 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 89fb7ce6b1..f1d2fb6d4c 100644\n--- a/config.c\n+++ b/config.c\n@@ -2811,11 +2811,11 @@ int repo_config_get_split_index(struct repository *r)\n \treturn -1; /* default value */\n }\n \n-int git_config_get_max_percent_split_change(void)\n+int repo_config_get_max_percent_split_change(struct repository *r)\n {\n \tint val = -1;\n \n-\tif (!git_config_get_int(\"splitindex.maxpercentchange\", &val)) {\n+\tif (!repo_config_get_int(r, \"splitindex.maxpercentchange\", &val)) {\n \t\tif (0 <= val && val <= 100)\n \t\t\treturn val;\n \ndiff --git a/config.h b/config.h\nindex 35cee9d4ca..dd7127b8e9 100644\n--- a/config.h\n+++ b/config.h\n@@ -712,7 +712,7 @@ int git_config_get_pathname(const char *key, char **dest);\n \n int repo_config_get_index_threads(struct repository *r, int *dest);\n int repo_config_get_split_index(struct repository *r);\n-int git_config_get_max_percent_split_change(void);\n+int repo_config_get_max_percent_split_change(struct repository *r);\n \n /* This dies if the configured or default date is in the future */\n int git_config_get_expiry(const char *key, const char **output);\ndiff --git a/read-cache.c b/read-cache.c\nindex 12c2da5a8b..1e52db7f36 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -3275,7 +3275,7 @@ static const int default_max_percent_split_change = 20;\n static int too_many_not_shared_entries(struct index_state *istate)\n {\n \tint i, not_shared = 0;\n-\tint max_split = git_config_get_max_percent_split_change();\n+\tint max_split = repo_config_get_max_percent_split_change(the_repository);\n \n \tswitch (max_split) {\n \tcase -1:\n-- \n2.46.0.dirty\n\n"},{"id":"500283","messageId":"412cc514e8f4b40c45d1c80224bba72688c4c576.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 13/20] config: pass repo to `git_config_get_expiry()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:42Z","receivedAt":"2024-08-07T06:57:48Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_config_get_expiry()` to accept a `struct repository` such\nthat we can get rid of the implicit dependency on `the_repository`.\nRename the function accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/gc.c | 6 +++---\n config.c     | 4 ++--\n config.h     | 2 +-\n read-cache.c | 4 ++--\n 4 files changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex 2ca6288c6b..dc87c65906 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -167,9 +167,9 @@ static void gc_config(void)\n \tgit_config_get_bool(\"gc.autodetach\", &detach_auto);\n \tgit_config_get_bool(\"gc.cruftpacks\", &cruft_packs);\n \tgit_config_get_ulong(\"gc.maxcruftsize\", &max_cruft_size);\n-\tgit_config_get_expiry(\"gc.pruneexpire\", &prune_expire);\n-\tgit_config_get_expiry(\"gc.worktreepruneexpire\", &prune_worktrees_expire);\n-\tgit_config_get_expiry(\"gc.logexpiry\", &gc_log_expire);\n+\trepo_config_get_expiry(the_repository, \"gc.pruneexpire\", &prune_expire);\n+\trepo_config_get_expiry(the_repository, \"gc.worktreepruneexpire\", &prune_worktrees_expire);\n+\trepo_config_get_expiry(the_repository, \"gc.logexpiry\", &gc_log_expire);\n \n \tgit_config_get_ulong(\"gc.bigpackthreshold\", &big_pack_threshold);\n \tgit_config_get_ulong(\"pack.deltacachesize\", &max_delta_cache_size);\ndiff --git a/config.c b/config.c\nindex f1d2fb6d4c..4138dc50ce 100644\n--- a/config.c\n+++ b/config.c\n@@ -2766,9 +2766,9 @@ int git_config_get_pathname(const char *key, char **dest)\n \treturn repo_config_get_pathname(the_repository, key, dest);\n }\n \n-int git_config_get_expiry(const char *key, const char **output)\n+int repo_config_get_expiry(struct repository *r, const char *key, const char **output)\n {\n-\tint ret = git_config_get_string(key, (char **)output);\n+\tint ret = repo_config_get_string(r, key, (char **)output);\n \tif (ret)\n \t\treturn ret;\n \tif (strcmp(*output, \"now\")) {\ndiff --git a/config.h b/config.h\nindex dd7127b8e9..7674617a1d 100644\n--- a/config.h\n+++ b/config.h\n@@ -715,7 +715,7 @@ int repo_config_get_split_index(struct repository *r);\n int repo_config_get_max_percent_split_change(struct repository *r);\n \n /* This dies if the configured or default date is in the future */\n-int git_config_get_expiry(const char *key, const char **output);\n+int repo_config_get_expiry(struct repository *r, const char *key, const char **output);\n \n /* parse either \"this many days\" integer, or \"5.days.ago\" approxidate */\n int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now);\ndiff --git a/read-cache.c b/read-cache.c\nindex 1e52db7f36..18394d7180 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -3184,8 +3184,8 @@ static unsigned long get_shared_index_expire_date(void)\n \tstatic int shared_index_expire_date_prepared;\n \n \tif (!shared_index_expire_date_prepared) {\n-\t\tgit_config_get_expiry(\"splitindex.sharedindexexpire\",\n-\t\t\t\t      &shared_index_expire);\n+\t\trepo_config_get_expiry(the_repository, \"splitindex.sharedindexexpire\",\n+\t\t\t\t       &shared_index_expire);\n \t\tshared_index_expire_date = approxidate(shared_index_expire);\n \t\tshared_index_expire_date_prepared = 1;\n \t}\n-- \n2.46.0.dirty\n\n"},{"id":"500284","messageId":"cf7942479f75d95dcd8606b0947a8897ae60da60.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 14/20] config: pass repo to `git_config_get_expiry_in_days()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:47Z","receivedAt":"2024-08-07T06:57:50Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_config_get_expiry_in_days()` to accept a `struct\nrepository` such that we can get rid of the implicit dependency on\n`the_repository`. Rename the function accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 5 +++--\n config.h | 3 ++-\n rerere.c | 4 ++--\n 3 files changed, 7 insertions(+), 5 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 4138dc50ce..33d9af29c8 100644\n--- a/config.c\n+++ b/config.c\n@@ -2779,13 +2779,14 @@ int repo_config_get_expiry(struct repository *r, const char *key, const char **o\n \treturn ret;\n }\n \n-int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestamp_t now)\n+int repo_config_get_expiry_in_days(struct repository *r, const char *key,\n+\t\t\t\t   timestamp_t *expiry, timestamp_t now)\n {\n \tconst char *expiry_string;\n \tintmax_t days;\n \ttimestamp_t when;\n \n-\tif (git_config_get_string_tmp(key, &expiry_string))\n+\tif (repo_config_get_string_tmp(r, key, &expiry_string))\n \t\treturn 1; /* no such thing */\n \n \tif (git_parse_signed(expiry_string, &days, maximum_signed_value_of_type(int))) {\ndiff --git a/config.h b/config.h\nindex 7674617a1d..3a5016afea 100644\n--- a/config.h\n+++ b/config.h\n@@ -718,7 +718,8 @@ int repo_config_get_max_percent_split_change(struct repository *r);\n int repo_config_get_expiry(struct repository *r, const char *key, const char **output);\n \n /* parse either \"this many days\" integer, or \"5.days.ago\" approxidate */\n-int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now);\n+int repo_config_get_expiry_in_days(struct repository *r, const char *key,\n+\t\t\t\t   timestamp_t *, timestamp_t now);\n \n /**\n  * First prints the error message specified by the caller in `err` and then\ndiff --git a/rerere.c b/rerere.c\nindex 3a3888cce2..bdd9fb2ff8 100644\n--- a/rerere.c\n+++ b/rerere.c\n@@ -1203,8 +1203,8 @@ void rerere_gc(struct repository *r, struct string_list *rr)\n \tif (setup_rerere(r, rr, 0) < 0)\n \t\treturn;\n \n-\tgit_config_get_expiry_in_days(\"gc.rerereresolved\", &cutoff_resolve, now);\n-\tgit_config_get_expiry_in_days(\"gc.rerereunresolved\", &cutoff_noresolve, now);\n+\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereresolved\", &cutoff_resolve, now);\n+\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereunresolved\", &cutoff_noresolve, now);\n \tgit_config(git_default_config, NULL);\n \tdir = opendir(git_path(\"rr-cache\"));\n \tif (!dir)\n-- \n2.46.0.dirty\n\n"},{"id":"500285","messageId":"d70d9bfa7eef82d0488da647c3cd1277282f8ee0.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 15/20] config: pass repo to `git_die_config()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:51Z","receivedAt":"2024-08-07T06:57:55Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_die_config()` to accept a `struct repository` such that we\ncan get rid of the implicit dependency on `the_repository`. Rename the\nfunction accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fast-import.c |  4 ++--\n builtin/notes.c       |  2 +-\n config.c              | 12 ++++++------\n config.h              |  3 ++-\n 4 files changed, 11 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex d21c4053a7..0249503c70 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -3481,8 +3481,8 @@ static void git_pack_config(void)\n \tif (!git_config_get_int(\"pack.indexversion\", &indexversion_value)) {\n \t\tpack_idx_opts.version = indexversion_value;\n \t\tif (pack_idx_opts.version > 2)\n-\t\t\tgit_die_config(\"pack.indexversion\",\n-\t\t\t\t\t\"bad pack.indexVersion=%\"PRIu32, pack_idx_opts.version);\n+\t\t\tgit_die_config(the_repository, \"pack.indexversion\",\n+\t\t\t\t       \"bad pack.indexVersion=%\"PRIu32, pack_idx_opts.version);\n \t}\n \tif (!git_config_get_ulong(\"pack.packsizelimit\", &packsizelimit_value))\n \t\tmax_packsize = packsizelimit_value;\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex d9c356e354..c0fa86d847 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -868,7 +868,7 @@ static int git_config_get_notes_strategy(const char *key,\n \tif (git_config_get_string(key, &value))\n \t\treturn 1;\n \tif (parse_notes_merge_strategy(value, strategy))\n-\t\tgit_die_config(key, _(\"unknown notes merge strategy %s\"), value);\n+\t\tgit_die_config(the_repository, key, _(\"unknown notes merge strategy %s\"), value);\n \n \tfree(value);\n \treturn 0;\ndiff --git a/config.c b/config.c\nindex 33d9af29c8..e35fc90238 100644\n--- a/config.c\n+++ b/config.c\n@@ -2611,7 +2611,7 @@ int repo_config_get_string(struct repository *repo,\n \tgit_config_check_init(repo);\n \tret = git_configset_get_string(repo->config, key, dest);\n \tif (ret < 0)\n-\t\tgit_die_config(key, NULL);\n+\t\tgit_die_config(repo, key, NULL);\n \treturn ret;\n }\n \n@@ -2622,7 +2622,7 @@ int repo_config_get_string_tmp(struct repository *repo,\n \tgit_config_check_init(repo);\n \tret = git_configset_get_string_tmp(repo->config, key, dest);\n \tif (ret < 0)\n-\t\tgit_die_config(key, NULL);\n+\t\tgit_die_config(repo, key, NULL);\n \treturn ret;\n }\n \n@@ -2668,7 +2668,7 @@ int repo_config_get_pathname(struct repository *repo,\n \tgit_config_check_init(repo);\n \tret = git_configset_get_pathname(repo->config, key, dest);\n \tif (ret < 0)\n-\t\tgit_die_config(key, NULL);\n+\t\tgit_die_config(repo, key, NULL);\n \treturn ret;\n }\n \n@@ -2774,7 +2774,7 @@ int repo_config_get_expiry(struct repository *r, const char *key, const char **o\n \tif (strcmp(*output, \"now\")) {\n \t\ttimestamp_t now = approxidate(\"now\");\n \t\tif (approxidate(*output) >= now)\n-\t\t\tgit_die_config(key, _(\"Invalid %s: '%s'\"), key, *output);\n+\t\t\tgit_die_config(r, key, _(\"Invalid %s: '%s'\"), key, *output);\n \t}\n \treturn ret;\n }\n@@ -2858,7 +2858,7 @@ void git_die_config_linenr(const char *key, const char *filename, int linenr)\n \t\t    key, filename, linenr);\n }\n \n-void git_die_config(const char *key, const char *err, ...)\n+void git_die_config(struct repository *r, const char *key, const char *err, ...)\n {\n \tconst struct string_list *values;\n \tstruct key_value_info *kv_info;\n@@ -2870,7 +2870,7 @@ void git_die_config(const char *key, const char *err, ...)\n \t\terror_fn(err, params);\n \t\tva_end(params);\n \t}\n-\tif (git_config_get_value_multi(key, &values))\n+\tif (repo_config_get_value_multi(r, key, &values))\n \t\tBUG(\"for key '%s' we must have a value to report on\", key);\n \tkv_info = values->items[values->nr - 1].util;\n \tgit_die_config_linenr(key, kv_info->filename, kv_info->linenr);\ndiff --git a/config.h b/config.h\nindex 3a5016afea..947307c591 100644\n--- a/config.h\n+++ b/config.h\n@@ -726,7 +726,8 @@ int repo_config_get_expiry_in_days(struct repository *r, const char *key,\n  * dies printing the line number and the file name of the highest priority\n  * value for the configuration variable `key`.\n  */\n-NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));\n+NORETURN void git_die_config(struct repository *r, const char *key, const char *err, ...)\n+\t__attribute__((format(printf, 3, 4)));\n \n /**\n  * Helper function which formats the die error message according to the\n-- \n2.46.0.dirty\n\n"},{"id":"500286","messageId":"980533972ce73c0d7a4450c2ebb514231c3ca649.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 16/20] config: pass repo to functions that rename or copy sections","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:57:56Z","receivedAt":"2024-08-07T06:58:02Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor functions that rename or copy config sections to accept a\n`struct repository` such that we can get rid of the implicit dependency\non `the_repository`. Rename the functions accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/branch.c            |  7 ++++---\n builtin/config.c            | 16 ++++++++--------\n builtin/remote.c            |  4 ++--\n builtin/submodule--helper.c |  2 +-\n config.c                    | 30 ++++++++++++++++--------------\n config.h                    |  8 ++++----\n submodule.c                 |  2 +-\n 7 files changed, 36 insertions(+), 33 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 48cac74f97..3f870741bf 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -210,7 +210,7 @@ static void delete_branch_config(const char *branchname)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n \tstrbuf_addf(&buf, \"branch.%s\", branchname);\n-\tif (git_config_rename_section(buf.buf, NULL) < 0)\n+\tif (repo_config_rename_section(the_repository, buf.buf, NULL) < 0)\n \t\twarning(_(\"update of config-file failed\"));\n \tstrbuf_release(&buf);\n }\n@@ -659,9 +659,10 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int\n \n \tstrbuf_addf(&oldsection, \"branch.%s\", interpreted_oldname);\n \tstrbuf_addf(&newsection, \"branch.%s\", interpreted_newname);\n-\tif (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0)\n+\tif (!copy && repo_config_rename_section(the_repository, oldsection.buf, newsection.buf) < 0)\n \t\tdie(_(\"branch is renamed, but update of config-file failed\"));\n-\tif (copy && strcmp(interpreted_oldname, interpreted_newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0)\n+\tif (copy && strcmp(interpreted_oldname, interpreted_newname) &&\n+\t    repo_config_copy_section(the_repository, oldsection.buf, newsection.buf) < 0)\n \t\tdie(_(\"branch is copied, but update of config-file failed\"));\n \tstrbuf_release(&oldref);\n \tstrbuf_release(&newref);\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 20a0b64090..e00d983596 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -1026,8 +1026,8 @@ static int cmd_config_rename_section(int argc, const char **argv, const char *pr\n \tlocation_options_init(&location_opts, prefix);\n \tcheck_write(&location_opts.source);\n \n-\tret = git_config_rename_section_in_file(location_opts.source.file,\n-\t\t\t\t\t\targv[0], argv[1]);\n+\tret = repo_config_rename_section_in_file(the_repository, location_opts.source.file,\n+\t\t\t\t\t\t argv[0], argv[1]);\n \tif (ret < 0)\n \t\tgoto out;\n \telse if (!ret)\n@@ -1055,8 +1055,8 @@ static int cmd_config_remove_section(int argc, const char **argv, const char *pr\n \tlocation_options_init(&location_opts, prefix);\n \tcheck_write(&location_opts.source);\n \n-\tret = git_config_rename_section_in_file(location_opts.source.file,\n-\t\t\t\t\t\targv[0], NULL);\n+\tret = repo_config_rename_section_in_file(the_repository, location_opts.source.file,\n+\t\t\t\t\t\t argv[0], NULL);\n \tif (ret < 0)\n \t\tgoto out;\n \telse if (!ret)\n@@ -1353,8 +1353,8 @@ static int cmd_config_actions(int argc, const char **argv, const char *prefix)\n \telse if (actions == ACTION_RENAME_SECTION) {\n \t\tcheck_write(&location_opts.source);\n \t\tcheck_argc(argc, 2, 2);\n-\t\tret = git_config_rename_section_in_file(location_opts.source.file,\n-\t\t\t\t\t\t\targv[0], argv[1]);\n+\t\tret = repo_config_rename_section_in_file(the_repository, location_opts.source.file,\n+\t\t\t\t\t\t\t argv[0], argv[1]);\n \t\tif (ret < 0)\n \t\t\tgoto out;\n \t\telse if (!ret)\n@@ -1365,8 +1365,8 @@ static int cmd_config_actions(int argc, const char **argv, const char *prefix)\n \telse if (actions == ACTION_REMOVE_SECTION) {\n \t\tcheck_write(&location_opts.source);\n \t\tcheck_argc(argc, 1, 1);\n-\t\tret = git_config_rename_section_in_file(location_opts.source.file,\n-\t\t\t\t\t\t\targv[0], NULL);\n+\t\tret = repo_config_rename_section_in_file(the_repository, location_opts.source.file,\n+\t\t\t\t\t\t\t argv[0], NULL);\n \t\tif (ret < 0)\n \t\t\tgoto out;\n \t\telse if (!ret)\ndiff --git a/builtin/remote.c b/builtin/remote.c\nindex 08292498bd..fef3026ef4 100644\n--- a/builtin/remote.c\n+++ b/builtin/remote.c\n@@ -736,7 +736,7 @@ static int mv(int argc, const char **argv, const char *prefix)\n \n \tstrbuf_addf(&buf, \"remote.%s\", rename.old_name);\n \tstrbuf_addf(&buf2, \"remote.%s\", rename.new_name);\n-\tif (git_config_rename_section(buf.buf, buf2.buf) < 1)\n+\tif (repo_config_rename_section(the_repository, buf.buf, buf2.buf) < 1)\n \t\treturn error(_(\"Could not rename config section '%s' to '%s'\"),\n \t\t\t\tbuf.buf, buf2.buf);\n \n@@ -944,7 +944,7 @@ static int rm(int argc, const char **argv, const char *prefix)\n \n \tif (!result) {\n \t\tstrbuf_addf(&buf, \"remote.%s\", remote->name);\n-\t\tif (git_config_rename_section(buf.buf, NULL) < 1)\n+\t\tif (repo_config_rename_section(the_repository, buf.buf, NULL) < 1)\n \t\t\treturn error(_(\"Could not remove config section '%s'\"), buf.buf);\n \n \t\thandle_push_default(remote->name, NULL);\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f1218a1995..662c87c06c 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1455,7 +1455,7 @@ static void deinit_submodule(const char *path, const char *prefix,\n \t\t * remove the whole section so we have a clean state when\n \t\t * the user later decides to init this submodule again\n \t\t */\n-\t\tgit_config_rename_section_in_file(NULL, sub_key, NULL);\n+\t\trepo_config_rename_section_in_file(the_repository, NULL, sub_key, NULL);\n \t\tif (!(flags & OPT_QUIET))\n \t\t\tprintf(_(\"Submodule '%s' (%s) unregistered for path '%s'\\n\"),\n \t\t\t\t sub->name, sub->url, displaypath);\ndiff --git a/config.c b/config.c\nindex e35fc90238..ed39922dbb 100644\n--- a/config.c\n+++ b/config.c\n@@ -3697,9 +3697,11 @@ static int section_name_is_ok(const char *name)\n #define GIT_CONFIG_MAX_LINE_LEN (512 * 1024)\n \n /* if new_name == NULL, the section is removed instead */\n-static int git_config_copy_or_rename_section_in_file(const char *config_filename,\n-\t\t\t\t      const char *old_name,\n-\t\t\t\t      const char *new_name, int copy)\n+static int repo_config_copy_or_rename_section_in_file(\n+\tstruct repository *r,\n+\tconst char *config_filename,\n+\tconst char *old_name,\n+\tconst char *new_name, int copy)\n {\n \tint ret = 0, remove = 0;\n \tchar *filename_buf = NULL;\n@@ -3720,7 +3722,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename\n \t}\n \n \tif (!config_filename)\n-\t\tconfig_filename = filename_buf = git_pathdup(\"config\");\n+\t\tconfig_filename = filename_buf = repo_git_path(r, \"config\");\n \n \tout_fd = hold_lock_file_for_update(&lock, config_filename, 0);\n \tif (out_fd < 0) {\n@@ -3863,28 +3865,28 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename\n \treturn ret;\n }\n \n-int git_config_rename_section_in_file(const char *config_filename,\n-\t\t\t\t      const char *old_name, const char *new_name)\n+int repo_config_rename_section_in_file(struct repository *r, const char *config_filename,\n+\t\t\t\t       const char *old_name, const char *new_name)\n {\n-\treturn git_config_copy_or_rename_section_in_file(config_filename,\n+\treturn repo_config_copy_or_rename_section_in_file(r, config_filename,\n \t\t\t\t\t old_name, new_name, 0);\n }\n \n-int git_config_rename_section(const char *old_name, const char *new_name)\n+int repo_config_rename_section(struct repository *r, const char *old_name, const char *new_name)\n {\n-\treturn git_config_rename_section_in_file(NULL, old_name, new_name);\n+\treturn repo_config_rename_section_in_file(r, NULL, old_name, new_name);\n }\n \n-int git_config_copy_section_in_file(const char *config_filename,\n-\t\t\t\t      const char *old_name, const char *new_name)\n+int repo_config_copy_section_in_file(struct repository *r, const char *config_filename,\n+\t\t\t\t     const char *old_name, const char *new_name)\n {\n-\treturn git_config_copy_or_rename_section_in_file(config_filename,\n+\treturn repo_config_copy_or_rename_section_in_file(r, config_filename,\n \t\t\t\t\t old_name, new_name, 1);\n }\n \n-int git_config_copy_section(const char *old_name, const char *new_name)\n+int repo_config_copy_section(struct repository *r, const char *old_name, const char *new_name)\n {\n-\treturn git_config_copy_section_in_file(NULL, old_name, new_name);\n+\treturn repo_config_copy_section_in_file(r, NULL, old_name, new_name);\n }\n \n /*\ndiff --git a/config.h b/config.h\nindex 947307c591..589d6dae26 100644\n--- a/config.h\n+++ b/config.h\n@@ -392,11 +392,11 @@ void repo_config_set_multivar_in_file(struct repository *r,\n  * If NULL is passed through `new_name` parameter,\n  * the section will be removed from the config file.\n  */\n-int git_config_rename_section(const char *, const char *);\n+int repo_config_rename_section(struct repository *, const char *, const char *);\n \n-int git_config_rename_section_in_file(const char *, const char *, const char *);\n-int git_config_copy_section(const char *, const char *);\n-int git_config_copy_section_in_file(const char *, const char *, const char *);\n+int repo_config_rename_section_in_file(struct repository *, const char *, const char *, const char *);\n+int repo_config_copy_section(struct repository *, const char *, const char *);\n+int repo_config_copy_section_in_file(struct repository *, const char *, const char *, const char *);\n int git_config_system(void);\n int config_error_nonbool(const char *);\n #if defined(__GNUC__)\ndiff --git a/submodule.c b/submodule.c\nindex ab99a30253..bc04fc8284 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -159,7 +159,7 @@ int remove_path_from_gitmodules(const char *path)\n \t}\n \tstrbuf_addstr(&sect, \"submodule.\");\n \tstrbuf_addstr(&sect, submodule->name);\n-\tif (git_config_rename_section_in_file(GITMODULES_FILE, sect.buf, NULL) < 0) {\n+\tif (repo_config_rename_section_in_file(the_repository, GITMODULES_FILE, sect.buf, NULL) < 0) {\n \t\t/* Maybe the user already did that, don't error out here */\n \t\twarning(_(\"Could not remove .gitmodules entry for %s\"), path);\n \t\tstrbuf_release(&sect);\n-- \n2.46.0.dirty\n\n"},{"id":"500287","messageId":"1c1b27cbacc5c5d858363b8ed6ad8fe27f863574.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 17/20] config: don't have setters depend on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:58:01Z","receivedAt":"2024-08-07T06:58:05Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Some of the setters that accept a `struct repository` still implicitly\nrely on `the_repository` via `git_config_set_multivar_in_file()`. While\nthis function would typically use the caller-provided path, it knows to\nfall back to using the configuration path indicated by `the_repository`.\n\nAdapt those functions to instead use the caller-provided repository.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex ed39922dbb..831c9eacb0 100644\n--- a/config.c\n+++ b/config.c\n@@ -3220,8 +3220,8 @@ int repo_config_set_worktree_gently(struct repository *r,\n \t/* Only use worktree-specific config if it is already enabled. */\n \tif (r->repository_format_worktree_config) {\n \t\tchar *file = repo_git_path(r, \"config.worktree\");\n-\t\tint ret = git_config_set_multivar_in_file_gently(\n-\t\t\t\t\tfile, key, value, NULL, NULL, 0);\n+\t\tint ret = repo_config_set_multivar_in_file_gently(\n+\t\t\t\t\tr, file, key, value, NULL, NULL, 0);\n \t\tfree(file);\n \t\treturn ret;\n \t}\n@@ -3613,10 +3613,10 @@ int repo_config_set_multivar_gently(struct repository *r, const char *key,\n \t\t\t\t    const char *value_pattern, unsigned flags)\n {\n \tchar *file = repo_git_path(r, \"config\");\n-\tint res = git_config_set_multivar_in_file_gently(file,\n-\t\t\t\t\t\t\t key, value,\n-\t\t\t\t\t\t\t value_pattern,\n-\t\t\t\t\t\t\t NULL, flags);\n+\tint res = repo_config_set_multivar_in_file_gently(r, file,\n+\t\t\t\t\t\t\t  key, value,\n+\t\t\t\t\t\t\t  value_pattern,\n+\t\t\t\t\t\t\t  NULL, flags);\n \tfree(file);\n \treturn res;\n }\n@@ -3626,8 +3626,8 @@ void repo_config_set_multivar(struct repository *r,\n \t\t\t      const char *value_pattern, unsigned flags)\n {\n \tchar *file = repo_git_path(r, \"config\");\n-\tgit_config_set_multivar_in_file(file, key, value,\n-\t\t\t\t\tvalue_pattern, flags);\n+\trepo_config_set_multivar_in_file(r, file, key, value,\n+\t\t\t\t\t value_pattern, flags);\n \tfree(file);\n }\n \n-- \n2.46.0.dirty\n\n"},{"id":"500288","messageId":"d8530a300b4cf0f854f2b0d03c79876c11d81116.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 18/20] config: don't depend on `the_repository` with branch conditions","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:58:05Z","receivedAt":"2024-08-07T06:58:11Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"When computing branch \"includeIf\" conditions we use `the_repository` to\nobtain the main ref store. We really shouldn't depend on this global\nrepository though, but should instead use the repository that is being\npassed to us via `struct config_include_data`. Otherwise, when parsing\nconfiguration of e.g. submodules, we may end up evaluating the condition\nthe via the wrong refdb.\n\nFix this.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 9 +++++----\n 1 file changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 831c9eacb0..08437f75e5 100644\n--- a/config.c\n+++ b/config.c\n@@ -300,13 +300,14 @@ static int include_by_gitdir(const struct key_value_info *kvi,\n \treturn ret;\n }\n \n-static int include_by_branch(const char *cond, size_t cond_len)\n+static int include_by_branch(struct config_include_data *data,\n+\t\t\t     const char *cond, size_t cond_len)\n {\n \tint flags;\n \tint ret;\n \tstruct strbuf pattern = STRBUF_INIT;\n-\tconst char *refname = !the_repository->gitdir ?\n-\t\tNULL : refs_resolve_ref_unsafe(get_main_ref_store(the_repository),\n+\tconst char *refname = (!data->repo || !data->repo->gitdir) ?\n+\t\tNULL : refs_resolve_ref_unsafe(get_main_ref_store(data->repo),\n \t\t\t\t\t       \"HEAD\", 0, NULL, &flags);\n \tconst char *shortname;\n \n@@ -406,7 +407,7 @@ static int include_condition_is_true(const struct key_value_info *kvi,\n \telse if (skip_prefix_mem(cond, cond_len, \"gitdir/i:\", &cond, &cond_len))\n \t\treturn include_by_gitdir(kvi, opts, cond, cond_len, 1);\n \telse if (skip_prefix_mem(cond, cond_len, \"onbranch:\", &cond, &cond_len))\n-\t\treturn include_by_branch(cond, cond_len);\n+\t\treturn include_by_branch(inc, cond, cond_len);\n \telse if (skip_prefix_mem(cond, cond_len, \"hasconfig:remote.*.url:\", &cond,\n \t\t\t\t   &cond_len))\n \t\treturn include_by_remote_url(inc, cond, cond_len);\n-- \n2.46.0.dirty\n\n"},{"id":"500289","messageId":"f7617beaa5aad64fe98ac52015eb68786114728b.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 19/20] global: prepare for hiding away repo-less config functions","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:58:10Z","receivedAt":"2024-08-07T06:58:13Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to hide config functions that implicitly depend on\n`the_repository` behind the `USE_THE_REPOSITORY_VARIABLE` macro. This\nwill uncover a bunch of dependents that transitively relied on the\nglobal variable, but didn'd define the macro yet.\n\nAdapt them such that we define the macro to prepare for this change.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n compat/fsmonitor/fsm-ipc-darwin.c | 2 ++\n compat/precompose_utf8.c          | 1 +\n connect.c                         | 2 ++\n credential.c                      | 2 ++\n daemon.c                          | 2 ++\n editor.c                          | 2 ++\n fsmonitor.c                       | 2 ++\n gpg-interface.c                   | 2 ++\n graph.c                           | 2 ++\n imap-send.c                       | 2 ++\n mailinfo.c                        | 2 ++\n merge-ll.c                        | 2 ++\n parallel-checkout.c               | 2 ++\n protocol.c                        | 2 ++\n refs.c                            | 2 ++\n refs/packed-backend.c             | 2 ++\n refs/reftable-backend.c           | 2 ++\n sideband.c                        | 2 ++\n t/helper/test-advise.c            | 2 ++\n t/helper/test-config.c            | 2 ++\n t/helper/test-userdiff.c          | 2 ++\n trailer.c                         | 2 ++\n versioncmp.c                      | 2 ++\n 23 files changed, 45 insertions(+)\n\ndiff --git a/compat/fsmonitor/fsm-ipc-darwin.c b/compat/fsmonitor/fsm-ipc-darwin.c\nindex 52f4f29720..fe149a1b37 100644\n--- a/compat/fsmonitor/fsm-ipc-darwin.c\n+++ b/compat/fsmonitor/fsm-ipc-darwin.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 \"gettext.h\"\ndiff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c\nindex 0bd5c24250..f7cc7b3be5 100644\n--- a/compat/precompose_utf8.c\n+++ b/compat/precompose_utf8.c\n@@ -4,6 +4,7 @@\n  */\n \n #define PRECOMPOSE_UNICODE_C\n+#define USE_THE_REPOSITORY_VARIABLE\n \n #include \"git-compat-util.h\"\n #include \"config.h\"\ndiff --git a/connect.c b/connect.c\nindex cf84e631e9..6829ab3974 100644\n--- a/connect.c\n+++ b/connect.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 \"environment.h\"\ndiff --git a/credential.c b/credential.c\nindex 4b1a2b94fe..ee46351ce0 100644\n--- a/credential.c\n+++ b/credential.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"config.h\"\ndiff --git a/daemon.c b/daemon.c\nindex 17d331b2f3..c65b068b76 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"config.h\"\ndiff --git a/editor.c b/editor.c\nindex 6c461dd253..323d7d91e2 100644\n--- a/editor.c\n+++ b/editor.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"advice.h\"\ndiff --git a/fsmonitor.c b/fsmonitor.c\nindex 2b17d60bbb..28130f748f 100644\n--- a/fsmonitor.c\n+++ b/fsmonitor.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 \"dir.h\"\ndiff --git a/gpg-interface.c b/gpg-interface.c\nindex 5c824aeb25..6587085cd1 100644\n--- a/gpg-interface.c\n+++ b/gpg-interface.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"commit.h\"\n #include \"config.h\"\ndiff --git a/graph.c b/graph.c\nindex 1ca34770ee..091c14cf4f 100644\n--- a/graph.c\n+++ b/graph.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"gettext.h\"\n #include \"config.h\"\ndiff --git a/imap-send.c b/imap-send.c\nindex 01404e5047..b2eb3d2dd0 100644\n--- a/imap-send.c\n+++ b/imap-send.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 \"config.h\"\n #include \"credential.h\"\ndiff --git a/mailinfo.c b/mailinfo.c\nindex 94b9b0abf2..95228531a6 100644\n--- a/mailinfo.c\n+++ b/mailinfo.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 \"gettext.h\"\ndiff --git a/merge-ll.c b/merge-ll.c\nindex 180c19df67..badb6dea57 100644\n--- a/merge-ll.c\n+++ b/merge-ll.c\n@@ -4,6 +4,8 @@\n  * Copyright (c) 2007 Junio C Hamano\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"config.h\"\n #include \"convert.h\"\ndiff --git a/parallel-checkout.c b/parallel-checkout.c\nindex 08b960aac8..01736f1352 100644\n--- a/parallel-checkout.c\n+++ b/parallel-checkout.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 \"entry.h\"\ndiff --git a/protocol.c b/protocol.c\nindex 079ba75acf..bae7226ff4 100644\n--- a/protocol.c\n+++ b/protocol.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 \"environment.h\"\ndiff --git a/refs.c b/refs.c\nindex 0afc70b51b..284c64dfc5 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -2,6 +2,8 @@\n  * The backend-independent part of the reference module.\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"advice.h\"\n #include \"config.h\"\ndiff --git a/refs/packed-backend.c b/refs/packed-backend.c\nindex 89976aa359..ba2ad90d10 100644\n--- a/refs/packed-backend.c\n+++ b/refs/packed-backend.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 \"../dir.h\"\ndiff --git a/refs/reftable-backend.c b/refs/reftable-backend.c\nindex bf4446afd3..df67923d21 100644\n--- a/refs/reftable-backend.c\n+++ b/refs/reftable-backend.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"../git-compat-util.h\"\n #include \"../abspath.h\"\n #include \"../chdir-notify.h\"\ndiff --git a/sideband.c b/sideband.c\nindex 5d8907151f..5b6b872a1c 100644\n--- a/sideband.c\n+++ b/sideband.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"color.h\"\n #include \"config.h\"\ndiff --git a/t/helper/test-advise.c b/t/helper/test-advise.c\nindex 8a3fd0009a..6967c8e25c 100644\n--- a/t/helper/test-advise.c\n+++ b/t/helper/test-advise.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"test-tool.h\"\n #include \"advice.h\"\n #include \"config.h\"\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex ed444ca4c2..e193079ed5 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"test-tool.h\"\n #include \"config.h\"\n #include \"setup.h\"\ndiff --git a/t/helper/test-userdiff.c b/t/helper/test-userdiff.c\nindex 0ce31ce59f..94c48ababb 100644\n--- a/t/helper/test-userdiff.c\n+++ b/t/helper/test-userdiff.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"test-tool.h\"\n #include \"setup.h\"\n #include \"userdiff.h\"\ndiff --git a/trailer.c b/trailer.c\nindex 72e5136c73..682d74505b 100644\n--- a/trailer.c\n+++ b/trailer.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 \"environment.h\"\ndiff --git a/versioncmp.c b/versioncmp.c\nindex 45e676cbca..e3b2a6e330 100644\n--- a/versioncmp.c\n+++ b/versioncmp.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-- \n2.46.0.dirty\n\n"},{"id":"500290","messageId":"43757f30770bf5a27fd8d7ac55a343185dbe62b3.1723013714.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH 20/20] config: hide functions using `the_repository` by default","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T06:58:15Z","receivedAt":"2024-08-07T06:58:18Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The config subsytem provides a bunch of legacy functions that read or\nset configuration for `the_repository`. The use of those functions is\ndiscouraged, and it is easy to miss the implicit dependency on\n`the_repository` that calls to those functions may cause.\n\nMove all config-related functions that use `the_repository` into a block\nthat gets only conditionally compiled depending on whether or not the\nmacro has been defined. This also removes all dependencies on that\nvariable in \"config.c\", allowing us to remove the definition of said\npreprocessor macro.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 130 -----------------------------\n config.h | 249 ++++++++++++++++++++++++++++++++++++++-----------------\n 2 files changed, 171 insertions(+), 208 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 08437f75e5..c4fdbf6e1b 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@@ -2695,78 +2693,6 @@ void git_protected_config(config_fn_t fn, void *data)\n \tconfigset_iter(&protected_config, fn, data);\n }\n \n-/* Functions used historically to read configuration from 'the_repository' */\n-void git_config(config_fn_t fn, void *data)\n-{\n-\trepo_config(the_repository, fn, data);\n-}\n-\n-void git_config_clear(void)\n-{\n-\trepo_config_clear(the_repository);\n-}\n-\n-int git_config_get(const char *key)\n-{\n-\treturn repo_config_get(the_repository, key);\n-}\n-\n-int git_config_get_value(const char *key, const char **value)\n-{\n-\treturn repo_config_get_value(the_repository, key, value);\n-}\n-\n-int git_config_get_value_multi(const char *key, const struct string_list **dest)\n-{\n-\treturn repo_config_get_value_multi(the_repository, key, dest);\n-}\n-\n-int git_config_get_string_multi(const char *key,\n-\t\t\t\tconst struct string_list **dest)\n-{\n-\treturn repo_config_get_string_multi(the_repository, key, dest);\n-}\n-\n-int git_config_get_string(const char *key, char **dest)\n-{\n-\treturn repo_config_get_string(the_repository, key, dest);\n-}\n-\n-int git_config_get_string_tmp(const char *key, const char **dest)\n-{\n-\treturn repo_config_get_string_tmp(the_repository, key, dest);\n-}\n-\n-int git_config_get_int(const char *key, int *dest)\n-{\n-\treturn repo_config_get_int(the_repository, key, dest);\n-}\n-\n-int git_config_get_ulong(const char *key, unsigned long *dest)\n-{\n-\treturn repo_config_get_ulong(the_repository, key, dest);\n-}\n-\n-int git_config_get_bool(const char *key, int *dest)\n-{\n-\treturn repo_config_get_bool(the_repository, key, dest);\n-}\n-\n-int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest)\n-{\n-\treturn repo_config_get_bool_or_int(the_repository, key, is_bool, dest);\n-}\n-\n-int git_config_get_maybe_bool(const char *key, int *dest)\n-{\n-\treturn repo_config_get_maybe_bool(the_repository, key, dest);\n-}\n-\n-int git_config_get_pathname(const char *key, char **dest)\n-{\n-\treturn repo_config_get_pathname(the_repository, key, dest);\n-}\n-\n int repo_config_get_expiry(struct repository *r, const char *key, const char **output)\n {\n \tint ret = repo_config_get_string(r, key, (char **)output);\n@@ -3186,35 +3112,17 @@ int repo_config_set_in_file_gently(struct repository *r, const char *config_file\n \treturn repo_config_set_multivar_in_file_gently(r, config_filename, key, value, NULL, comment, 0);\n }\n \n-int git_config_set_in_file_gently(const char *config_filename,\n-\t\t\t\t  const char *key, const char *comment, const char *value)\n-{\n-\treturn repo_config_set_in_file_gently(the_repository, config_filename,\n-\t\t\t\t\t      key, comment, value);\n-}\n-\n void repo_config_set_in_file(struct repository *r, const char *config_filename,\n \t\t\t     const char *key, const char *value)\n {\n \trepo_config_set_multivar_in_file(r, config_filename, key, value, NULL, 0);\n }\n \n-void git_config_set_in_file(const char *config_filename,\n-\t\t\t    const char *key, const char *value)\n-{\n-\trepo_config_set_in_file(the_repository, config_filename, key, value);\n-}\n-\n int repo_config_set_gently(struct repository *r, const char *key, const char *value)\n {\n \treturn repo_config_set_multivar_gently(r, key, value, NULL, 0);\n }\n \n-int git_config_set_gently(const char *key, const char *value)\n-{\n-\treturn repo_config_set_gently(the_repository, key, value);\n-}\n-\n int repo_config_set_worktree_gently(struct repository *r,\n \t\t\t\t    const char *key, const char *value)\n {\n@@ -3236,11 +3144,6 @@ void repo_config_set(struct repository *r, const char *key, const char *value)\n \ttrace2_cmd_set_config(key, value);\n }\n \n-void git_config_set(const char *key, const char *value)\n-{\n-\trepo_config_set(the_repository, key, value);\n-}\n-\n char *git_config_prepare_comment_string(const char *comment)\n {\n \tsize_t leading_blanks;\n@@ -3569,17 +3472,6 @@ int repo_config_set_multivar_in_file_gently(struct repository *r,\n \tgoto out_free;\n }\n \n-int git_config_set_multivar_in_file_gently(const char *config_filename,\n-\t\t\t\t\t   const char *key, const char *value,\n-\t\t\t\t\t   const char *value_pattern,\n-\t\t\t\t\t   const char *comment,\n-\t\t\t\t\t   unsigned flags)\n-{\n-\treturn repo_config_set_multivar_in_file_gently(the_repository, config_filename,\n-\t\t\t\t\t\t       key, value, value_pattern,\n-\t\t\t\t\t\t       comment, flags);\n-}\n-\n void repo_config_set_multivar_in_file(struct repository *r,\n \t\t\t\t      const char *config_filename,\n \t\t\t\t      const char *key, const char *value,\n@@ -3594,21 +3486,6 @@ void repo_config_set_multivar_in_file(struct repository *r,\n \t\tdie(_(\"could not unset '%s'\"), key);\n }\n \n-void git_config_set_multivar_in_file(const char *config_filename,\n-\t\t\t\t     const char *key, const char *value,\n-\t\t\t\t     const char *value_pattern, unsigned flags)\n-{\n-\trepo_config_set_multivar_in_file(the_repository, config_filename,\n-\t\t\t\t\t key, value, value_pattern, flags);\n-}\n-\n-int git_config_set_multivar_gently(const char *key, const char *value,\n-\t\t\t\t   const char *value_pattern, unsigned flags)\n-{\n-\treturn repo_config_set_multivar_gently(the_repository, key, value,\n-\t\t\t\t\t       value_pattern, flags);\n-}\n-\n int repo_config_set_multivar_gently(struct repository *r, const char *key,\n \t\t\t\t    const char *value,\n \t\t\t\t    const char *value_pattern, unsigned flags)\n@@ -3632,13 +3509,6 @@ void repo_config_set_multivar(struct repository *r,\n \tfree(file);\n }\n \n-void git_config_set_multivar(const char *key, const char *value,\n-\t\t\t     const char *value_pattern, unsigned flags)\n-{\n-\trepo_config_set_multivar(the_repository, key, value,\n-\t\t\t\t value_pattern, flags);\n-}\n-\n static size_t section_name_match (const char *buf, const char *name)\n {\n \tsize_t i = 0, j = 0;\ndiff --git a/config.h b/config.h\nindex 589d6dae26..4d319a4193 100644\n--- a/config.h\n+++ b/config.h\n@@ -26,7 +26,7 @@ struct object_id;\n /* git_config_parse_key() returns these negated: */\n #define CONFIG_INVALID_KEY 1\n #define CONFIG_NO_SECTION_OR_NAME 2\n-/* git_config_set_gently(), git_config_set_multivar_gently() return the above or these: */\n+/* repo_config_set_gently(), repo_config_set_multivar_gently() return the above or these: */\n #define CONFIG_NO_LOCK -1\n #define CONFIG_INVALID_FILE 3\n #define CONFIG_NO_WRITE 4\n@@ -170,9 +170,9 @@ int git_default_config(const char *, const char *,\n \n /**\n  * Read a specific file in git-config format.\n- * This function takes the same callback and data parameters as `git_config`.\n+ * This function takes the same callback and data parameters as `repo_config`.\n  *\n- * Unlike git_config(), this function does not respect includes.\n+ * Unlike repo_config(), this function does not respect includes.\n  */\n int git_config_from_file(config_fn_t fn, const char *, void *);\n \n@@ -198,9 +198,9 @@ void read_very_early_config(config_fn_t cb, void *data);\n /**\n  * Most programs will simply want to look up variables in all config files\n  * that Git knows about, using the normal precedence rules. To do this,\n- * call `git_config` with a callback function and void data pointer.\n+ * call `repo_config` with a callback function and void data pointer.\n  *\n- * `git_config` will read all config sources in order of increasing\n+ * `repo_config` will read all config sources in order of increasing\n  * priority. Thus a callback should typically overwrite previously-seen\n  * entries with new ones (e.g., if both the user-wide `~/.gitconfig` and\n  * repo-specific `.git/config` contain `color.ui`, the config machinery\n@@ -210,11 +210,11 @@ void read_very_early_config(config_fn_t cb, void *data);\n  *\n  * Unlike git_config_from_file(), this function respects includes.\n  */\n-void git_config(config_fn_t fn, void *);\n+void repo_config(struct repository *r, config_fn_t fn, void *);\n \n /**\n  * Lets the caller examine config while adjusting some of the default\n- * behavior of `git_config`. It should almost never be used by \"regular\"\n+ * behavior of `repo_config`. It should almost never be used by \"regular\"\n  * Git code that is looking up configuration variables.\n  * It is intended for advanced callers like `git-config`, which are\n  * intentionally tweaking the normal config-lookup process.\n@@ -223,12 +223,12 @@ void git_config(config_fn_t fn, void *);\n  * - `config_source`\n  * If this parameter is non-NULL, it specifies the source to parse for\n  * configuration, rather than looking in the usual files. See `struct\n- * git_config_source` in `config.h` for details. Regular `git_config` defaults\n+ * git_config_source` in `config.h` for details. Regular `repo_config` defaults\n  * to `NULL`.\n  *\n  * - `opts`\n  * Specify options to adjust the behavior of parsing config files. See `struct\n- * config_options` in `config.h` for details. As an example: regular `git_config`\n+ * config_options` in `config.h` for details. As an example: regular `repo_config`\n  * sets `opts.respect_includes` to `1` by default.\n  */\n int config_with_options(config_fn_t fn, void *,\n@@ -297,7 +297,6 @@ int git_config_pathname(char **, const char *, const char *);\n \n int git_config_expiry_date(timestamp_t *, const char *, const char *);\n int git_config_color(char *, const char *, const char *);\n-int git_config_set_in_file_gently(const char *, const char *, const char *, const char *);\n int repo_config_set_in_file_gently(struct repository *r, const char *config_filename,\n \t\t\t\t   const char *key, const char *comment, const char *value);\n \n@@ -305,10 +304,8 @@ int repo_config_set_in_file_gently(struct repository *r, const char *config_file\n  * write config values to a specific config file, takes a key/value pair as\n  * parameter.\n  */\n-void git_config_set_in_file(const char *, const char *, const char *);\n void repo_config_set_in_file(struct repository *, const char *, const char *, const char *);\n \n-int git_config_set_gently(const char *, const char *);\n int repo_config_set_gently(struct repository *r, const char *, const char *);\n \n /**\n@@ -321,14 +318,13 @@ int repo_config_set_worktree_gently(struct repository *, const char *, const cha\n /**\n  * write config values to `.git/config`, takes a key/value pair as parameter.\n  */\n-void git_config_set(const char *, const char *);\n void repo_config_set(struct repository *, const char *, const char *);\n \n int git_config_parse_key(const char *, char **, size_t *);\n \n /*\n  * The following macros specify flag bits that alter the behavior\n- * of the git_config_set_multivar*() methods.\n+ * of the repo_config_set_multivar*() methods.\n  */\n \n /*\n@@ -345,11 +341,8 @@ int git_config_parse_key(const char *, char **, size_t *);\n  */\n #define CONFIG_FLAGS_FIXED_VALUE (1 << 1)\n \n-int git_config_set_multivar_gently(const char *, const char *, const char *, unsigned);\n int repo_config_set_multivar_gently(struct repository *, const char *, const char *, const char *, unsigned);\n-void git_config_set_multivar(const char *, const char *, const char *, unsigned);\n void repo_config_set_multivar(struct repository *r, const char *, const char *, const char *, unsigned);\n-int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, const char *, unsigned);\n int repo_config_set_multivar_in_file_gently(struct repository *, const char *, const char *, const char *, const char *, const char *, unsigned);\n \n char *git_config_prepare_comment_string(const char *);\n@@ -374,11 +367,6 @@ char *git_config_prepare_comment_string(const char *);\n  *\n  * It returns 0 on success.\n  */\n-void git_config_set_multivar_in_file(const char *config_filename,\n-\t\t\t\t     const char *key,\n-\t\t\t\t     const char *value,\n-\t\t\t\t     const char *value_pattern,\n-\t\t\t\t     unsigned flags);\n void repo_config_set_multivar_in_file(struct repository *r,\n \t\t\t\t      const char *config_filename,\n \t\t\t\t      const char *key,\n@@ -563,39 +551,11 @@ int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *i\n int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest);\n int git_configset_get_pathname(struct config_set *cs, const char *key, char **dest);\n \n-/* Functions for reading a repository's config */\n-struct repository;\n-void repo_config(struct repository *repo, config_fn_t fn, void *data);\n-\n /**\n  * Run only the discover part of the repo_config_get_*() functions\n  * below, in addition to 1 if not found, returns negative values on\n  * error (e.g. if the key itself is invalid).\n  */\n-RESULT_MUST_BE_USED\n-int repo_config_get(struct repository *repo, const char *key);\n-int repo_config_get_value(struct repository *repo,\n-\t\t\t  const char *key, const char **value);\n-RESULT_MUST_BE_USED\n-int repo_config_get_value_multi(struct repository *repo, const char *key,\n-\t\t\t\tconst struct string_list **dest);\n-RESULT_MUST_BE_USED\n-int repo_config_get_string_multi(struct repository *repo, const char *key,\n-\t\t\t\t const struct string_list **dest);\n-int repo_config_get_string(struct repository *repo,\n-\t\t\t   const char *key, char **dest);\n-int repo_config_get_string_tmp(struct repository *repo,\n-\t\t\t       const char *key, const char **dest);\n-int repo_config_get_int(struct repository *repo,\n-\t\t\tconst char *key, int *dest);\n-int repo_config_get_ulong(struct repository *repo,\n-\t\t\t  const char *key, unsigned long *dest);\n-int repo_config_get_bool(struct repository *repo,\n-\t\t\t const char *key, int *dest);\n-int repo_config_get_bool_or_int(struct repository *repo,\n-\t\t\t\tconst char *key, int *is_bool, int *dest);\n-int repo_config_get_maybe_bool(struct repository *repo,\n-\t\t\t       const char *key, int *dest);\n int repo_config_get_pathname(struct repository *repo,\n \t\t\t     const char *key, char **dest);\n \n@@ -611,17 +571,17 @@ void git_protected_config(config_fn_t fn, void *data);\n  * -------------------------------\n  *\n  * For programs wanting to query for specific variables in a non-callback\n- * manner, the config API provides two functions `git_config_get_value`\n- * and `git_config_get_value_multi`. They both read values from an internal\n+ * manner, the config API provides two functions `repo_config_get_value`\n+ * and `repo_config_get_value_multi`. They both read values from an internal\n  * cache generated previously from reading the config files.\n  *\n- * For those git_config_get*() functions that aren't documented,\n+ * For those repo_config_get*() functions that aren't documented,\n  * consult the corresponding repo_config_get*() function's\n  * documentation.\n  */\n \n RESULT_MUST_BE_USED\n-int git_config_get(const char *key);\n+int repo_config_get(struct repository *r, const char *key);\n \n /**\n  * Finds the highest-priority value for the configuration variable `key`,\n@@ -630,7 +590,7 @@ int git_config_get(const char *key);\n  * `value`. The caller should not free or modify `value`, as it is owned\n  * by the cache.\n  */\n-int git_config_get_value(const char *key, const char **value);\n+int repo_config_get_value(struct repository *r, const char *key, const char **value);\n \n /**\n  * Finds and returns the value list, sorted in order of increasing priority\n@@ -641,16 +601,15 @@ int git_config_get_value(const char *key, const char **value);\n  * owned by the cache.\n  */\n RESULT_MUST_BE_USED\n-int git_config_get_value_multi(const char *key,\n-\t\t\t       const struct string_list **dest);\n-RESULT_MUST_BE_USED\n-int git_config_get_string_multi(const char *key,\n+int repo_config_get_value_multi(struct repository *r, const char *key,\n \t\t\t\tconst struct string_list **dest);\n+RESULT_MUST_BE_USED\n+int repo_config_get_string_multi(struct repository *r, const char *key,\n+\t\t\t\t const struct string_list **dest);\n \n /**\n  * Resets and invalidates the config cache.\n  */\n-void git_config_clear(void);\n void repo_config_clear(struct repository *repo);\n \n /**\n@@ -659,14 +618,15 @@ void repo_config_clear(struct repository *repo);\n  * error message and returns -1. When the configuration variable `key` is\n  * not found, returns 1 without touching `dest`.\n  */\n-int git_config_get_string(const char *key, char **dest);\n+int repo_config_get_string(struct repository *r, const char *key, char **dest);\n \n /**\n- * Similar to `git_config_get_string`, but does not allocate any new\n+ * Similar to `repo_config_get_string`, but does not allocate any new\n  * memory; on success `dest` will point to memory owned by the config\n  * machinery, which could be invalidated if it is discarded and reloaded.\n  */\n-int git_config_get_string_tmp(const char *key, const char **dest);\n+int repo_config_get_string_tmp(struct repository *r,\n+\t\t\t       const char *key, const char **dest);\n \n /**\n  * Finds and parses the value to an integer for the configuration variable\n@@ -674,12 +634,13 @@ int git_config_get_string_tmp(const char *key, const char **dest);\n  * `dest` and returns 0. When the configuration variable `key` is not found,\n  * returns 1 without touching `dest`.\n  */\n-int git_config_get_int(const char *key, int *dest);\n+int repo_config_get_int(struct repository *r, const char *key, int *dest);\n \n /**\n- * Similar to `git_config_get_int` but for unsigned longs.\n+ * Similar to `repo_config_get_int` but for unsigned longs.\n  */\n-int git_config_get_ulong(const char *key, unsigned long *dest);\n+int repo_config_get_ulong(struct repository *r,\n+\t\t\t  const char *key, unsigned long *dest);\n \n /**\n  * Finds and parses the value into a boolean value, for the configuration\n@@ -690,25 +651,21 @@ int git_config_get_ulong(const char *key, unsigned long *dest);\n  * configuration variable `key` is not found, returns 1 without touching\n  * `dest`.\n  */\n-int git_config_get_bool(const char *key, int *dest);\n+int repo_config_get_bool(struct repository *r, const char *key, int *dest);\n \n /**\n- * Similar to `git_config_get_bool`, except that integers are copied as-is,\n+ * Similar to `repo_config_get_bool`, except that integers are copied as-is,\n  * and `is_bool` flag is unset.\n  */\n-int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);\n+int repo_config_get_bool_or_int(struct repository *r, const char *key,\n+\t\t\t\tint *is_bool, int *dest);\n \n /**\n- * Similar to `git_config_get_bool`, except that it returns -1 on error\n+ * Similar to `repo_config_get_bool`, except that it returns -1 on error\n  * rather than dying.\n  */\n-int git_config_get_maybe_bool(const char *key, int *dest);\n-\n-/**\n- * Similar to `git_config_get_string`, but expands `~` or `~user` into\n- * the user's home directory when found at the beginning of the path.\n- */\n-int git_config_get_pathname(const char *key, char **dest);\n+int repo_config_get_maybe_bool(struct repository *r,\n+\t\t\t      const char *key, int *dest);\n \n int repo_config_get_index_threads(struct repository *r, int *dest);\n int repo_config_get_split_index(struct repository *r);\n@@ -732,7 +689,7 @@ NORETURN void git_die_config(struct repository *r, const char *key, const char *\n /**\n  * Helper function which formats the die error message according to the\n  * parameters entered. Used by `git_die_config()`. It can be used by callers\n- * handling `git_config_get_value_multi()` to print the correct error message\n+ * handling `repo_config_get_value_multi()` to print the correct error message\n  * for the desired value.\n  */\n NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr);\n@@ -741,4 +698,140 @@ NORETURN void git_die_config_linenr(const char *key, const char *filename, int l\n \tlookup_config(mapping, ARRAY_SIZE(mapping), var)\n int lookup_config(const char **mapping, int nr_mapping, const char *var);\n \n+# ifdef USE_THE_REPOSITORY_VARIABLE\n+static inline void git_config(config_fn_t fn, void *data)\n+{\n+\trepo_config(the_repository, fn, data);\n+}\n+\n+static inline void git_config_clear(void)\n+{\n+\trepo_config_clear(the_repository);\n+}\n+\n+static inline int git_config_get(const char *key)\n+{\n+\treturn repo_config_get(the_repository, key);\n+}\n+\n+static inline int git_config_get_value(const char *key, const char **value)\n+{\n+\treturn repo_config_get_value(the_repository, key, value);\n+}\n+\n+static inline int git_config_get_value_multi(const char *key, const struct string_list **dest)\n+{\n+\treturn repo_config_get_value_multi(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_string_multi(const char *key,\n+\t\t\t\tconst struct string_list **dest)\n+{\n+\treturn repo_config_get_string_multi(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_string(const char *key, char **dest)\n+{\n+\treturn repo_config_get_string(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_string_tmp(const char *key, const char **dest)\n+{\n+\treturn repo_config_get_string_tmp(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_int(const char *key, int *dest)\n+{\n+\treturn repo_config_get_int(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_ulong(const char *key, unsigned long *dest)\n+{\n+\treturn repo_config_get_ulong(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_bool(const char *key, int *dest)\n+{\n+\treturn repo_config_get_bool(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest)\n+{\n+\treturn repo_config_get_bool_or_int(the_repository, key, is_bool, dest);\n+}\n+\n+static inline int git_config_get_maybe_bool(const char *key, int *dest)\n+{\n+\treturn repo_config_get_maybe_bool(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_pathname(const char *key, char **dest)\n+{\n+\treturn repo_config_get_pathname(the_repository, key, dest);\n+}\n+\n+static inline void git_config_set_in_file(const char *config_filename,\n+\t\t\t\t\t  const char *key, const char *value)\n+{\n+\trepo_config_set_in_file(the_repository, config_filename, key, value);\n+}\n+\n+static inline int git_config_set_gently(const char *key, const char *value)\n+{\n+\treturn repo_config_set_gently(the_repository, key, value);\n+}\n+\n+static inline void git_config_set(const char *key, const char *value)\n+{\n+\trepo_config_set(the_repository, key, value);\n+}\n+\n+static inline int git_config_set_in_file_gently(\n+\tconst char *config_filename,\n+\tconst char *key,\n+\tconst char *comment,\n+\tconst char *value)\n+{\n+\treturn repo_config_set_in_file_gently(the_repository, config_filename,\n+\t\t\t\t\t      key, comment, value);\n+}\n+\n+static inline int git_config_set_multivar_in_file_gently(\n+\tconst char *config_filename,\n+\tconst char *key, const char *value,\n+\tconst char *value_pattern,\n+\tconst char *comment,\n+\tunsigned flags)\n+{\n+\treturn repo_config_set_multivar_in_file_gently(the_repository, config_filename,\n+\t\t\t\t\t\t       key, value, value_pattern,\n+\t\t\t\t\t\t       comment, flags);\n+}\n+\n+static inline void git_config_set_multivar_in_file(\n+\tconst char *config_filename,\n+\tconst char *key,\n+\tconst char *value,\n+\tconst char *value_pattern,\n+\tunsigned flags)\n+{\n+\trepo_config_set_multivar_in_file(the_repository, config_filename,\n+\t\t\t\t\t key, value, value_pattern, flags);\n+}\n+\n+static inline int git_config_set_multivar_gently(const char *key, const char *value,\n+\t\t\t\t   const char *value_pattern, unsigned flags)\n+{\n+\treturn repo_config_set_multivar_gently(the_repository, key, value,\n+\t\t\t\t\t       value_pattern, flags);\n+}\n+\n+static inline void git_config_set_multivar(const char *key, const char *value,\n+\t\t\t     const char *value_pattern, unsigned flags)\n+{\n+\trepo_config_set_multivar(the_repository, key, value,\n+\t\t\t\t value_pattern, flags);\n+}\n+# endif /* USE_THE_REPOSITORY_VARIABLE */\n+\n #endif /* CONFIG_H */\n-- \n2.46.0.dirty\n\n"},{"id":"500302","messageId":"D39L2L3K6I94.3JFA6EEDPYNQC@gmail.com","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"Re: [PATCH 00/20] Stop using `the_repository` in \"config.c\"","fromName":"Ghanshyam Thakkar","fromEmail":"shyamthakkar001@gmail.com","sentAt":"2024-08-07T09:48:30Z","receivedAt":"2024-08-07T09:48:35Z","isPatch":true,"sender":{"key":"shyamthakkar001@gmail.com","avatar":"https://avatars.githubusercontent.com/u/72698233?v=4"},"body":"Patrick Steinhardt <ps@pks.im> wrote:\n> Hi,\n>\n> I found that there had been a bunch of callsites in code\n> not marked with `USE_THE_REPOSITORY_VARIABLE` that still implicitly\n> relied on `the_repository` due to calling interfaces of \"config.c\".\n> This patch series has the goal of fixing that and making the dependency\n> implicit.\n\ndid you mean 'making the dependency explicit'?\n\nThanks.\n"},{"id":"500321","messageId":"ZrNyh_2Gl6Eqi18u@tanuki","threadId":"61914","inReplyTo":"D39L2L3K6I94.3JFA6EEDPYNQC@gmail.com","subject":"Re: [PATCH 00/20] Stop using `the_repository` in \"config.c\"","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-07T13:11:35Z","receivedAt":"2024-08-07T13:11:40Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Aug 07, 2024 at 03:18:30PM +0530, Ghanshyam Thakkar wrote:\n> Patrick Steinhardt <ps@pks.im> wrote:\n> > Hi,\n> >\n> > I found that there had been a bunch of callsites in code\n> > not marked with `USE_THE_REPOSITORY_VARIABLE` that still implicitly\n> > relied on `the_repository` due to calling interfaces of \"config.c\".\n> > This patch series has the goal of fixing that and making the dependency\n> > implicit.\n> \n> did you mean 'making the dependency explicit'?\n\nD'oh, of course. Thanks!\n\nPatrick\n"},{"id":"500549","messageId":"xl37sjpibmamkxdmpvfy44sijseuk5doizdlbnuodnbd6pdhxj@dws5e4wdu5lg","threadId":"61914","inReplyTo":"7ce3278f649ce70453242e5458d28c5fd54576ba.1723013714.git.ps@pks.im","subject":"Re: [PATCH 01/20] path: expose `do_git_path()` as `repo_git_pathv()`","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-09T16:58:31Z","receivedAt":"2024-08-09T16:59:20Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/07 08:56AM, Patrick Steinhardt wrote:\n> We're about to move functions of the \"path\" subsytem that do not use a\n\ns/subsytem/subsystem/\n\n> `struct repository` into \"path.h\" as static inlined functions. This will\n> require us to call `do_git_path()`, which is internal to \"path.c\".\n\nSo in other words, functions leveraging `the_repository` in \"path.c\" are\ngoing to be moved to \"path.h\". Since these functions depend on\n`do_git_path()`, we need to expose it. Makes sense so far.\n\n> Expose the function as `repo_git_pathv()` to prepare for the change.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n[snip]\n> +/*\n> + * Print a path into the git directory of repository `repo` into the provided\n> + * buffer.\n> + */\n> +void repo_git_pathv(const struct repository *repo,\n> +\t\t    const struct worktree *wt, struct strbuf *buf,\n> +\t\t    const char *fmt, va_list args);\n> +\n\nOut of curiousity, do we have a preferred convention for how functions\naccepting `va_list` are named? Searching through the codebase, I don't\nsee a ton of consistency, but I have noticed examples prefixed with \"v\".\n"},{"id":"500552","messageId":"ytv7y3jlbaru5o3ehotanqoqvjnwaomzsyj746k3hbb3htymts@m4qct6cvebiz","threadId":"61914","inReplyTo":"e7a143c30dd95d8192eacc35c876e7926cb7c6a4.1723013714.git.ps@pks.im","subject":"Re: [PATCH 02/20] path: expose `do_git_common_path()` as `strbuf_git_common_pathv()`","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-09T17:18:12Z","receivedAt":"2024-08-09T17:19:00Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/07 08:56AM, Patrick Steinhardt wrote:\n> With the same reasoning as the preceding commit, expose the function\n> `do_git_common_path()` as `strbuf_git_common_pathv()`.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  path.c | 22 +++++++++++-----------\n>  path.h |  5 ++++-\n>  2 files changed, 15 insertions(+), 12 deletions(-)\n> \n> diff --git a/path.c b/path.c\n> index 71f1cb4dfb..bff98b255e 100644\n> --- a/path.c\n> +++ b/path.c\n> @@ -617,16 +617,16 @@ int strbuf_git_path_submodule(struct strbuf *buf, const char *path,\n>  \treturn err;\n>  }\n>  \n> -static void do_git_common_path(const struct repository *repo,\n> -\t\t\t       struct strbuf *buf,\n> -\t\t\t       const char *fmt,\n> -\t\t\t       va_list args)\n> +void strbuf_git_common_pathv(struct strbuf *sb,\n> +\t\t\t     const struct repository *repo,\n> +\t\t\t     const char *fmt,\n> +\t\t\t     va_list args)\n\nHere we reorder the arguments to make `strbuf` first. I assume we are do\nthis to align with the preexisting `strbuf_git_common_path()` and use\nthe \"strbuf_\" prefix in the function name.\n\nIn the previous commit we used the \"repo_\" prefix for\n`repo_git_pathv()`. Would it make sense to be consistent here? All these\nfunctions are operating on the provided buffer, but for a given\nrepository. Not sure what would be most appropriate here.\n\n>  {\n> -\tstrbuf_addstr(buf, repo->commondir);\n> -\tif (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))\n> -\t\tstrbuf_addch(buf, '/');\n> -\tstrbuf_vaddf(buf, fmt, args);\n> -\tstrbuf_cleanup_path(buf);\n> +\tstrbuf_addstr(sb, repo->commondir);\n> +\tif (sb->len && !is_dir_sep(sb->buf[sb->len - 1]))\n> +\t\tstrbuf_addch(sb, '/');\n> +\tstrbuf_vaddf(sb, fmt, args);\n> +\tstrbuf_cleanup_path(sb);\n>  }\n"},{"id":"500553","messageId":"xmqq5xs9eh4p.fsf@gitster.g","threadId":"61914","inReplyTo":"ytv7y3jlbaru5o3ehotanqoqvjnwaomzsyj746k3hbb3htymts@m4qct6cvebiz","subject":"Re: [PATCH 02/20] path: expose `do_git_common_path()` as `strbuf_git_common_pathv()`","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-09T17:32:54Z","receivedAt":"2024-08-09T17:32:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Justin Tobler <jltobler@gmail.com> writes:\n\n>> -static void do_git_common_path(const struct repository *repo,\n>> -\t\t\t       struct strbuf *buf,\n>> -\t\t\t       const char *fmt,\n>> -\t\t\t       va_list args)\n>> +void strbuf_git_common_pathv(struct strbuf *sb,\n>> +\t\t\t     const struct repository *repo,\n>> +\t\t\t     const char *fmt,\n>> +\t\t\t     va_list args)\n>\n> Here we reorder the arguments to make `strbuf` first. I assume we are do\n> this to align with the preexisting `strbuf_git_common_path()` and use\n> the \"strbuf_\" prefix in the function name.\n\nI thought that we already established as a general guideline that\n\"strbuf_\" should be cleaned up so that functions that happen to use\nstrbuf merely as a way to carry parameters into or results out of\nthem but are not primarily about string manipulation are renamed out\nof the \"strbuf_\" namespace.\n\n  https://lore.kernel.org/git/ZqiLA0bGYZfH1OWD@tanuki/\n\nAnd this is about getting a path, which is communicated via a\n\"struct strbuf\", and not the standard \"char *\".  That is a prime\nexample of a function that we do *not* want to stress strbuf-ness\nof the function.\n\n> In the previous commit we used the \"repo_\" prefix for\n> `repo_git_pathv()`. Would it make sense to be consistent here? All these\n> functions are operating on the provided buffer, but for a given\n> repository. Not sure what would be most appropriate here.\n\nYes, if the function is about obtaining the path for a file in a\ngiven repository's metadata directory, and its association with\n\"strbuf\" is that it merely happens to use it instead of \"char *\",\nit should not be named as if \"strbuf_\" ness is the primary\ncharacteristics of the function.\n\nstrbuf_cleanup_path() should also be renamed for the same reason.\n\n>>  {\n>> -\tstrbuf_addstr(buf, repo->commondir);\n>> -\tif (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))\n>> -\t\tstrbuf_addch(buf, '/');\n>> -\tstrbuf_vaddf(buf, fmt, args);\n>> -\tstrbuf_cleanup_path(buf);\n>> +\tstrbuf_addstr(sb, repo->commondir);\n>> +\tif (sb->len && !is_dir_sep(sb->buf[sb->len - 1]))\n>> +\t\tstrbuf_addch(sb, '/');\n>> +\tstrbuf_vaddf(sb, fmt, args);\n>> +\tstrbuf_cleanup_path(sb);\n>>  }\n"},{"id":"500554","messageId":"zvkqwebiqktmpsithuf5bf2ugwpwfzi5jc2wpk53ewz4nlns4r@kdbzz4hmuhjk","threadId":"61914","inReplyTo":"c2556fff9e25aabab237c5902aff64f65b0a953f.1723013714.git.ps@pks.im","subject":"Re: [PATCH 03/20] editor: do not rely on `the_repository` for interactive edits","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-09T17:36:41Z","receivedAt":"2024-08-09T17:37:30Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/07 08:56AM, Patrick Steinhardt wrote:\n> We implicitly rely on `the_repository` when editing a file interactively\n> because we call `git_path()`. Adapt the function to instead take a\n> `sturct repository` as parameter so that we can remove this hidden\n\ns/sturct/struct/\ns/parameter/a parameter/\n\n> dependency.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  add-patch.c |  3 ++-\n>  editor.c    | 12 +++++++-----\n>  editor.h    |  3 ++-\n>  3 files changed, 11 insertions(+), 7 deletions(-)\n> \n> diff --git a/add-patch.c b/add-patch.c\n> index 46f6bddfe5..4e3aa02ed8 100644\n> --- a/add-patch.c\n> +++ b/add-patch.c\n> @@ -1140,7 +1140,8 @@ static int edit_hunk_manually(struct add_p_state *s, struct hunk *hunk)\n>  \t\t\t\t\"removed, then the edit is\\n\"\n>  \t\t\t\t\"aborted and the hunk is left unchanged.\\n\"));\n>  \n> -\tif (strbuf_edit_interactively(&s->buf, \"addp-hunk-edit.diff\", NULL) < 0)\n> +\tif (strbuf_edit_interactively(&s->buf, \"addp-hunk-edit.diff\", NULL,\n> +\t\t\t\t      the_repository) < 0)\n>  \t\treturn -1;\n>  \n>  \t/* strip out commented lines */\n> diff --git a/editor.c b/editor.c\n> index d1ba2d7c34..6c461dd253 100644\n> --- a/editor.c\n> +++ b/editor.c\n> @@ -134,13 +134,15 @@ int launch_sequence_editor(const char *path, struct strbuf *buffer,\n>  }\n>  \n>  int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n> -\t\t\t      const char *const *env)\n> +\t\t\t      const char *const *env, struct repository *r)\n>  {\n> -\tchar *path2 = NULL;\n> +\tstruct strbuf sb = STRBUF_INIT;\n>  \tint fd, res = 0;\n>  \n> -\tif (!is_absolute_path(path))\n> -\t\tpath = path2 = xstrdup(git_path(\"%s\", path));\n> +\tif (!is_absolute_path(path)) {\n> +\t\tstrbuf_repo_git_path(&sb, r, \"%s\", path);\n> +\t\tpath = sb.buf;\n> +\t}\n\nBy switching from `git_path()` to `strbuf_repo_git_path()`,\n`strbuf_edit_interactively()` no longer implicitly depends on\n`the_repository`. This requires a `struct repository` be injected into\n`strbuf_edit_interactively()`. The function signature is updated along\nwith the single call site. The small cleanup also looks good. Makes\nsense to me.\n\nNon-blocking: Instead of appending `struct repository` as the last\nargument, it might be nicer to match `strbuf_repo_git_path()` and place\nit as the second argument.\n\n>  \tfd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);\n>  \tif (fd < 0)\n> @@ -157,6 +159,6 @@ int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n>  \t\tunlink(path);\n>  \t}\n>  \n> -\tfree(path2);\n> +\tstrbuf_release(&sb);\n>  \treturn res;\n>  }\n> diff --git a/editor.h b/editor.h\n> index 8016bb5e00..d4c4d216ac 100644\n> --- a/editor.h\n> +++ b/editor.h\n> @@ -1,6 +1,7 @@\n>  #ifndef EDITOR_H\n>  #define EDITOR_H\n>  \n> +struct repository;\n>  struct strbuf;\n>  \n>  const char *git_editor(void);\n> @@ -29,6 +30,6 @@ int launch_sequence_editor(const char *path, struct strbuf *buffer,\n>   * If `path` is relative, it refers to a file in the `.git` directory.\n>   */\n>  int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n> -\t\t\t      const char *const *env);\n> +\t\t\t      const char *const *env, struct repository *r);\n>  \n>  #endif\n> -- \n> 2.46.0.dirty\n> \n\n\n"},{"id":"500557","messageId":"cqc4xlbrusu5edfsh2snvekkd2qfwjxu3x33pzizp22rsuidbw@pz4e3fsqfhgv","threadId":"61914","inReplyTo":"67405dcd0a121aee971f854dc35ba89bd4f808c4.1723013714.git.ps@pks.im","subject":"Re: [PATCH 06/20] path: stop relying on `the_repository` in `worktree_git_path()`","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-09T19:02:21Z","receivedAt":"2024-08-09T19:03:09Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/07 08:57AM, Patrick Steinhardt wrote:\n> When not provided a worktree, then `worktree_git_path()` will fall back\n> to returning a path relative to the main repository. In this case, we\n> implicitly rely on `the_repository` to derive the path. Remove this\n> dependency by passing a `struct repository` as parameter.\n\nAre there many situations where `worktree_git_path()` would expect to\nnot be provided a worktree? I wonder whether this implicit behavior is\nreally necessary to begin with.\n\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n[snip] \n> -const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)\n> +const char *worktree_git_path(struct repository *r,\n> +\t\t\t      const struct worktree *wt, const char *fmt, ...)\n>  {\n>  \tstruct strbuf *pathname = get_pathname();\n>  \tva_list args;\n> +\n> +\tif (wt && wt->repo != r)\n> +\t\tBUG(\"worktree not connected to expected repository\");\n\nSo if we receive a worktree, we expect that it should always match the\nmain repostiory. Makes sense.\n\n> +\n>  \tva_start(args, fmt);\n> -\trepo_git_pathv(the_repository, wt, pathname, fmt, args);\n> +\trepo_git_pathv(r, wt, pathname, fmt, args);\n>  \tva_end(args);\n>  \treturn pathname->buf;\n>  }\n> diff --git a/path.h b/path.h\n> index 3d21b9cd16..6228ca03d7 100644\n> --- a/path.h\n> +++ b/path.h\n> @@ -97,9 +97,10 @@ const char *git_path(const char *fmt, ...)\n>   * Similar to git_path() but can produce paths for a specified\n>   * worktree instead of current one\n>   */\n\nNow that the previously implicit behavior is more explicit, it might be\nupdate the comment to explain that the provided repository is used as a\nfallback.\n\n> -const char *worktree_git_path(const struct worktree *wt,\n> +const char *worktree_git_path(struct repository *r,\n> +\t\t\t      const struct worktree *wt,\n>  \t\t\t      const char *fmt, ...)\n> -\t__attribute__((format (printf, 2, 3)));\n> +\t__attribute__((format (printf, 3, 4)));\n\nOverall, I quite like how this series is bubbling up `the_repository`\nusages from the bottom up. :)\n"},{"id":"500565","messageId":"mc4omj4mi23fhmqp4xeafcluzf2iidp4uaf3h3gaxcalm3igvk@a7abzjynshfw","threadId":"61914","inReplyTo":"b4e973a2804ba09149224a2e18a359717228607e.1723013714.git.ps@pks.im","subject":"Re: [PATCH 07/20] path: hide functions using `the_repository` by default","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-09T19:43:59Z","receivedAt":"2024-08-09T19:44:48Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/07 08:57AM, Patrick Steinhardt wrote:\n> The path subsytem provides a bunch of legacy functions that compute\n\ns/subsytem/subsystem/\n\n> paths relative to the \"gitdir\" and \"commondir\" directories of the global\n> `the_repository` variable. Use of those functions is discouraged, and it\n> is easy to miss the implicit dependency on `the_repository` that calls\n> to those functions may cause.\n> \n> With `USE_THE_REPOSITORY_VARIABLE`, we have recently introduced a tool\n> that allows us to get rid of such functions over time. With this define,\n\ns/define/defined/\n\n> we can hide away functions that have such implicit dependency such that\n> other subsystems that want to be free of `the_repository` will not use\n> them by accident.\n> \n> Move all path-related functions that use `the_repository` into a block\n> that gets only conditionally compiled depending on whether or not the\n> macro has been defined. This also removes all dependencies on that\n> variable in \"path.c\", allowing us to remove the definition of said\n> preprocessor macro.\n\nNice! So now the \"path.c\" is `the_repository` free. Implicit use of\n`the_repository` is guarded behind `USE_THE_REPOSITORY_VARIABLE`. This\nis quite neat. :)\n\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  path.c |  52 +-------------------\n>  path.h | 147 ++++++++++++++++++++++++++++++++++++++-------------------\n>  2 files changed, 100 insertions(+), 99 deletions(-)\n> \n> diff --git a/path.c b/path.c\n> index 567eff5253..d073ae6449 100644\n> --- a/path.c\n> +++ b/path.c\n> @@ -2,8 +2,6 @@\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\"\n> @@ -30,7 +28,7 @@ static int get_st_mode_bits(const char *path, int *mode)\n>  \treturn 0;\n>  }\n>  \n> -static struct strbuf *get_pathname(void)\n> +struct strbuf *get_pathname(void)\n\nNow that functions with implicit `the_repository` usage are static\ninlined we are required to expose `get_pathname()` for the same reason\nas some of the other functions in previous commits.\n\n[snip]\n> +# ifdef USE_THE_REPOSITORY_VARIABLE\n> +#  include \"strbuf.h\"\n> +#  include \"repository.h\"\n\nNaive question, what is the purpose of providing the include statements\nhere? Wouldn't they always already be included?\n\n> +\n> +/*\n> + * Return a statically allocated path into the main repository's\n> + * (the_repository) common git directory.\n> + */\n> +__attribute__((format (printf, 1, 2)))\n> +static inline const char *git_common_path(const char *fmt, ...)\n> +{\n> +\tstruct strbuf *pathname = get_pathname();\n> +\tva_list args;\n> +\tva_start(args, fmt);\n> +\tstrbuf_git_common_pathv(pathname, the_repository, fmt, args);\n> +\tva_end(args);\n> +\treturn pathname->buf;\n> +}\n> +\n> +/*\n> + * Construct a path into the main repository's (the_repository) git directory\n> + * and place it in the provided buffer `buf`, the contents of the buffer will\n> + * be overridden.\n> + */\n> +__attribute__((format (printf, 2, 3)))\n> +static inline char *git_path_buf(struct strbuf *buf, const char *fmt, ...)\n> +{\n> +\tva_list args;\n> +\tstrbuf_reset(buf);\n> +\tva_start(args, fmt);\n> +\trepo_git_pathv(the_repository, NULL, buf, fmt, args);\n> +\tva_end(args);\n> +\treturn buf->buf;\n> +}\n> +\n> +/*\n> + * Construct a path into the main repository's (the_repository) git directory\n> + * and append it to the provided buffer `sb`.\n> + */\n> +__attribute__((format (printf, 2, 3)))\n> +static inline void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)\n> +{\n> +\tva_list args;\n> +\tva_start(args, fmt);\n> +\trepo_git_pathv(the_repository, NULL, sb, fmt, args);\n> +\tva_end(args);\n> +}\n> +\n> +/*\n> + * Return a statically allocated path into the main repository's\n> + * (the_repository) git directory.\n> + */\n> +__attribute__((format (printf, 1, 2)))\n> +static inline const char *git_path(const char *fmt, ...)\n> +{\n> +\tstruct strbuf *pathname = get_pathname();\n> +\tva_list args;\n> +\tva_start(args, fmt);\n> +\trepo_git_pathv(the_repository, NULL, pathname, fmt, args);\n> +\tva_end(args);\n> +\treturn pathname->buf;\n> +}\n> +\n> +#define GIT_PATH_FUNC(func, filename) \\\n> +\tconst char *func(void) \\\n> +\t{ \\\n> +\t\tstatic char *ret; \\\n> +\t\tif (!ret) \\\n> +\t\t\tret = git_pathdup(filename); \\\n> +\t\treturn ret; \\\n> +\t}\n> +\n> +/*\n> + * Return a path into the main repository's (the_repository) git directory.\n> + */\n> +__attribute__((format (printf, 1, 2)))\n> +static inline char *git_pathdup(const char *fmt, ...)\n> +{\n> +\tstruct strbuf path = STRBUF_INIT;\n> +\tva_list args;\n> +\tva_start(args, fmt);\n> +\trepo_git_pathv(the_repository, NULL, &path, fmt, args);\n> +\tva_end(args);\n> +\treturn strbuf_detach(&path, NULL);\n> +}\n> +\n> +# endif /* USE_THE_REPOSITORY_VARIABLE */\n\nI like how it's all consolidated into this one block. Very nice! :)\n"},{"id":"500568","messageId":"rg5j5ehur5a2qvpt65ezfub5dmmqrbn7if5f2r7ibweuupsnm2@qeciml3qvdvy","threadId":"61914","inReplyTo":"feae2ad31ac91baae75c46c22c5c3ef3b58c1897.1723013714.git.ps@pks.im","subject":"Re: [PATCH 08/20] config: introduce missing setters that take repo as parameter","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-09T20:07:37Z","receivedAt":"2024-08-09T20:08:26Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/07 08:57AM, Patrick Steinhardt wrote:\n> While we already provide some of the config-setting interfaces with a\n> `struct repository` as parameter, others only have a variant that\n> implicitly depend on `the_repository`. Fill in those gaps such that we\n\ns/depend/depends/\n\n> can start to deprecate the repo-less variants.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  config.c | 93 ++++++++++++++++++++++++++++++++++++++++++++------------\n>  config.h | 15 ++++++++-\n>  2 files changed, 87 insertions(+), 21 deletions(-)\n> \n> diff --git a/config.c b/config.c\n> index 6421894614..ac89b708e7 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -3178,21 +3178,39 @@ static void maybe_remove_section(struct config_store_data *store,\n>  \t\t*end_offset = store->parsed[store->parsed_nr - 1].end;\n>  }\n>  \n> +int repo_config_set_in_file_gently(struct repository *r, const char *config_filename,\n> +\t\t\t\t   const char *key, const char *comment, const char *value)\n\nInstead of prefixing with `repo_`, should we instead use the `config_`\nprefix? Maybe `config_repo_`? It might be nice for names to align with\nthe config subsystem here.\n\n[snip]\n> diff --git a/config.h b/config.h\n> index 54b47dec9e..b13e1bfb8d 100644\n> --- a/config.h\n> +++ b/config.h\n> @@ -298,14 +298,18 @@ int git_config_pathname(char **, const char *, const char *);\n>  int git_config_expiry_date(timestamp_t *, const char *, const char *);\n>  int git_config_color(char *, const char *, const char *);\n>  int git_config_set_in_file_gently(const char *, const char *, const char *, const char *);\n> +int repo_config_set_in_file_gently(struct repository *r, const char *config_filename,\n> +\t\t\t\t   const char *key, const char *comment, const char *value);\n>  \n>  /**\n>   * write config values to a specific config file, takes a key/value pair as\n>   * parameter.\n>   */\n>  void git_config_set_in_file(const char *, const char *, const char *);\n> +void repo_config_set_in_file(struct repository *, const char *, const char *, const char *);\n>  \n>  int git_config_set_gently(const char *, const char *);\n> +int repo_config_set_gently(struct repository *r, const char *, const char *);\n>  \n>  /**\n>   * Write a config value that should apply to the current worktree. If\n> @@ -318,6 +322,7 @@ int repo_config_set_worktree_gently(struct repository *, const char *, const cha\n>   * write config values to `.git/config`, takes a key/value pair as parameter.\n>   */\n>  void git_config_set(const char *, const char *);\n> +void repo_config_set(struct repository *, const char *, const char *);\n>  \n>  int git_config_parse_key(const char *, char **, size_t *);\n>  \n> @@ -341,9 +346,11 @@ int git_config_parse_key(const char *, char **, size_t *);\n>  #define CONFIG_FLAGS_FIXED_VALUE (1 << 1)\n>  \n>  int git_config_set_multivar_gently(const char *, const char *, const char *, unsigned);\n> -void git_config_set_multivar(const char *, const char *, const char *, unsigned);\n>  int repo_config_set_multivar_gently(struct repository *, const char *, const char *, const char *, unsigned);\n> +void git_config_set_multivar(const char *, const char *, const char *, unsigned);\n> +void repo_config_set_multivar(struct repository *r, const char *, const char *, const char *, unsigned);\n>  int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, const char *, unsigned);\n> +int repo_config_set_multivar_in_file_gently(struct repository *, const char *, const char *, const char *, const char *, const char *, unsigned);\n>  \n>  char *git_config_prepare_comment_string(const char *);\n>  \n> @@ -372,6 +379,12 @@ void git_config_set_multivar_in_file(const char *config_filename,\n>  \t\t\t\t     const char *value,\n>  \t\t\t\t     const char *value_pattern,\n>  \t\t\t\t     unsigned flags);\n> +void repo_config_set_multivar_in_file(struct repository *r,\n> +\t\t\t\t      const char *config_filename,\n> +\t\t\t\t      const char *key,\n> +\t\t\t\t      const char *value,\n> +\t\t\t\t      const char *value_pattern,\n> +\t\t\t\t      unsigned flags);\n>  \n>  /**\n>   * rename or remove sections in the config file\n\nThe rest of this patch is simply implementing variations of existing\nfunctions that explicitly inject a repository and looks good to me.\n"},{"id":"500569","messageId":"qo26pmkrctepcob4vjfimvxlgoic7gqjxasnz2hqmv4hpgc37t@jh5wo2fjqyoo","threadId":"61914","inReplyTo":"cf7942479f75d95dcd8606b0947a8897ae60da60.1723013714.git.ps@pks.im","subject":"Re: [PATCH 14/20] config: pass repo to `git_config_get_expiry_in_days()`","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-09T20:21:18Z","receivedAt":"2024-08-09T20:22:06Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/07 08:57AM, Patrick Steinhardt wrote:\n> Refactor `git_config_get_expiry_in_days()` to accept a `struct\n> repository` such that we can get rid of the implicit dependency on\n> `the_repository`. Rename the function accordingly.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n[snip]\n> -\tgit_config_get_expiry_in_days(\"gc.rerereresolved\", &cutoff_resolve, now);\n> -\tgit_config_get_expiry_in_days(\"gc.rerereunresolved\", &cutoff_noresolve, now);\n> +\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereresolved\", &cutoff_resolve, now);\n> +\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereunresolved\", &cutoff_noresolve, now);\n\nnon-blocking: Do we want to fold these lines?\n\n>  \tgit_config(git_default_config, NULL);\n>  \tdir = opendir(git_path(\"rr-cache\"));\n>  \tif (!dir)\n"},{"id":"500570","messageId":"unahz22fciepxsgt74jdk63i3yminzjwsdqee3ti5mrii2cz3s@jf6ussbyx637","threadId":"61914","inReplyTo":"d8530a300b4cf0f854f2b0d03c79876c11d81116.1723013714.git.ps@pks.im","subject":"Re: [PATCH 18/20] config: don't depend on `the_repository` with branch conditions","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-09T20:47:50Z","receivedAt":"2024-08-09T20:48:39Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/07 08:58AM, Patrick Steinhardt wrote:\n> When computing branch \"includeIf\" conditions we use `the_repository` to\n> obtain the main ref store. We really shouldn't depend on this global\n> repository though, but should instead use the repository that is being\n> passed to us via `struct config_include_data`. Otherwise, when parsing\n> configuration of e.g. submodules, we may end up evaluating the condition\n> the via the wrong refdb.\n> \n> Fix this.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  config.c | 9 +++++----\n>  1 file changed, 5 insertions(+), 4 deletions(-)\n> \n> diff --git a/config.c b/config.c\n> index 831c9eacb0..08437f75e5 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -300,13 +300,14 @@ static int include_by_gitdir(const struct key_value_info *kvi,\n>  \treturn ret;\n>  }\n>  \n> -static int include_by_branch(const char *cond, size_t cond_len)\n> +static int include_by_branch(struct config_include_data *data,\n> +\t\t\t     const char *cond, size_t cond_len)\n>  {\n>  \tint flags;\n>  \tint ret;\n>  \tstruct strbuf pattern = STRBUF_INIT;\n> -\tconst char *refname = !the_repository->gitdir ?\n> -\t\tNULL : refs_resolve_ref_unsafe(get_main_ref_store(the_repository),\n> +\tconst char *refname = (!data->repo || !data->repo->gitdir) ?\n> +\t\tNULL : refs_resolve_ref_unsafe(get_main_ref_store(data->repo),\n>  \t\t\t\t\t       \"HEAD\", 0, NULL, &flags);\n>  \tconst char *shortname;\n\nThis works the same so long as `config_include_data` always has its\nrepository set. I wonder if for `!data->repo` we should instead signal a\nBUG? Otherwise we would silently return NULL in such cases. Maybe that\nwould be the desired behavior though?\n\n>  \n> @@ -406,7 +407,7 @@ static int include_condition_is_true(const struct key_value_info *kvi,\n>  \telse if (skip_prefix_mem(cond, cond_len, \"gitdir/i:\", &cond, &cond_len))\n>  \t\treturn include_by_gitdir(kvi, opts, cond, cond_len, 1);\n>  \telse if (skip_prefix_mem(cond, cond_len, \"onbranch:\", &cond, &cond_len))\n> -\t\treturn include_by_branch(cond, cond_len);\n> +\t\treturn include_by_branch(inc, cond, cond_len);\n>  \telse if (skip_prefix_mem(cond, cond_len, \"hasconfig:remote.*.url:\", &cond,\n>  \t\t\t\t   &cond_len))\n>  \t\treturn include_by_remote_url(inc, cond, cond_len);\n> -- \n> 2.46.0.dirty\n> \n\n\n"},{"id":"500572","messageId":"j6litzbor4sz7pycfh7wf5fmejidf5s75sbw3xgrpuwnroyvh6@kkydoqh47bjm","threadId":"61914","inReplyTo":"f7617beaa5aad64fe98ac52015eb68786114728b.1723013714.git.ps@pks.im","subject":"Re: [PATCH 19/20] global: prepare for hiding away repo-less config functions","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-09T20:57:14Z","receivedAt":"2024-08-09T20:58:01Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/07 08:58AM, Patrick Steinhardt wrote:\n> We're about to hide config functions that implicitly depend on\n> `the_repository` behind the `USE_THE_REPOSITORY_VARIABLE` macro. This\n> will uncover a bunch of dependents that transitively relied on the\n> global variable, but didn'd define the macro yet.\n\ns/didn'd/didn't/\n\n> Adapt them such that we define the macro to prepare for this change.\n\nOnce config functions that rely implicitly on `the_repository` are\nguarded by `USE_THE_REPOSITORY_VARIABLE`, the macro will be required to\nuse them. Now that the dependency is exposed they must be marked\naccordingly. Makes sense to me.\n"},{"id":"500575","messageId":"oksb4qyur7ucqurshkp3232lk3ipqckcwbk56ulungkwozwsf5@w55hc5w6ml4h","threadId":"61914","inReplyTo":"43757f30770bf5a27fd8d7ac55a343185dbe62b3.1723013714.git.ps@pks.im","subject":"Re: [PATCH 20/20] config: hide functions using `the_repository` by default","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-09T21:13:02Z","receivedAt":"2024-08-09T21:13:50Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/07 08:58AM, Patrick Steinhardt wrote:\n> The config subsytem provides a bunch of legacy functions that read or\n\ns/subsytem/subsystem/\n\n> set configuration for `the_repository`. The use of those functions is\n> discouraged, and it is easy to miss the implicit dependency on\n> `the_repository` that calls to those functions may cause.\n> \n> Move all config-related functions that use `the_repository` into a block\n> that gets only conditionally compiled depending on whether or not the\n> macro has been defined. This also removes all dependencies on that\n> variable in \"config.c\", allowing us to remove the definition of said\n> preprocessor macro.\n\nHere we are making the same change done earlier to \"path.h\". Use of\nconfig functions that rely on `the_repository` implicitly now require\nthe caller to define `USE_THE_REPOSITORY_VARIABLE` explicitly. Thus\nimproving visibility of use.\n\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n[snip]\n> +# ifdef USE_THE_REPOSITORY_VARIABLE\n> +static inline void git_config(config_fn_t fn, void *data)\n> +{\n> +\trepo_config(the_repository, fn, data);\n> +}\n> +\n> +static inline void git_config_clear(void)\n> +{\n> +\trepo_config_clear(the_repository);\n> +}\n> +\n> +static inline int git_config_get(const char *key)\n> +{\n> +\treturn repo_config_get(the_repository, key);\n> +}\n> +\n> +static inline int git_config_get_value(const char *key, const char **value)\n> +{\n> +\treturn repo_config_get_value(the_repository, key, value);\n> +}\n> +\n> +static inline int git_config_get_value_multi(const char *key, const struct string_list **dest)\n> +{\n> +\treturn repo_config_get_value_multi(the_repository, key, dest);\n> +}\n> +\n> +static inline int git_config_get_string_multi(const char *key,\n> +\t\t\t\tconst struct string_list **dest)\n> +{\n> +\treturn repo_config_get_string_multi(the_repository, key, dest);\n> +}\n> +\n> +static inline int git_config_get_string(const char *key, char **dest)\n> +{\n> +\treturn repo_config_get_string(the_repository, key, dest);\n> +}\n> +\n> +static inline int git_config_get_string_tmp(const char *key, const char **dest)\n> +{\n> +\treturn repo_config_get_string_tmp(the_repository, key, dest);\n> +}\n> +\n> +static inline int git_config_get_int(const char *key, int *dest)\n> +{\n> +\treturn repo_config_get_int(the_repository, key, dest);\n> +}\n> +\n> +static inline int git_config_get_ulong(const char *key, unsigned long *dest)\n> +{\n> +\treturn repo_config_get_ulong(the_repository, key, dest);\n> +}\n> +\n> +static inline int git_config_get_bool(const char *key, int *dest)\n> +{\n> +\treturn repo_config_get_bool(the_repository, key, dest);\n> +}\n> +\n> +static inline int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest)\n> +{\n> +\treturn repo_config_get_bool_or_int(the_repository, key, is_bool, dest);\n> +}\n> +\n> +static inline int git_config_get_maybe_bool(const char *key, int *dest)\n> +{\n> +\treturn repo_config_get_maybe_bool(the_repository, key, dest);\n> +}\n> +\n> +static inline int git_config_get_pathname(const char *key, char **dest)\n> +{\n> +\treturn repo_config_get_pathname(the_repository, key, dest);\n> +}\n> +\n> +static inline void git_config_set_in_file(const char *config_filename,\n> +\t\t\t\t\t  const char *key, const char *value)\n> +{\n> +\trepo_config_set_in_file(the_repository, config_filename, key, value);\n> +}\n> +\n> +static inline int git_config_set_gently(const char *key, const char *value)\n> +{\n> +\treturn repo_config_set_gently(the_repository, key, value);\n> +}\n> +\n> +static inline void git_config_set(const char *key, const char *value)\n> +{\n> +\trepo_config_set(the_repository, key, value);\n> +}\n> +\n> +static inline int git_config_set_in_file_gently(\n> +\tconst char *config_filename,\n> +\tconst char *key,\n> +\tconst char *comment,\n> +\tconst char *value)\n> +{\n> +\treturn repo_config_set_in_file_gently(the_repository, config_filename,\n> +\t\t\t\t\t      key, comment, value);\n> +}\n> +\n> +static inline int git_config_set_multivar_in_file_gently(\n> +\tconst char *config_filename,\n> +\tconst char *key, const char *value,\n> +\tconst char *value_pattern,\n> +\tconst char *comment,\n> +\tunsigned flags)\n> +{\n> +\treturn repo_config_set_multivar_in_file_gently(the_repository, config_filename,\n> +\t\t\t\t\t\t       key, value, value_pattern,\n> +\t\t\t\t\t\t       comment, flags);\n> +}\n> +\n> +static inline void git_config_set_multivar_in_file(\n> +\tconst char *config_filename,\n> +\tconst char *key,\n> +\tconst char *value,\n> +\tconst char *value_pattern,\n> +\tunsigned flags)\n> +{\n> +\trepo_config_set_multivar_in_file(the_repository, config_filename,\n> +\t\t\t\t\t key, value, value_pattern, flags);\n> +}\n> +\n> +static inline int git_config_set_multivar_gently(const char *key, const char *value,\n> +\t\t\t\t   const char *value_pattern, unsigned flags)\n> +{\n> +\treturn repo_config_set_multivar_gently(the_repository, key, value,\n> +\t\t\t\t\t       value_pattern, flags);\n> +}\n> +\n> +static inline void git_config_set_multivar(const char *key, const char *value,\n> +\t\t\t     const char *value_pattern, unsigned flags)\n> +{\n> +\trepo_config_set_multivar(the_repository, key, value,\n> +\t\t\t\t value_pattern, flags);\n> +}\n> +# endif /* USE_THE_REPOSITORY_VARIABLE */\n\nOnce again, very neat to see this guarded behind\n`USE_THE_REPOSITORY_VARIABLE` now. :)\n\n-Justin\n"},{"id":"500576","messageId":"xmqqh6btbdqz.fsf@gitster.g","threadId":"61914","inReplyTo":"qo26pmkrctepcob4vjfimvxlgoic7gqjxasnz2hqmv4hpgc37t@jh5wo2fjqyoo","subject":"Re: [PATCH 14/20] config: pass repo to `git_config_get_expiry_in_days()`","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-09T21:14:12Z","receivedAt":"2024-08-09T21:14:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Justin Tobler <jltobler@gmail.com> writes:\n\n> On 24/08/07 08:57AM, Patrick Steinhardt wrote:\n>> Refactor `git_config_get_expiry_in_days()` to accept a `struct\n>> repository` such that we can get rid of the implicit dependency on\n>> `the_repository`. Rename the function accordingly.\n>> \n>> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n>> ---\n> [snip]\n>> -\tgit_config_get_expiry_in_days(\"gc.rerereresolved\", &cutoff_resolve, now);\n>> -\tgit_config_get_expiry_in_days(\"gc.rerereunresolved\", &cutoff_noresolve, now);\n>> +\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereresolved\", &cutoff_resolve, now);\n>> +\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereunresolved\", &cutoff_noresolve, now);\n>\n> non-blocking: Do we want to fold these lines?\n\nYes, if we are going to see another iteration for other reasons.\n\n"},{"id":"500705","messageId":"cover.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723013714.git.ps@pks.im","subject":"[PATCH v2 00/20] Stop using `the_repository` in \"config.c\"","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:17Z","receivedAt":"2024-08-13T09:13:22Z","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 that drops the dependency\non `the_repository` in both \"path.c\" and \"config.c\".\n\nChanges compared to v1:\n\n  - Various typo fixes in commit messages.\n\n  - Rename `strbuf_git_common_pathv()` to `repo_common_pathv()`.\n\n  - Reorder arguments of `strbuf_edit_interactively()` such that the\n    `struct repository` gets passed as first argument.\n\n  - Document behaviour of `worktree_git_path()` when no worktree is\n    given.\n\n  - Wrap some overly long lines.\n\nThanks!\n\nPatrick\n\nPatrick Steinhardt (20):\n  path: expose `do_git_path()` as `repo_git_pathv()`\n  path: expose `do_git_common_path()` as `repo_common_pathv()`\n  editor: do not rely on `the_repository` for interactive edits\n  hooks: remove implicit dependency on `the_repository`\n  path: stop relying on `the_repository` when reporting garbage\n  path: stop relying on `the_repository` in `worktree_git_path()`\n  path: hide functions using `the_repository` by default\n  config: introduce missing setters that take repo as parameter\n  config: expose `repo_config_clear()`\n  config: pass repo to `git_config_get_index_threads()`\n  config: pass repo to `git_config_get_split_index()`\n  config: pass repo to `git_config_get_max_percent_split_change()`\n  config: pass repo to `git_config_get_expiry()`\n  config: pass repo to `git_config_get_expiry_in_days()`\n  config: pass repo to `git_die_config()`\n  config: pass repo to functions that rename or copy sections\n  config: don't have setters depend on `the_repository`\n  config: don't depend on `the_repository` with branch conditions\n  global: prepare for hiding away repo-less config functions\n  config: hide functions using `the_repository` by default\n\n add-patch.c                       |   3 +-\n builtin/am.c                      |   9 +-\n builtin/branch.c                  |   7 +-\n builtin/bugreport.c               |   2 +-\n builtin/checkout.c                |   2 +-\n builtin/clone.c                   |   2 +-\n builtin/config.c                  |  16 +-\n builtin/count-objects.c           |   2 +-\n builtin/fast-import.c             |   4 +-\n builtin/fsck.c                    |   2 +-\n builtin/gc.c                      |   8 +-\n builtin/hook.c                    |   2 +-\n builtin/merge.c                   |   2 +-\n builtin/notes.c                   |   2 +-\n builtin/rebase.c                  |   2 +-\n builtin/receive-pack.c            |  10 +-\n builtin/remote.c                  |   4 +-\n builtin/submodule--helper.c       |   2 +-\n builtin/update-index.c            |   4 +-\n builtin/worktree.c                |   6 +-\n commit.c                          |   2 +-\n compat/fsmonitor/fsm-ipc-darwin.c |   2 +\n compat/precompose_utf8.c          |   1 +\n config.c                          | 225 ++++++++---------------\n config.h                          | 285 +++++++++++++++++++++---------\n connect.c                         |   2 +\n credential.c                      |   2 +\n daemon.c                          |   2 +\n editor.c                          |  15 +-\n editor.h                          |   5 +-\n fsmonitor.c                       |   2 +\n gpg-interface.c                   |   2 +\n graph.c                           |   2 +\n hook.c                            |  21 +--\n hook.h                            |  13 +-\n imap-send.c                       |   2 +\n mailinfo.c                        |   2 +\n merge-ll.c                        |   2 +\n parallel-checkout.c               |   2 +\n path.c                            |  97 +++-------\n path.h                            | 170 ++++++++++++------\n protocol.c                        |   2 +\n read-cache.c                      |  22 +--\n refs.c                            |   4 +-\n refs/packed-backend.c             |   2 +\n refs/reftable-backend.c           |   2 +\n rerere.c                          |   6 +-\n reset.c                           |   2 +-\n revision.c                        |   2 +-\n sequencer.c                       |   6 +-\n sideband.c                        |   2 +\n submodule.c                       |   2 +-\n t/helper/test-advise.c            |   2 +\n t/helper/test-config.c            |   2 +\n t/helper/test-userdiff.c          |   2 +\n trailer.c                         |   2 +\n transport.c                       |   2 +-\n versioncmp.c                      |   2 +\n worktree.c                        |   2 +-\n wt-status.c                       |  14 +-\n 60 files changed, 570 insertions(+), 457 deletions(-)\n\nRange-diff against v1:\n 1:  7ce3278f64 =  1:  d0f5f2b17f path: expose `do_git_path()` as `repo_git_pathv()`\n 2:  e7a143c30d !  2:  2e3f474e5d path: expose `do_git_common_path()` as `strbuf_git_common_pathv()`\n    @@ Metadata\n     Author: Patrick Steinhardt <ps@pks.im>\n     \n      ## Commit message ##\n    -    path: expose `do_git_common_path()` as `strbuf_git_common_pathv()`\n    +    path: expose `do_git_common_path()` as `repo_common_pathv()`\n     \n         With the same reasoning as the preceding commit, expose the function\n    -    `do_git_common_path()` as `strbuf_git_common_pathv()`.\n    +    `do_git_common_path()` as `repo_common_pathv()`. While at it, reorder\n    +    parameters such that they match the order we have in `repo_git_pathv()`.\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n    @@ path.c: int strbuf_git_path_submodule(struct strbuf *buf, const char *path,\n     -\t\t\t       struct strbuf *buf,\n     -\t\t\t       const char *fmt,\n     -\t\t\t       va_list args)\n    -+void strbuf_git_common_pathv(struct strbuf *sb,\n    -+\t\t\t     const struct repository *repo,\n    -+\t\t\t     const char *fmt,\n    -+\t\t\t     va_list args)\n    ++void repo_common_pathv(const struct repository *repo,\n    ++\t\t       struct strbuf *sb,\n    ++\t\t       const char *fmt,\n    ++\t\t       va_list args)\n      {\n     -\tstrbuf_addstr(buf, repo->commondir);\n     -\tif (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))\n    @@ path.c: const char *git_common_path(const char *fmt, ...)\n      \tva_list args;\n      \tva_start(args, fmt);\n     -\tdo_git_common_path(the_repository, pathname, fmt, args);\n    -+\tstrbuf_git_common_pathv(pathname, the_repository, fmt, args);\n    ++\trepo_common_pathv(the_repository, pathname, fmt, args);\n      \tva_end(args);\n      \treturn pathname->buf;\n      }\n    @@ path.c: void strbuf_git_common_path(struct strbuf *sb,\n      \tva_list args;\n      \tva_start(args, fmt);\n     -\tdo_git_common_path(repo, sb, fmt, args);\n    -+\tstrbuf_git_common_pathv(sb, repo, fmt, args);\n    ++\trepo_common_pathv(repo, sb, fmt, args);\n      \tva_end(args);\n      }\n      \n    @@ path.h: void strbuf_git_common_path(struct strbuf *sb,\n      \t\t\t    const struct repository *repo,\n      \t\t\t    const char *fmt, ...)\n      \t__attribute__((format (printf, 3, 4)));\n    -+void strbuf_git_common_pathv(struct strbuf *sb,\n    -+\t\t\t     const struct repository *repo,\n    -+\t\t\t     const char *fmt,\n    -+\t\t\t     va_list args);\n    ++void repo_common_pathv(const struct repository *repo,\n    ++\t\t       struct strbuf *buf,\n    ++\t\t       const char *fmt,\n    ++\t\t       va_list args);\n      \n      /*\n       * Return a statically allocated path into the main repository's\n 3:  c2556fff9e !  3:  2f73e0efcd editor: do not rely on `the_repository` for interactive edits\n    @@ Commit message\n     \n         We implicitly rely on `the_repository` when editing a file interactively\n         because we call `git_path()`. Adapt the function to instead take a\n    -    `sturct repository` as parameter so that we can remove this hidden\n    +    `struct repository` as a parameter so that we can remove this hidden\n         dependency.\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n    @@ add-patch.c: static int edit_hunk_manually(struct add_p_state *s, struct hunk *h\n      \t\t\t\t\"aborted and the hunk is left unchanged.\\n\"));\n      \n     -\tif (strbuf_edit_interactively(&s->buf, \"addp-hunk-edit.diff\", NULL) < 0)\n    -+\tif (strbuf_edit_interactively(&s->buf, \"addp-hunk-edit.diff\", NULL,\n    -+\t\t\t\t      the_repository) < 0)\n    ++\tif (strbuf_edit_interactively(the_repository, &s->buf,\n    ++\t\t\t\t      \"addp-hunk-edit.diff\", NULL) < 0)\n      \t\treturn -1;\n      \n      \t/* strip out commented lines */\n     \n      ## editor.c ##\n     @@ editor.c: int launch_sequence_editor(const char *path, struct strbuf *buffer,\n    + \treturn launch_specified_editor(git_sequence_editor(), path, buffer, env);\n      }\n      \n    - int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n    --\t\t\t      const char *const *env)\n    -+\t\t\t      const char *const *env, struct repository *r)\n    +-int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n    ++int strbuf_edit_interactively(struct repository *r,\n    ++\t\t\t      struct strbuf *buffer, const char *path,\n    + \t\t\t      const char *const *env)\n      {\n     -\tchar *path2 = NULL;\n     +\tstruct strbuf sb = STRBUF_INIT;\n    @@ editor.h\n      \n      const char *git_editor(void);\n     @@ editor.h: int launch_sequence_editor(const char *path, struct strbuf *buffer,\n    +  *\n       * If `path` is relative, it refers to a file in the `.git` directory.\n       */\n    - int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n    +-int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n     -\t\t\t      const char *const *env);\n    -+\t\t\t      const char *const *env, struct repository *r);\n    ++int strbuf_edit_interactively(struct repository *r, struct strbuf *buffer,\n    ++\t\t\t      const char *path, const char *const *env);\n      \n      #endif\n 4:  9a0964aff3 =  4:  688d705179 hooks: remove implicit dependency on `the_repository`\n 5:  4368b32f65 =  5:  bbaa85ebad path: stop relying on `the_repository` when reporting garbage\n 6:  67405dcd0a !  6:  29302f4b14 path: stop relying on `the_repository` in `worktree_git_path()`\n    @@ path.c: const char *mkpath(const char *fmt, ...)\n     \n      ## path.h ##\n     @@ path.h: const char *git_path(const char *fmt, ...)\n    + \n    + /*\n       * Similar to git_path() but can produce paths for a specified\n    -  * worktree instead of current one\n    +- * worktree instead of current one\n    ++ * worktree instead of current one. When no worktree is given, then the path is\n    ++ * computed relative to main worktree of the given repository.\n       */\n     -const char *worktree_git_path(const struct worktree *wt,\n     +const char *worktree_git_path(struct repository *r,\n 7:  b4e973a280 !  7:  1b6651770a path: hide functions using `the_repository` by default\n    @@ Metadata\n      ## Commit message ##\n         path: hide functions using `the_repository` by default\n     \n    -    The path subsytem provides a bunch of legacy functions that compute\n    +    The path subsystem provides a bunch of legacy functions that compute\n         paths relative to the \"gitdir\" and \"commondir\" directories of the global\n         `the_repository` variable. Use of those functions is discouraged, and it\n         is easy to miss the implicit dependency on `the_repository` that calls\n         to those functions may cause.\n     \n         With `USE_THE_REPOSITORY_VARIABLE`, we have recently introduced a tool\n    -    that allows us to get rid of such functions over time. With this define,\n    +    that allows us to get rid of such functions over time. With this macro,\n         we can hide away functions that have such implicit dependency such that\n         other subsystems that want to be free of `the_repository` will not use\n         them by accident.\n    @@ path.c: void strbuf_repo_git_path(struct strbuf *sb,\n      char *mkpathdup(const char *fmt, ...)\n      {\n      \tstruct strbuf sb = STRBUF_INIT;\n    -@@ path.c: void strbuf_git_common_pathv(struct strbuf *sb,\n    +@@ path.c: void repo_common_pathv(const struct repository *repo,\n      \tstrbuf_cleanup_path(sb);\n      }\n      \n    @@ path.c: void strbuf_git_common_pathv(struct strbuf *sb,\n     -\tstruct strbuf *pathname = get_pathname();\n     -\tva_list args;\n     -\tva_start(args, fmt);\n    --\tstrbuf_git_common_pathv(pathname, the_repository, fmt, args);\n    +-\trepo_common_pathv(the_repository, pathname, fmt, args);\n     -\tva_end(args);\n     -\treturn pathname->buf;\n     -}\n    @@ path.h: char *mkpathdup(const char *fmt, ...)\n       * repository's common git directory, which is shared by all worktrees.\n       */\n      \n    -@@ path.h: void strbuf_git_common_pathv(struct strbuf *sb,\n    - \t\t\t     va_list args);\n    +@@ path.h: void repo_common_pathv(const struct repository *repo,\n    + \t\t       va_list args);\n      \n      /*\n     - * Return a statically allocated path into the main repository's\n    @@ path.h: void strbuf_repo_git_path(struct strbuf *sb,\n     -/*\n     - * Similar to git_path() but can produce paths for a specified\n     + * Similar to repo_git_path() but can produce paths for a specified\n    -  * worktree instead of current one\n    +  * worktree instead of current one. When no worktree is given, then the path is\n    +  * computed relative to main worktree of the given repository.\n       */\n    - const char *worktree_git_path(struct repository *r,\n     @@ path.h: const char *worktree_git_path(struct repository *r,\n      \t\t\t      const char *fmt, ...)\n      \t__attribute__((format (printf, 3, 4)));\n    @@ path.h: char *xdg_cache_home(const char *filename);\n     +\tstruct strbuf *pathname = get_pathname();\n     +\tva_list args;\n     +\tva_start(args, fmt);\n    -+\tstrbuf_git_common_pathv(pathname, the_repository, fmt, args);\n    ++\trepo_common_pathv(the_repository, pathname, fmt, args);\n     +\tva_end(args);\n     +\treturn pathname->buf;\n     +}\n 8:  feae2ad31a !  8:  e316491e56 config: introduce missing setters that take repo as parameter\n    @@ Commit message\n     \n         While we already provide some of the config-setting interfaces with a\n         `struct repository` as parameter, others only have a variant that\n    -    implicitly depend on `the_repository`. Fill in those gaps such that we\n    +    implicitly depends on `the_repository`. Fill in those gaps such that we\n         can start to deprecate the repo-less variants.\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n 9:  63da87696e =  9:  5e73ef6cec config: expose `repo_config_clear()`\n10:  03df1277f7 = 10:  35e0f4579c config: pass repo to `git_config_get_index_threads()`\n11:  85311d686e = 11:  a88ed83b97 config: pass repo to `git_config_get_split_index()`\n12:  b95ed05f88 = 12:  17c5420d63 config: pass repo to `git_config_get_max_percent_split_change()`\n13:  412cc514e8 = 13:  f39d4a3244 config: pass repo to `git_config_get_expiry()`\n14:  cf7942479f ! 14:  111f77e653 config: pass repo to `git_config_get_expiry_in_days()`\n    @@ rerere.c: void rerere_gc(struct repository *r, struct string_list *rr)\n      \n     -\tgit_config_get_expiry_in_days(\"gc.rerereresolved\", &cutoff_resolve, now);\n     -\tgit_config_get_expiry_in_days(\"gc.rerereunresolved\", &cutoff_noresolve, now);\n    -+\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereresolved\", &cutoff_resolve, now);\n    -+\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereunresolved\", &cutoff_noresolve, now);\n    ++\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereresolved\",\n    ++\t\t\t\t       &cutoff_resolve, now);\n    ++\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereunresolved\",\n    ++\t\t\t\t       &cutoff_noresolve, now);\n      \tgit_config(git_default_config, NULL);\n      \tdir = opendir(git_path(\"rr-cache\"));\n      \tif (!dir)\n15:  d70d9bfa7e = 15:  6adee5633a config: pass repo to `git_die_config()`\n16:  980533972c = 16:  b8c54b751c config: pass repo to functions that rename or copy sections\n17:  1c1b27cbac = 17:  1e5cd92e8e config: don't have setters depend on `the_repository`\n18:  d8530a300b = 18:  96963364e7 config: don't depend on `the_repository` with branch conditions\n19:  f7617beaa5 ! 19:  124f5794e6 global: prepare for hiding away repo-less config functions\n    @@ Commit message\n         We're about to hide config functions that implicitly depend on\n         `the_repository` behind the `USE_THE_REPOSITORY_VARIABLE` macro. This\n         will uncover a bunch of dependents that transitively relied on the\n    -    global variable, but didn'd define the macro yet.\n    +    global variable, but didn't define the macro yet.\n     \n         Adapt them such that we define the macro to prepare for this change.\n     \n20:  43757f3077 ! 20:  467cd481f5 config: hide functions using `the_repository` by default\n    @@ Metadata\n      ## Commit message ##\n         config: hide functions using `the_repository` by default\n     \n    -    The config subsytem provides a bunch of legacy functions that read or\n    +    The config subsystem provides a bunch of legacy functions that read or\n         set configuration for `the_repository`. The use of those functions is\n         discouraged, and it is easy to miss the implicit dependency on\n         `the_repository` that calls to those functions may cause.\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500706","messageId":"d0f5f2b17f2514cfb4b96761bcc9d677dc168752.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 01/20] path: expose `do_git_path()` as `repo_git_pathv()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:20Z","receivedAt":"2024-08-13T09:13:23Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to move functions of the \"path\" subsytem that do not use a\n`struct repository` into \"path.h\" as static inlined functions. This will\nrequire us to call `do_git_path()`, which is internal to \"path.c\".\n\nExpose the function as `repo_git_pathv()` to prepare for the change.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n path.c | 20 ++++++++++----------\n path.h |  8 ++++++++\n 2 files changed, 18 insertions(+), 10 deletions(-)\n\ndiff --git a/path.c b/path.c\nindex 19f7684f38..71f1cb4dfb 100644\n--- a/path.c\n+++ b/path.c\n@@ -417,9 +417,9 @@ static void strbuf_worktree_gitdir(struct strbuf *buf,\n \t\tstrbuf_git_common_path(buf, repo, \"worktrees/%s\", wt->id);\n }\n \n-static void do_git_path(const struct repository *repo,\n-\t\t\tconst struct worktree *wt, struct strbuf *buf,\n-\t\t\tconst char *fmt, va_list args)\n+void repo_git_pathv(const struct repository *repo,\n+\t\t    const struct worktree *wt, struct strbuf *buf,\n+\t\t    const char *fmt, va_list args)\n {\n \tint gitdir_len;\n \tstrbuf_worktree_gitdir(buf, repo, wt);\n@@ -438,7 +438,7 @@ char *repo_git_path(const struct repository *repo,\n \tstruct strbuf path = STRBUF_INIT;\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(repo, NULL, &path, fmt, args);\n+\trepo_git_pathv(repo, NULL, &path, fmt, args);\n \tva_end(args);\n \treturn strbuf_detach(&path, NULL);\n }\n@@ -449,7 +449,7 @@ void strbuf_repo_git_path(struct strbuf *sb,\n {\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(repo, NULL, sb, fmt, args);\n+\trepo_git_pathv(repo, NULL, sb, fmt, args);\n \tva_end(args);\n }\n \n@@ -458,7 +458,7 @@ char *git_path_buf(struct strbuf *buf, const char *fmt, ...)\n \tva_list args;\n \tstrbuf_reset(buf);\n \tva_start(args, fmt);\n-\tdo_git_path(the_repository, NULL, buf, fmt, args);\n+\trepo_git_pathv(the_repository, NULL, buf, fmt, args);\n \tva_end(args);\n \treturn buf->buf;\n }\n@@ -467,7 +467,7 @@ void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)\n {\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(the_repository, NULL, sb, fmt, args);\n+\trepo_git_pathv(the_repository, NULL, sb, fmt, args);\n \tva_end(args);\n }\n \n@@ -476,7 +476,7 @@ const char *git_path(const char *fmt, ...)\n \tstruct strbuf *pathname = get_pathname();\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(the_repository, NULL, pathname, fmt, args);\n+\trepo_git_pathv(the_repository, NULL, pathname, fmt, args);\n \tva_end(args);\n \treturn pathname->buf;\n }\n@@ -486,7 +486,7 @@ char *git_pathdup(const char *fmt, ...)\n \tstruct strbuf path = STRBUF_INIT;\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(the_repository, NULL, &path, fmt, args);\n+\trepo_git_pathv(the_repository, NULL, &path, fmt, args);\n \tva_end(args);\n \treturn strbuf_detach(&path, NULL);\n }\n@@ -517,7 +517,7 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)\n \tstruct strbuf *pathname = get_pathname();\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_path(the_repository, wt, pathname, fmt, args);\n+\trepo_git_pathv(the_repository, wt, pathname, fmt, args);\n \tva_end(args);\n \treturn pathname->buf;\n }\ndiff --git a/path.h b/path.h\nindex a6f0b70692..94e7030f0b 100644\n--- a/path.h\n+++ b/path.h\n@@ -66,6 +66,14 @@ char *repo_git_path(const struct repository *repo,\n \t\t    const char *fmt, ...)\n \t__attribute__((format (printf, 2, 3)));\n \n+/*\n+ * Print a path into the git directory of repository `repo` into the provided\n+ * buffer.\n+ */\n+void repo_git_pathv(const struct repository *repo,\n+\t\t    const struct worktree *wt, struct strbuf *buf,\n+\t\t    const char *fmt, va_list args);\n+\n /*\n  * Construct a path into the git directory of repository `repo` and append it\n  * to the provided buffer `sb`.\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500707","messageId":"2e3f474e5d7df6e8ad676d50f2191a28e580f5fe.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 02/20] path: expose `do_git_common_path()` as `repo_common_pathv()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:23Z","receivedAt":"2024-08-13T09:13:26Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"With the same reasoning as the preceding commit, expose the function\n`do_git_common_path()` as `repo_common_pathv()`. While at it, reorder\nparameters such that they match the order we have in `repo_git_pathv()`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n path.c | 22 +++++++++++-----------\n path.h |  5 ++++-\n 2 files changed, 15 insertions(+), 12 deletions(-)\n\ndiff --git a/path.c b/path.c\nindex 71f1cb4dfb..069db6ff8f 100644\n--- a/path.c\n+++ b/path.c\n@@ -617,16 +617,16 @@ int strbuf_git_path_submodule(struct strbuf *buf, const char *path,\n \treturn err;\n }\n \n-static void do_git_common_path(const struct repository *repo,\n-\t\t\t       struct strbuf *buf,\n-\t\t\t       const char *fmt,\n-\t\t\t       va_list args)\n+void repo_common_pathv(const struct repository *repo,\n+\t\t       struct strbuf *sb,\n+\t\t       const char *fmt,\n+\t\t       va_list args)\n {\n-\tstrbuf_addstr(buf, repo->commondir);\n-\tif (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))\n-\t\tstrbuf_addch(buf, '/');\n-\tstrbuf_vaddf(buf, fmt, args);\n-\tstrbuf_cleanup_path(buf);\n+\tstrbuf_addstr(sb, repo->commondir);\n+\tif (sb->len && !is_dir_sep(sb->buf[sb->len - 1]))\n+\t\tstrbuf_addch(sb, '/');\n+\tstrbuf_vaddf(sb, fmt, args);\n+\tstrbuf_cleanup_path(sb);\n }\n \n const char *git_common_path(const char *fmt, ...)\n@@ -634,7 +634,7 @@ const char *git_common_path(const char *fmt, ...)\n \tstruct strbuf *pathname = get_pathname();\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_common_path(the_repository, pathname, fmt, args);\n+\trepo_common_pathv(the_repository, pathname, fmt, args);\n \tva_end(args);\n \treturn pathname->buf;\n }\n@@ -645,7 +645,7 @@ void strbuf_git_common_path(struct strbuf *sb,\n {\n \tva_list args;\n \tva_start(args, fmt);\n-\tdo_git_common_path(repo, sb, fmt, args);\n+\trepo_common_pathv(repo, sb, fmt, args);\n \tva_end(args);\n }\n \ndiff --git a/path.h b/path.h\nindex 94e7030f0b..05aff5f4c3 100644\n--- a/path.h\n+++ b/path.h\n@@ -37,6 +37,10 @@ void strbuf_git_common_path(struct strbuf *sb,\n \t\t\t    const struct repository *repo,\n \t\t\t    const char *fmt, ...)\n \t__attribute__((format (printf, 3, 4)));\n+void repo_common_pathv(const struct repository *repo,\n+\t\t       struct strbuf *buf,\n+\t\t       const char *fmt,\n+\t\t       va_list args);\n \n /*\n  * Return a statically allocated path into the main repository's\n@@ -45,7 +49,6 @@ void strbuf_git_common_path(struct strbuf *sb,\n const char *git_common_path(const char *fmt, ...)\n \t__attribute__((format (printf, 1, 2)));\n \n-\n /*\n  * The `git_path` family of functions will construct a path into a repository's\n  * git directory.\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500708","messageId":"2f73e0efcd4304d191636edf662564dabc48e18c.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 03/20] editor: do not rely on `the_repository` for interactive edits","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:25Z","receivedAt":"2024-08-13T09:13:29Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We implicitly rely on `the_repository` when editing a file interactively\nbecause we call `git_path()`. Adapt the function to instead take a\n`struct repository` as a parameter so that we can remove this hidden\ndependency.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n add-patch.c |  3 ++-\n editor.c    | 13 ++++++++-----\n editor.h    |  5 +++--\n 3 files changed, 13 insertions(+), 8 deletions(-)\n\ndiff --git a/add-patch.c b/add-patch.c\nindex 46f6bddfe5..218dda3e79 100644\n--- a/add-patch.c\n+++ b/add-patch.c\n@@ -1140,7 +1140,8 @@ static int edit_hunk_manually(struct add_p_state *s, struct hunk *hunk)\n \t\t\t\t\"removed, then the edit is\\n\"\n \t\t\t\t\"aborted and the hunk is left unchanged.\\n\"));\n \n-\tif (strbuf_edit_interactively(&s->buf, \"addp-hunk-edit.diff\", NULL) < 0)\n+\tif (strbuf_edit_interactively(the_repository, &s->buf,\n+\t\t\t\t      \"addp-hunk-edit.diff\", NULL) < 0)\n \t\treturn -1;\n \n \t/* strip out commented lines */\ndiff --git a/editor.c b/editor.c\nindex d1ba2d7c34..e93b4fdb09 100644\n--- a/editor.c\n+++ b/editor.c\n@@ -133,14 +133,17 @@ int launch_sequence_editor(const char *path, struct strbuf *buffer,\n \treturn launch_specified_editor(git_sequence_editor(), path, buffer, env);\n }\n \n-int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n+int strbuf_edit_interactively(struct repository *r,\n+\t\t\t      struct strbuf *buffer, const char *path,\n \t\t\t      const char *const *env)\n {\n-\tchar *path2 = NULL;\n+\tstruct strbuf sb = STRBUF_INIT;\n \tint fd, res = 0;\n \n-\tif (!is_absolute_path(path))\n-\t\tpath = path2 = xstrdup(git_path(\"%s\", path));\n+\tif (!is_absolute_path(path)) {\n+\t\tstrbuf_repo_git_path(&sb, r, \"%s\", path);\n+\t\tpath = sb.buf;\n+\t}\n \n \tfd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);\n \tif (fd < 0)\n@@ -157,6 +160,6 @@ int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n \t\tunlink(path);\n \t}\n \n-\tfree(path2);\n+\tstrbuf_release(&sb);\n \treturn res;\n }\ndiff --git a/editor.h b/editor.h\nindex 8016bb5e00..f1c41df378 100644\n--- a/editor.h\n+++ b/editor.h\n@@ -1,6 +1,7 @@\n #ifndef EDITOR_H\n #define EDITOR_H\n \n+struct repository;\n struct strbuf;\n \n const char *git_editor(void);\n@@ -28,7 +29,7 @@ int launch_sequence_editor(const char *path, struct strbuf *buffer,\n  *\n  * If `path` is relative, it refers to a file in the `.git` directory.\n  */\n-int strbuf_edit_interactively(struct strbuf *buffer, const char *path,\n-\t\t\t      const char *const *env);\n+int strbuf_edit_interactively(struct repository *r, struct strbuf *buffer,\n+\t\t\t      const char *path, const char *const *env);\n \n #endif\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500709","messageId":"688d705179e0d8692c635e20f15eb18ae8e500eb.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 04/20] hooks: remove implicit dependency on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:28Z","receivedAt":"2024-08-13T09:13:31Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We implicitly depend on `the_repository` in our hook subsystem because\nwe use `strbuf_git_path()` to compute hook paths. Remove this dependency\nby accepting a `struct repository` as parameter instead.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/am.c           |  9 +++++----\n builtin/bugreport.c    |  2 +-\n builtin/checkout.c     |  2 +-\n builtin/clone.c        |  2 +-\n builtin/gc.c           |  2 +-\n builtin/hook.c         |  2 +-\n builtin/merge.c        |  2 +-\n builtin/rebase.c       |  2 +-\n builtin/receive-pack.c | 10 +++++-----\n builtin/worktree.c     |  2 +-\n commit.c               |  2 +-\n hook.c                 | 21 +++++++++++----------\n hook.h                 | 13 ++++++++-----\n read-cache.c           |  6 +++---\n refs.c                 |  2 +-\n reset.c                |  2 +-\n sequencer.c            |  6 +++---\n transport.c            |  2 +-\n 18 files changed, 47 insertions(+), 42 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex a12be088f7..d8875ad402 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -490,7 +490,8 @@ static int run_applypatch_msg_hook(struct am_state *state)\n \tassert(state->msg);\n \n \tif (!state->no_verify)\n-\t\tret = run_hooks_l(\"applypatch-msg\", am_path(state, \"final-commit\"), NULL);\n+\t\tret = run_hooks_l(the_repository, \"applypatch-msg\",\n+\t\t\t\t  am_path(state, \"final-commit\"), NULL);\n \n \tif (!ret) {\n \t\tFREE_AND_NULL(state->msg);\n@@ -512,7 +513,7 @@ static int run_post_rewrite_hook(const struct am_state *state)\n \tstrvec_push(&opt.args, \"rebase\");\n \topt.path_to_stdin = am_path(state, \"rewritten\");\n \n-\treturn run_hooks_opt(\"post-rewrite\", &opt);\n+\treturn run_hooks_opt(the_repository, \"post-rewrite\", &opt);\n }\n \n /**\n@@ -1663,7 +1664,7 @@ static void do_commit(const struct am_state *state)\n \tconst char *reflog_msg, *author, *committer = NULL;\n \tstruct strbuf sb = STRBUF_INIT;\n \n-\tif (!state->no_verify && run_hooks(\"pre-applypatch\"))\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@@ -1716,7 +1717,7 @@ static void do_commit(const struct am_state *state)\n \t\tfclose(fp);\n \t}\n \n-\trun_hooks(\"post-applypatch\");\n+\trun_hooks(the_repository, \"post-applypatch\");\n \n \tfree_commit_list(parents);\n \tstrbuf_release(&sb);\ndiff --git a/builtin/bugreport.c b/builtin/bugreport.c\nindex b3cc77af53..bdfed3d8f1 100644\n--- a/builtin/bugreport.c\n+++ b/builtin/bugreport.c\n@@ -58,7 +58,7 @@ static void get_populated_hooks(struct strbuf *hook_info, int nongit)\n \tfor (p = hook_name_list; *p; p++) {\n \t\tconst char *hook = *p;\n \n-\t\tif (hook_exists(hook))\n+\t\tif (hook_exists(the_repository, hook))\n \t\t\tstrbuf_addf(hook_info, \"%s\\n\", hook);\n \t}\n }\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 0f21ddd2c6..89543b3054 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -125,7 +125,7 @@ static void branch_info_release(struct branch_info *info)\n static int post_checkout_hook(struct commit *old_commit, struct commit *new_commit,\n \t\t\t      int changed)\n {\n-\treturn run_hooks_l(\"post-checkout\",\n+\treturn run_hooks_l(the_repository, \"post-checkout\",\n \t\t\t   oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()),\n \t\t\t   oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),\n \t\t\t   changed ? \"1\" : \"0\", NULL);\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex af6017d41a..29d4b79eb5 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -788,7 +788,7 @@ static int checkout(int submodule_progress, int filter_submodules)\n \tif (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))\n \t\tdie(_(\"unable to write new index file\"));\n \n-\terr |= run_hooks_l(\"post-checkout\", oid_to_hex(null_oid()),\n+\terr |= run_hooks_l(the_repository, \"post-checkout\", oid_to_hex(null_oid()),\n \t\t\t   oid_to_hex(&oid), \"1\", NULL);\n \n \tif (!err && (option_recurse_submodules.nr > 0)) {\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex 72bac2554f..2ca6288c6b 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -463,7 +463,7 @@ static int need_to_gc(void)\n \telse\n \t\treturn 0;\n \n-\tif (run_hooks(\"pre-auto-gc\"))\n+\tif (run_hooks(the_repository, \"pre-auto-gc\"))\n \t\treturn 0;\n \treturn 1;\n }\ndiff --git a/builtin/hook.c b/builtin/hook.c\nindex 5234693a94..cc37438fde 100644\n--- a/builtin/hook.c\n+++ b/builtin/hook.c\n@@ -58,7 +58,7 @@ static int run(int argc, const char **argv, const char *prefix)\n \thook_name = argv[0];\n \tif (!ignore_missing)\n \t\topt.error_if_missing = 1;\n-\tret = run_hooks_opt(hook_name, &opt);\n+\tret = run_hooks_opt(the_repository, hook_name, &opt);\n \tif (ret < 0) /* error() return */\n \t\tret = 1;\n \treturn ret;\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex c896b18d1a..662a49a0e8 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -478,7 +478,7 @@ static void finish(struct commit *head_commit,\n \t}\n \n \t/* Run a post-merge hook */\n-\trun_hooks_l(\"post-merge\", squash ? \"1\" : \"0\", NULL);\n+\trun_hooks_l(the_repository, \"post-merge\", squash ? \"1\" : \"0\", NULL);\n \n \tif (new_head)\n \t\tapply_autostash_ref(the_repository, \"MERGE_AUTOSTASH\");\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex e3a8e74cfc..fa0ca613e1 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1774,7 +1774,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \n \t/* If a hook exists, give it a chance to interrupt*/\n \tif (!ok_to_skip_pre_rebase &&\n-\t    run_hooks_l(\"pre-rebase\", options.upstream_arg,\n+\t    run_hooks_l(the_repository, \"pre-rebase\", options.upstream_arg,\n \t\t\targc ? argv[0] : NULL, NULL))\n \t\tdie(_(\"The pre-rebase hook refused to rebase.\"));\n \ndiff --git a/builtin/receive-pack.c b/builtin/receive-pack.c\nindex 339524ae2a..4ff22d8b15 100644\n--- a/builtin/receive-pack.c\n+++ b/builtin/receive-pack.c\n@@ -792,7 +792,7 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed,\n \tstruct child_process proc = CHILD_PROCESS_INIT;\n \tstruct async muxer;\n \tint code;\n-\tconst char *hook_path = find_hook(hook_name);\n+\tconst char *hook_path = find_hook(the_repository, hook_name);\n \n \tif (!hook_path)\n \t\treturn 0;\n@@ -922,7 +922,7 @@ static int run_update_hook(struct command *cmd)\n {\n \tstruct child_process proc = CHILD_PROCESS_INIT;\n \tint code;\n-\tconst char *hook_path = find_hook(\"update\");\n+\tconst char *hook_path = find_hook(the_repository, \"update\");\n \n \tif (!hook_path)\n \t\treturn 0;\n@@ -1098,7 +1098,7 @@ static int run_proc_receive_hook(struct command *commands,\n \tint hook_use_push_options = 0;\n \tint version = 0;\n \tint code;\n-\tconst char *hook_path = find_hook(\"proc-receive\");\n+\tconst char *hook_path = find_hook(the_repository, \"proc-receive\");\n \n \tif (!hook_path) {\n \t\trp_error(\"cannot find hook 'proc-receive'\");\n@@ -1409,7 +1409,7 @@ static const char *push_to_checkout(unsigned char *hash,\n \tstrvec_pushf(env, \"GIT_WORK_TREE=%s\", absolute_path(work_tree));\n \tstrvec_pushv(&opt.env, env->v);\n \tstrvec_push(&opt.args, hash_to_hex(hash));\n-\tif (run_hooks_opt(push_to_checkout_hook, &opt))\n+\tif (run_hooks_opt(the_repository, push_to_checkout_hook, &opt))\n \t\treturn \"push-to-checkout hook declined\";\n \telse\n \t\treturn NULL;\n@@ -1618,7 +1618,7 @@ static void run_update_post_hook(struct command *commands)\n \tstruct child_process proc = CHILD_PROCESS_INIT;\n \tconst char *hook;\n \n-\thook = find_hook(\"post-update\");\n+\thook = find_hook(the_repository, \"post-update\");\n \tif (!hook)\n \t\treturn;\n \ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 1d51e54fcd..a4b7f24e1e 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -573,7 +573,7 @@ static int add_worktree(const char *path, const char *refname,\n \t\t\t     NULL);\n \t\topt.dir = path;\n \n-\t\tret = run_hooks_opt(\"post-checkout\", &opt);\n+\t\tret = run_hooks_opt(the_repository, \"post-checkout\", &opt);\n \t}\n \n \tstrvec_clear(&child_env);\ndiff --git a/commit.c b/commit.c\nindex 087cb19f4f..24ab5c1b50 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1960,5 +1960,5 @@ int run_commit_hook(int editor_is_used, const char *index_file,\n \tva_end(args);\n \n \topt.invoked_hook = invoked_hook;\n-\treturn run_hooks_opt(name, &opt);\n+\treturn run_hooks_opt(the_repository, name, &opt);\n }\ndiff --git a/hook.c b/hook.c\nindex 7e90787bca..a9320cb0ce 100644\n--- a/hook.c\n+++ b/hook.c\n@@ -10,14 +10,14 @@\n #include \"environment.h\"\n #include \"setup.h\"\n \n-const char *find_hook(const char *name)\n+const char *find_hook(struct repository *r, const char *name)\n {\n \tstatic struct strbuf path = STRBUF_INIT;\n \n \tint found_hook;\n \n \tstrbuf_reset(&path);\n-\tstrbuf_git_path(&path, \"hooks/%s\", name);\n+\tstrbuf_repo_git_path(&path, r, \"hooks/%s\", name);\n \tfound_hook = access(path.buf, X_OK) >= 0;\n #ifdef STRIP_EXTENSION\n \tif (!found_hook) {\n@@ -48,9 +48,9 @@ const char *find_hook(const char *name)\n \treturn path.buf;\n }\n \n-int hook_exists(const char *name)\n+int hook_exists(struct repository *r, const char *name)\n {\n-\treturn !!find_hook(name);\n+\treturn !!find_hook(r, name);\n }\n \n static int pick_next_hook(struct child_process *cp,\n@@ -121,7 +121,8 @@ static void run_hooks_opt_clear(struct run_hooks_opt *options)\n \tstrvec_clear(&options->args);\n }\n \n-int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)\n+int run_hooks_opt(struct repository *r, const char *hook_name,\n+\t\t  struct run_hooks_opt *options)\n {\n \tstruct strbuf abs_path = STRBUF_INIT;\n \tstruct hook_cb_data cb_data = {\n@@ -129,7 +130,7 @@ int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)\n \t\t.hook_name = hook_name,\n \t\t.options = options,\n \t};\n-\tconst char *const hook_path = find_hook(hook_name);\n+\tconst char *const hook_path = find_hook(r, hook_name);\n \tint ret = 0;\n \tconst struct run_process_parallel_opts opts = {\n \t\t.tr2_category = \"hook\",\n@@ -173,14 +174,14 @@ int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options)\n \treturn ret;\n }\n \n-int run_hooks(const char *hook_name)\n+int run_hooks(struct repository *r, const char *hook_name)\n {\n \tstruct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;\n \n-\treturn run_hooks_opt(hook_name, &opt);\n+\treturn run_hooks_opt(r, hook_name, &opt);\n }\n \n-int run_hooks_l(const char *hook_name, ...)\n+int run_hooks_l(struct repository *r, const char *hook_name, ...)\n {\n \tstruct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;\n \tva_list ap;\n@@ -191,5 +192,5 @@ int run_hooks_l(const char *hook_name, ...)\n \t\tstrvec_push(&opt.args, arg);\n \tva_end(ap);\n \n-\treturn run_hooks_opt(hook_name, &opt);\n+\treturn run_hooks_opt(r, hook_name, &opt);\n }\ndiff --git a/hook.h b/hook.h\nindex 6511525aeb..11863fa734 100644\n--- a/hook.h\n+++ b/hook.h\n@@ -2,6 +2,8 @@\n #define HOOK_H\n #include \"strvec.h\"\n \n+struct repository;\n+\n struct run_hooks_opt\n {\n \t/* Environment vars to be set for each hook */\n@@ -55,12 +57,12 @@ struct hook_cb_data {\n  * or disabled. Note that this points to static storage that will be\n  * overwritten by further calls to find_hook and run_hook_*.\n  */\n-const char *find_hook(const char *name);\n+const char *find_hook(struct repository *r, const char *name);\n \n /**\n  * A boolean version of find_hook()\n  */\n-int hook_exists(const char *hookname);\n+int hook_exists(struct repository *r, const char *hookname);\n \n /**\n  * Takes a `hook_name`, resolves it to a path with find_hook(), and\n@@ -70,13 +72,14 @@ int hook_exists(const char *hookname);\n  * Returns the status code of the run hook, or a negative value on\n  * error().\n  */\n-int run_hooks_opt(const char *hook_name, struct run_hooks_opt *options);\n+int run_hooks_opt(struct repository *r, const char *hook_name,\n+\t\t  struct run_hooks_opt *options);\n \n /**\n  * A wrapper for run_hooks_opt() which provides a dummy \"struct\n  * run_hooks_opt\" initialized with \"RUN_HOOKS_OPT_INIT\".\n  */\n-int run_hooks(const char *hook_name);\n+int run_hooks(struct repository *r, const char *hook_name);\n \n /**\n  * Like run_hooks(), a wrapper for run_hooks_opt().\n@@ -87,5 +90,5 @@ int run_hooks(const char *hook_name);\n  * hook. This function behaves like the old run_hook_le() API.\n  */\n LAST_ARG_MUST_BE_NULL\n-int run_hooks_l(const char *hook_name, ...);\n+int run_hooks_l(struct repository *r, const char *hook_name, ...);\n #endif\ndiff --git a/read-cache.c b/read-cache.c\nindex 48bf24f87c..742369b295 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -3156,9 +3156,9 @@ static int do_write_locked_index(struct index_state *istate,\n \telse\n \t\tret = close_lock_file_gently(lock);\n \n-\trun_hooks_l(\"post-index-change\",\n-\t\t\tistate->updated_workdir ? \"1\" : \"0\",\n-\t\t\tistate->updated_skipworktree ? \"1\" : \"0\", NULL);\n+\trun_hooks_l(the_repository, \"post-index-change\",\n+\t\t    istate->updated_workdir ? \"1\" : \"0\",\n+\t\t    istate->updated_skipworktree ? \"1\" : \"0\", NULL);\n \tistate->updated_workdir = 0;\n \tistate->updated_skipworktree = 0;\n \ndiff --git a/refs.c b/refs.c\nindex e082fc59b0..0afc70b51b 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -2132,7 +2132,7 @@ static int run_transaction_hook(struct ref_transaction *transaction,\n \tconst char *hook;\n \tint ret = 0, i;\n \n-\thook = find_hook(\"reference-transaction\");\n+\thook = find_hook(transaction->ref_store->repo, \"reference-transaction\");\n \tif (!hook)\n \t\treturn ret;\n \ndiff --git a/reset.c b/reset.c\nindex 9550dea03d..b22b1be792 100644\n--- a/reset.c\n+++ b/reset.c\n@@ -79,7 +79,7 @@ static int update_refs(const struct reset_head_opts *opts,\n \t\t\t\t\t\t reflog_head);\n \t}\n \tif (!ret && run_hook)\n-\t\trun_hooks_l(\"post-checkout\",\n+\t\trun_hooks_l(the_repository, \"post-checkout\",\n \t\t\t    oid_to_hex(head ? head : null_oid()),\n \t\t\t    oid_to_hex(oid), \"1\", NULL);\n \tstrbuf_release(&msg);\ndiff --git a/sequencer.c b/sequencer.c\nindex 0291920f0b..edeeec6f15 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1316,7 +1316,7 @@ static int run_rewrite_hook(const struct object_id *oldoid,\n \tstruct child_process proc = CHILD_PROCESS_INIT;\n \tint code;\n \tstruct strbuf sb = STRBUF_INIT;\n-\tconst char *hook_path = find_hook(\"post-rewrite\");\n+\tconst char *hook_path = find_hook(the_repository, \"post-rewrite\");\n \n \tif (!hook_path)\n \t\treturn 0;\n@@ -1614,7 +1614,7 @@ static int try_to_commit(struct repository *r,\n \t\t}\n \t}\n \n-\tif (hook_exists(\"prepare-commit-msg\")) {\n+\tif (hook_exists(r, \"prepare-commit-msg\")) {\n \t\tres = run_prepare_commit_msg_hook(r, msg, hook_commit);\n \t\tif (res)\n \t\t\tgoto out;\n@@ -5149,7 +5149,7 @@ static int pick_commits(struct repository *r,\n \n \t\t\thook_opt.path_to_stdin = rebase_path_rewritten_list();\n \t\t\tstrvec_push(&hook_opt.args, \"rebase\");\n-\t\t\trun_hooks_opt(\"post-rewrite\", &hook_opt);\n+\t\t\trun_hooks_opt(r, \"post-rewrite\", &hook_opt);\n \t\t}\n \t\tapply_autostash(rebase_path_autostash());\n \ndiff --git a/transport.c b/transport.c\nindex 12cc5b4d96..f8cd2810a5 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -1271,7 +1271,7 @@ static int run_pre_push_hook(struct transport *transport,\n \tstruct ref *r;\n \tstruct child_process proc = CHILD_PROCESS_INIT;\n \tstruct strbuf buf;\n-\tconst char *hook_path = find_hook(\"pre-push\");\n+\tconst char *hook_path = find_hook(the_repository, \"pre-push\");\n \n \tif (!hook_path)\n \t\treturn 0;\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500710","messageId":"bbaa85ebad458c60c59784b690be8be2ddbe76fc.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 05/20] path: stop relying on `the_repository` when reporting garbage","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:31Z","receivedAt":"2024-08-13T09:13:37Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We access `the_repository` in `report_linked_checkout_garbage()` both\ndirectly and indirectly via `get_git_dir()`. Remove this dependency by\ninstead passing a `struct repository` as parameter.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/count-objects.c | 2 +-\n path.c                  | 6 +++---\n path.h                  | 2 +-\n 3 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/count-objects.c b/builtin/count-objects.c\nindex 2d4bb5e8d0..ec6098a149 100644\n--- a/builtin/count-objects.c\n+++ b/builtin/count-objects.c\n@@ -113,7 +113,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(count_objects_usage, opts);\n \tif (verbose) {\n \t\treport_garbage = real_report_garbage;\n-\t\treport_linked_checkout_garbage();\n+\t\treport_linked_checkout_garbage(the_repository);\n \t}\n \n \tfor_each_loose_file_in_objdir(get_object_directory(),\ndiff --git a/path.c b/path.c\nindex 069db6ff8f..97a07fafc7 100644\n--- a/path.c\n+++ b/path.c\n@@ -365,15 +365,15 @@ static void update_common_dir(struct strbuf *buf, int git_dir_len,\n \t\tstrbuf_addstr(buf, LOCK_SUFFIX);\n }\n \n-void report_linked_checkout_garbage(void)\n+void report_linked_checkout_garbage(struct repository *r)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n \tconst struct common_dir *p;\n \tint len;\n \n-\tif (!the_repository->different_commondir)\n+\tif (!r->different_commondir)\n \t\treturn;\n-\tstrbuf_addf(&sb, \"%s/\", get_git_dir());\n+\tstrbuf_addf(&sb, \"%s/\", r->gitdir);\n \tlen = sb.len;\n \tfor (p = common_list; p->path; p++) {\n \t\tconst char *path = p->path;\ndiff --git a/path.h b/path.h\nindex 05aff5f4c3..9a4a4a8fb3 100644\n--- a/path.h\n+++ b/path.h\n@@ -158,7 +158,7 @@ int strbuf_git_path_submodule(struct strbuf *sb, const char *path,\n \t\t\t\t     const char *fmt, ...)\n \t__attribute__((format (printf, 3, 4)));\n \n-void report_linked_checkout_garbage(void);\n+void report_linked_checkout_garbage(struct repository *r);\n \n /*\n  * You can define a static memoized git path like:\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500711","messageId":"29302f4b14c29323bd85f25e0585c5383e7303e0.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 06/20] path: stop relying on `the_repository` in `worktree_git_path()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:37Z","receivedAt":"2024-08-13T09:13:40Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"When not provided a worktree, then `worktree_git_path()` will fall back\nto returning a path relative to the main repository. In this case, we\nimplicitly rely on `the_repository` to derive the path. Remove this\ndependency by passing a `struct repository` as parameter.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fsck.c     |  2 +-\n builtin/worktree.c |  4 ++--\n path.c             |  9 +++++++--\n path.h             |  8 +++++---\n revision.c         |  2 +-\n worktree.c         |  2 +-\n wt-status.c        | 14 +++++++-------\n 7 files changed, 24 insertions(+), 17 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex d13a226c2e..ad36df9628 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -1050,7 +1050,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \t\t\t * and may get overwritten by other calls\n \t\t\t * while we're examining the index.\n \t\t\t */\n-\t\t\tpath = xstrdup(worktree_git_path(wt, \"index\"));\n+\t\t\tpath = xstrdup(worktree_git_path(the_repository, wt, \"index\"));\n \t\t\tread_index_from(&istate, path, get_worktree_git_dir(wt));\n \t\t\tfsck_index(&istate, path, wt->is_current);\n \t\t\tdiscard_index(&istate);\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex a4b7f24e1e..eb0a386992 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -1146,14 +1146,14 @@ static void validate_no_submodules(const struct worktree *wt)\n \tstruct strbuf path = STRBUF_INIT;\n \tint i, found_submodules = 0;\n \n-\tif (is_directory(worktree_git_path(wt, \"modules\"))) {\n+\tif (is_directory(worktree_git_path(the_repository, wt, \"modules\"))) {\n \t\t/*\n \t\t * There could be false positives, e.g. the \"modules\"\n \t\t * directory exists but is empty. But it's a rare case and\n \t\t * this simpler check is probably good enough for now.\n \t\t */\n \t\tfound_submodules = 1;\n-\t} else if (read_index_from(&istate, worktree_git_path(wt, \"index\"),\n+\t} else if (read_index_from(&istate, worktree_git_path(the_repository, wt, \"index\"),\n \t\t\t\t   get_worktree_git_dir(wt)) > 0) {\n \t\tfor (i = 0; i < istate.cache_nr; i++) {\n \t\t\tstruct cache_entry *ce = istate.cache[i];\ndiff --git a/path.c b/path.c\nindex 97a07fafc7..2949261193 100644\n--- a/path.c\n+++ b/path.c\n@@ -512,12 +512,17 @@ const char *mkpath(const char *fmt, ...)\n \treturn cleanup_path(pathname->buf);\n }\n \n-const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)\n+const char *worktree_git_path(struct repository *r,\n+\t\t\t      const struct worktree *wt, const char *fmt, ...)\n {\n \tstruct strbuf *pathname = get_pathname();\n \tva_list args;\n+\n+\tif (wt && wt->repo != r)\n+\t\tBUG(\"worktree not connected to expected repository\");\n+\n \tva_start(args, fmt);\n-\trepo_git_pathv(the_repository, wt, pathname, fmt, args);\n+\trepo_git_pathv(r, wt, pathname, fmt, args);\n \tva_end(args);\n \treturn pathname->buf;\n }\ndiff --git a/path.h b/path.h\nindex 9a4a4a8fb3..78e9230de9 100644\n--- a/path.h\n+++ b/path.h\n@@ -95,11 +95,13 @@ const char *git_path(const char *fmt, ...)\n \n /*\n  * Similar to git_path() but can produce paths for a specified\n- * worktree instead of current one\n+ * worktree instead of current one. When no worktree is given, then the path is\n+ * computed relative to main worktree of the given repository.\n  */\n-const char *worktree_git_path(const struct worktree *wt,\n+const char *worktree_git_path(struct repository *r,\n+\t\t\t      const struct worktree *wt,\n \t\t\t      const char *fmt, ...)\n-\t__attribute__((format (printf, 2, 3)));\n+\t__attribute__((format (printf, 3, 4)));\n \n /*\n  * Return a path into the main repository's (the_repository) git directory.\ndiff --git a/revision.c b/revision.c\nindex 1c0192f522..0b92a13af5 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1872,7 +1872,7 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)\n \t\t\tcontinue; /* current index already taken care of */\n \n \t\tif (read_index_from(&istate,\n-\t\t\t\t    worktree_git_path(wt, \"index\"),\n+\t\t\t\t    worktree_git_path(the_repository, wt, \"index\"),\n \t\t\t\t    get_worktree_git_dir(wt)) > 0)\n \t\t\tdo_add_index_objects_to_pending(revs, &istate, flags);\n \t\tdiscard_index(&istate);\ndiff --git a/worktree.c b/worktree.c\nindex f3c4c8ec54..886c5db691 100644\n--- a/worktree.c\n+++ b/worktree.c\n@@ -252,7 +252,7 @@ const char *worktree_lock_reason(struct worktree *wt)\n \tif (!wt->lock_reason_valid) {\n \t\tstruct strbuf path = STRBUF_INIT;\n \n-\t\tstrbuf_addstr(&path, worktree_git_path(wt, \"locked\"));\n+\t\tstrbuf_addstr(&path, worktree_git_path(the_repository, wt, \"locked\"));\n \t\tif (file_exists(path.buf)) {\n \t\t\tstruct strbuf lock_reason = STRBUF_INIT;\n \t\t\tif (strbuf_read_file(&lock_reason, path.buf, 0) < 0)\ndiff --git a/wt-status.c b/wt-status.c\nindex b778eef989..b477239039 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1618,7 +1618,7 @@ static char *get_branch(const struct worktree *wt, const char *path)\n \tstruct object_id oid;\n \tconst char *branch_name;\n \n-\tif (strbuf_read_file(&sb, worktree_git_path(wt, \"%s\", path), 0) <= 0)\n+\tif (strbuf_read_file(&sb, worktree_git_path(the_repository, wt, \"%s\", path), 0) <= 0)\n \t\tgoto got_nothing;\n \n \twhile (sb.len && sb.buf[sb.len - 1] == '\\n')\n@@ -1716,18 +1716,18 @@ int wt_status_check_rebase(const struct worktree *wt,\n {\n \tstruct stat st;\n \n-\tif (!stat(worktree_git_path(wt, \"rebase-apply\"), &st)) {\n-\t\tif (!stat(worktree_git_path(wt, \"rebase-apply/applying\"), &st)) {\n+\tif (!stat(worktree_git_path(the_repository, wt, \"rebase-apply\"), &st)) {\n+\t\tif (!stat(worktree_git_path(the_repository, wt, \"rebase-apply/applying\"), &st)) {\n \t\t\tstate->am_in_progress = 1;\n-\t\t\tif (!stat(worktree_git_path(wt, \"rebase-apply/patch\"), &st) && !st.st_size)\n+\t\t\tif (!stat(worktree_git_path(the_repository, wt, \"rebase-apply/patch\"), &st) && !st.st_size)\n \t\t\t\tstate->am_empty_patch = 1;\n \t\t} else {\n \t\t\tstate->rebase_in_progress = 1;\n \t\t\tstate->branch = get_branch(wt, \"rebase-apply/head-name\");\n \t\t\tstate->onto = get_branch(wt, \"rebase-apply/onto\");\n \t\t}\n-\t} else if (!stat(worktree_git_path(wt, \"rebase-merge\"), &st)) {\n-\t\tif (!stat(worktree_git_path(wt, \"rebase-merge/interactive\"), &st))\n+\t} else if (!stat(worktree_git_path(the_repository, wt, \"rebase-merge\"), &st)) {\n+\t\tif (!stat(worktree_git_path(the_repository, wt, \"rebase-merge/interactive\"), &st))\n \t\t\tstate->rebase_interactive_in_progress = 1;\n \t\telse\n \t\t\tstate->rebase_in_progress = 1;\n@@ -1743,7 +1743,7 @@ int wt_status_check_bisect(const struct worktree *wt,\n {\n \tstruct stat st;\n \n-\tif (!stat(worktree_git_path(wt, \"BISECT_LOG\"), &st)) {\n+\tif (!stat(worktree_git_path(the_repository, wt, \"BISECT_LOG\"), &st)) {\n \t\tstate->bisect_in_progress = 1;\n \t\tstate->bisecting_from = get_branch(wt, \"BISECT_START\");\n \t\treturn 1;\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500712","messageId":"1b6651770a7aab0885222ad3425918635648e8ac.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 07/20] path: hide functions using `the_repository` by default","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:40Z","receivedAt":"2024-08-13T09:13:43Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The path subsystem provides a bunch of legacy functions that compute\npaths relative to the \"gitdir\" and \"commondir\" directories of the global\n`the_repository` variable. Use of those functions is discouraged, and it\nis easy to miss the implicit dependency on `the_repository` that calls\nto those functions may cause.\n\nWith `USE_THE_REPOSITORY_VARIABLE`, we have recently introduced a tool\nthat allows us to get rid of such functions over time. With this macro,\nwe can hide away functions that have such implicit dependency such that\nother subsystems that want to be free of `the_repository` will not use\nthem by accident.\n\nMove all path-related functions that use `the_repository` into a block\nthat gets only conditionally compiled depending on whether or not the\nmacro has been defined. This also removes all dependencies on that\nvariable in \"path.c\", allowing us to remove the definition of said\npreprocessor macro.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n path.c |  52 +-------------------\n path.h | 147 ++++++++++++++++++++++++++++++++++++++-------------------\n 2 files changed, 100 insertions(+), 99 deletions(-)\n\ndiff --git a/path.c b/path.c\nindex 2949261193..a3bf25b7de 100644\n--- a/path.c\n+++ b/path.c\n@@ -2,8 +2,6 @@\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\"\n@@ -30,7 +28,7 @@ static int get_st_mode_bits(const char *path, int *mode)\n \treturn 0;\n }\n \n-static struct strbuf *get_pathname(void)\n+struct strbuf *get_pathname(void)\n {\n \tstatic struct strbuf pathname_array[4] = {\n \t\tSTRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT\n@@ -453,44 +451,6 @@ void strbuf_repo_git_path(struct strbuf *sb,\n \tva_end(args);\n }\n \n-char *git_path_buf(struct strbuf *buf, const char *fmt, ...)\n-{\n-\tva_list args;\n-\tstrbuf_reset(buf);\n-\tva_start(args, fmt);\n-\trepo_git_pathv(the_repository, NULL, buf, fmt, args);\n-\tva_end(args);\n-\treturn buf->buf;\n-}\n-\n-void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)\n-{\n-\tva_list args;\n-\tva_start(args, fmt);\n-\trepo_git_pathv(the_repository, NULL, sb, fmt, args);\n-\tva_end(args);\n-}\n-\n-const char *git_path(const char *fmt, ...)\n-{\n-\tstruct strbuf *pathname = get_pathname();\n-\tva_list args;\n-\tva_start(args, fmt);\n-\trepo_git_pathv(the_repository, NULL, pathname, fmt, args);\n-\tva_end(args);\n-\treturn pathname->buf;\n-}\n-\n-char *git_pathdup(const char *fmt, ...)\n-{\n-\tstruct strbuf path = STRBUF_INIT;\n-\tva_list args;\n-\tva_start(args, fmt);\n-\trepo_git_pathv(the_repository, NULL, &path, fmt, args);\n-\tva_end(args);\n-\treturn strbuf_detach(&path, NULL);\n-}\n-\n char *mkpathdup(const char *fmt, ...)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n@@ -634,16 +594,6 @@ void repo_common_pathv(const struct repository *repo,\n \tstrbuf_cleanup_path(sb);\n }\n \n-const char *git_common_path(const char *fmt, ...)\n-{\n-\tstruct strbuf *pathname = get_pathname();\n-\tva_list args;\n-\tva_start(args, fmt);\n-\trepo_common_pathv(the_repository, pathname, fmt, args);\n-\tva_end(args);\n-\treturn pathname->buf;\n-}\n-\n void strbuf_git_common_path(struct strbuf *sb,\n \t\t\t    const struct repository *repo,\n \t\t\t    const char *fmt, ...)\ndiff --git a/path.h b/path.h\nindex 78e9230de9..e91d19fff6 100644\n--- a/path.h\n+++ b/path.h\n@@ -25,7 +25,7 @@ char *mkpathdup(const char *fmt, ...)\n \t__attribute__((format (printf, 1, 2)));\n \n /*\n- * The `git_common_path` family of functions will construct a path into a\n+ * The `strbuf_git_common_path` family of functions will construct a path into a\n  * repository's common git directory, which is shared by all worktrees.\n  */\n \n@@ -43,14 +43,7 @@ void repo_common_pathv(const struct repository *repo,\n \t\t       va_list args);\n \n /*\n- * Return a statically allocated path into the main repository's\n- * (the_repository) common git directory.\n- */\n-const char *git_common_path(const char *fmt, ...)\n-\t__attribute__((format (printf, 1, 2)));\n-\n-/*\n- * The `git_path` family of functions will construct a path into a repository's\n+ * The `repo_git_path` family of functions will construct a path into a repository's\n  * git directory.\n  *\n  * These functions will perform adjustments to the resultant path to account\n@@ -87,14 +80,7 @@ void strbuf_repo_git_path(struct strbuf *sb,\n \t__attribute__((format (printf, 3, 4)));\n \n /*\n- * Return a statically allocated path into the main repository's\n- * (the_repository) git directory.\n- */\n-const char *git_path(const char *fmt, ...)\n-\t__attribute__((format (printf, 1, 2)));\n-\n-/*\n- * Similar to git_path() but can produce paths for a specified\n+ * Similar to repo_git_path() but can produce paths for a specified\n  * worktree instead of current one. When no worktree is given, then the path is\n  * computed relative to main worktree of the given repository.\n  */\n@@ -103,27 +89,6 @@ const char *worktree_git_path(struct repository *r,\n \t\t\t      const char *fmt, ...)\n \t__attribute__((format (printf, 3, 4)));\n \n-/*\n- * Return a path into the main repository's (the_repository) git directory.\n- */\n-char *git_pathdup(const char *fmt, ...)\n-\t__attribute__((format (printf, 1, 2)));\n-\n-/*\n- * Construct a path into the main repository's (the_repository) git directory\n- * and place it in the provided buffer `buf`, the contents of the buffer will\n- * be overridden.\n- */\n-char *git_path_buf(struct strbuf *buf, const char *fmt, ...)\n-\t__attribute__((format (printf, 2, 3)));\n-\n-/*\n- * Construct a path into the main repository's (the_repository) git directory\n- * and append it to the provided buffer `sb`.\n- */\n-void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)\n-\t__attribute__((format (printf, 2, 3)));\n-\n /*\n  * Return a path into the worktree of repository `repo`.\n  *\n@@ -165,19 +130,10 @@ void report_linked_checkout_garbage(struct repository *r);\n /*\n  * You can define a static memoized git path like:\n  *\n- *    static GIT_PATH_FUNC(git_path_foo, \"FOO\")\n+ *    static REPO_GIT_PATH_FUNC(git_path_foo, \"FOO\")\n  *\n  * or use one of the global ones below.\n  */\n-#define GIT_PATH_FUNC(func, filename) \\\n-\tconst char *func(void) \\\n-\t{ \\\n-\t\tstatic char *ret; \\\n-\t\tif (!ret) \\\n-\t\t\tret = git_pathdup(filename); \\\n-\t\treturn ret; \\\n-\t}\n-\n #define REPO_GIT_PATH_FUNC(var, filename) \\\n \tconst char *git_path_##var(struct repository *r) \\\n \t{ \\\n@@ -261,4 +217,99 @@ char *xdg_cache_home(const char *filename);\n  */\n void safe_create_dir(const char *dir, int share);\n \n+/*\n+ * Do not use this function. It is only exported to other subsystems until we\n+ * can get rid of the below block of functions that implicitly rely on\n+ * `the_repository`.\n+ */\n+struct strbuf *get_pathname(void);\n+\n+# ifdef USE_THE_REPOSITORY_VARIABLE\n+#  include \"strbuf.h\"\n+#  include \"repository.h\"\n+\n+/*\n+ * Return a statically allocated path into the main repository's\n+ * (the_repository) common git directory.\n+ */\n+__attribute__((format (printf, 1, 2)))\n+static inline const char *git_common_path(const char *fmt, ...)\n+{\n+\tstruct strbuf *pathname = get_pathname();\n+\tva_list args;\n+\tva_start(args, fmt);\n+\trepo_common_pathv(the_repository, pathname, fmt, args);\n+\tva_end(args);\n+\treturn pathname->buf;\n+}\n+\n+/*\n+ * Construct a path into the main repository's (the_repository) git directory\n+ * and place it in the provided buffer `buf`, the contents of the buffer will\n+ * be overridden.\n+ */\n+__attribute__((format (printf, 2, 3)))\n+static inline char *git_path_buf(struct strbuf *buf, const char *fmt, ...)\n+{\n+\tva_list args;\n+\tstrbuf_reset(buf);\n+\tva_start(args, fmt);\n+\trepo_git_pathv(the_repository, NULL, buf, fmt, args);\n+\tva_end(args);\n+\treturn buf->buf;\n+}\n+\n+/*\n+ * Construct a path into the main repository's (the_repository) git directory\n+ * and append it to the provided buffer `sb`.\n+ */\n+__attribute__((format (printf, 2, 3)))\n+static inline void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)\n+{\n+\tva_list args;\n+\tva_start(args, fmt);\n+\trepo_git_pathv(the_repository, NULL, sb, fmt, args);\n+\tva_end(args);\n+}\n+\n+/*\n+ * Return a statically allocated path into the main repository's\n+ * (the_repository) git directory.\n+ */\n+__attribute__((format (printf, 1, 2)))\n+static inline const char *git_path(const char *fmt, ...)\n+{\n+\tstruct strbuf *pathname = get_pathname();\n+\tva_list args;\n+\tva_start(args, fmt);\n+\trepo_git_pathv(the_repository, NULL, pathname, fmt, args);\n+\tva_end(args);\n+\treturn pathname->buf;\n+}\n+\n+#define GIT_PATH_FUNC(func, filename) \\\n+\tconst char *func(void) \\\n+\t{ \\\n+\t\tstatic char *ret; \\\n+\t\tif (!ret) \\\n+\t\t\tret = git_pathdup(filename); \\\n+\t\treturn ret; \\\n+\t}\n+\n+/*\n+ * Return a path into the main repository's (the_repository) git directory.\n+ */\n+__attribute__((format (printf, 1, 2)))\n+static inline char *git_pathdup(const char *fmt, ...)\n+{\n+\tstruct strbuf path = STRBUF_INIT;\n+\tva_list args;\n+\tva_start(args, fmt);\n+\trepo_git_pathv(the_repository, NULL, &path, fmt, args);\n+\tva_end(args);\n+\treturn strbuf_detach(&path, NULL);\n+}\n+\n+# endif /* USE_THE_REPOSITORY_VARIABLE */\n+\n #endif /* PATH_H */\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500713","messageId":"e316491e56a5a53a0fe9bacc0f67eabe5c3ca18b.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 08/20] config: introduce missing setters that take repo as parameter","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:43Z","receivedAt":"2024-08-13T09:13:47Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"While we already provide some of the config-setting interfaces with a\n`struct repository` as parameter, others only have a variant that\nimplicitly depends on `the_repository`. Fill in those gaps such that we\ncan start to deprecate the repo-less variants.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 93 ++++++++++++++++++++++++++++++++++++++++++++------------\n config.h | 15 ++++++++-\n 2 files changed, 87 insertions(+), 21 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 6421894614..ac89b708e7 100644\n--- a/config.c\n+++ b/config.c\n@@ -3178,21 +3178,39 @@ static void maybe_remove_section(struct config_store_data *store,\n \t\t*end_offset = store->parsed[store->parsed_nr - 1].end;\n }\n \n+int repo_config_set_in_file_gently(struct repository *r, const char *config_filename,\n+\t\t\t\t   const char *key, const char *comment, const char *value)\n+{\n+\treturn repo_config_set_multivar_in_file_gently(r, config_filename, key, value, NULL, comment, 0);\n+}\n+\n int git_config_set_in_file_gently(const char *config_filename,\n \t\t\t\t  const char *key, const char *comment, const char *value)\n {\n-\treturn git_config_set_multivar_in_file_gently(config_filename, key, value, NULL, comment, 0);\n+\treturn repo_config_set_in_file_gently(the_repository, config_filename,\n+\t\t\t\t\t      key, comment, value);\n+}\n+\n+void repo_config_set_in_file(struct repository *r, const char *config_filename,\n+\t\t\t     const char *key, const char *value)\n+{\n+\trepo_config_set_multivar_in_file(r, config_filename, key, value, NULL, 0);\n }\n \n void git_config_set_in_file(const char *config_filename,\n \t\t\t    const char *key, const char *value)\n {\n-\tgit_config_set_multivar_in_file(config_filename, key, value, NULL, 0);\n+\trepo_config_set_in_file(the_repository, config_filename, key, value);\n+}\n+\n+int repo_config_set_gently(struct repository *r, const char *key, const char *value)\n+{\n+\treturn repo_config_set_multivar_gently(r, key, value, NULL, 0);\n }\n \n int git_config_set_gently(const char *key, const char *value)\n {\n-\treturn git_config_set_multivar_gently(key, value, NULL, 0);\n+\treturn repo_config_set_gently(the_repository, key, value);\n }\n \n int repo_config_set_worktree_gently(struct repository *r,\n@@ -3209,13 +3227,18 @@ int repo_config_set_worktree_gently(struct repository *r,\n \treturn repo_config_set_multivar_gently(r, key, value, NULL, 0);\n }\n \n-void git_config_set(const char *key, const char *value)\n+void repo_config_set(struct repository *r, const char *key, const char *value)\n {\n-\tgit_config_set_multivar(key, value, NULL, 0);\n+\trepo_config_set_multivar(r, key, value, NULL, 0);\n \n \ttrace2_cmd_set_config(key, value);\n }\n \n+void git_config_set(const char *key, const char *value)\n+{\n+\trepo_config_set(the_repository, key, value);\n+}\n+\n char *git_config_prepare_comment_string(const char *comment)\n {\n \tsize_t leading_blanks;\n@@ -3293,11 +3316,12 @@ static void validate_comment_string(const char *comment)\n  * - the config file is removed and the lock file rename()d to it.\n  *\n  */\n-int git_config_set_multivar_in_file_gently(const char *config_filename,\n-\t\t\t\t\t   const char *key, const char *value,\n-\t\t\t\t\t   const char *value_pattern,\n-\t\t\t\t\t   const char *comment,\n-\t\t\t\t\t   unsigned flags)\n+int repo_config_set_multivar_in_file_gently(struct repository *r,\n+\t\t\t\t\t    const char *config_filename,\n+\t\t\t\t\t    const char *key, const char *value,\n+\t\t\t\t\t    const char *value_pattern,\n+\t\t\t\t\t    const char *comment,\n+\t\t\t\t\t    unsigned flags)\n {\n \tint fd = -1, in_fd = -1;\n \tint ret;\n@@ -3317,7 +3341,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,\n \tstore.multi_replace = (flags & CONFIG_FLAGS_MULTI_REPLACE) != 0;\n \n \tif (!config_filename)\n-\t\tconfig_filename = filename_buf = git_pathdup(\"config\");\n+\t\tconfig_filename = filename_buf = repo_git_path(r, \"config\");\n \n \t/*\n \t * The lock serves a purpose in addition to locking: the new\n@@ -3526,7 +3550,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,\n \tret = 0;\n \n \t/* Invalidate the config cache */\n-\tgit_config_clear();\n+\trepo_config_clear(r);\n \n out_free:\n \trollback_lock_file(&lock);\n@@ -3543,12 +3567,24 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,\n \tgoto out_free;\n }\n \n-void git_config_set_multivar_in_file(const char *config_filename,\n-\t\t\t\t     const char *key, const char *value,\n-\t\t\t\t     const char *value_pattern, unsigned flags)\n+int git_config_set_multivar_in_file_gently(const char *config_filename,\n+\t\t\t\t\t   const char *key, const char *value,\n+\t\t\t\t\t   const char *value_pattern,\n+\t\t\t\t\t   const char *comment,\n+\t\t\t\t\t   unsigned flags)\n {\n-\tif (!git_config_set_multivar_in_file_gently(config_filename, key, value,\n-\t\t\t\t\t\t    value_pattern, NULL, flags))\n+\treturn repo_config_set_multivar_in_file_gently(the_repository, config_filename,\n+\t\t\t\t\t\t       key, value, value_pattern,\n+\t\t\t\t\t\t       comment, flags);\n+}\n+\n+void repo_config_set_multivar_in_file(struct repository *r,\n+\t\t\t\t      const char *config_filename,\n+\t\t\t\t      const char *key, const char *value,\n+\t\t\t\t      const char *value_pattern, unsigned flags)\n+{\n+\tif (!repo_config_set_multivar_in_file_gently(r, config_filename, key, value,\n+\t\t\t\t\t\t     value_pattern, NULL, flags))\n \t\treturn;\n \tif (value)\n \t\tdie(_(\"could not set '%s' to '%s'\"), key, value);\n@@ -3556,6 +3592,14 @@ void git_config_set_multivar_in_file(const char *config_filename,\n \t\tdie(_(\"could not unset '%s'\"), key);\n }\n \n+void git_config_set_multivar_in_file(const char *config_filename,\n+\t\t\t\t     const char *key, const char *value,\n+\t\t\t\t     const char *value_pattern, unsigned flags)\n+{\n+\trepo_config_set_multivar_in_file(the_repository, config_filename,\n+\t\t\t\t\t key, value, value_pattern, flags);\n+}\n+\n int git_config_set_multivar_gently(const char *key, const char *value,\n \t\t\t\t   const char *value_pattern, unsigned flags)\n {\n@@ -3576,12 +3620,21 @@ int repo_config_set_multivar_gently(struct repository *r, const char *key,\n \treturn res;\n }\n \n+void repo_config_set_multivar(struct repository *r,\n+\t\t\t      const char *key, const char *value,\n+\t\t\t      const char *value_pattern, unsigned flags)\n+{\n+\tchar *file = repo_git_path(r, \"config\");\n+\tgit_config_set_multivar_in_file(file, key, value,\n+\t\t\t\t\tvalue_pattern, flags);\n+\tfree(file);\n+}\n+\n void git_config_set_multivar(const char *key, const char *value,\n \t\t\t     const char *value_pattern, unsigned flags)\n {\n-\tgit_config_set_multivar_in_file(git_path(\"config\"),\n-\t\t\t\t\tkey, value, value_pattern,\n-\t\t\t\t\tflags);\n+\trepo_config_set_multivar(the_repository, key, value,\n+\t\t\t\t value_pattern, flags);\n }\n \n static size_t section_name_match (const char *buf, const char *name)\ndiff --git a/config.h b/config.h\nindex 54b47dec9e..b13e1bfb8d 100644\n--- a/config.h\n+++ b/config.h\n@@ -298,14 +298,18 @@ int git_config_pathname(char **, const char *, const char *);\n int git_config_expiry_date(timestamp_t *, const char *, const char *);\n int git_config_color(char *, const char *, const char *);\n int git_config_set_in_file_gently(const char *, const char *, const char *, const char *);\n+int repo_config_set_in_file_gently(struct repository *r, const char *config_filename,\n+\t\t\t\t   const char *key, const char *comment, const char *value);\n \n /**\n  * write config values to a specific config file, takes a key/value pair as\n  * parameter.\n  */\n void git_config_set_in_file(const char *, const char *, const char *);\n+void repo_config_set_in_file(struct repository *, const char *, const char *, const char *);\n \n int git_config_set_gently(const char *, const char *);\n+int repo_config_set_gently(struct repository *r, const char *, const char *);\n \n /**\n  * Write a config value that should apply to the current worktree. If\n@@ -318,6 +322,7 @@ int repo_config_set_worktree_gently(struct repository *, const char *, const cha\n  * write config values to `.git/config`, takes a key/value pair as parameter.\n  */\n void git_config_set(const char *, const char *);\n+void repo_config_set(struct repository *, const char *, const char *);\n \n int git_config_parse_key(const char *, char **, size_t *);\n \n@@ -341,9 +346,11 @@ int git_config_parse_key(const char *, char **, size_t *);\n #define CONFIG_FLAGS_FIXED_VALUE (1 << 1)\n \n int git_config_set_multivar_gently(const char *, const char *, const char *, unsigned);\n-void git_config_set_multivar(const char *, const char *, const char *, unsigned);\n int repo_config_set_multivar_gently(struct repository *, const char *, const char *, const char *, unsigned);\n+void git_config_set_multivar(const char *, const char *, const char *, unsigned);\n+void repo_config_set_multivar(struct repository *r, const char *, const char *, const char *, unsigned);\n int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, const char *, unsigned);\n+int repo_config_set_multivar_in_file_gently(struct repository *, const char *, const char *, const char *, const char *, const char *, unsigned);\n \n char *git_config_prepare_comment_string(const char *);\n \n@@ -372,6 +379,12 @@ void git_config_set_multivar_in_file(const char *config_filename,\n \t\t\t\t     const char *value,\n \t\t\t\t     const char *value_pattern,\n \t\t\t\t     unsigned flags);\n+void repo_config_set_multivar_in_file(struct repository *r,\n+\t\t\t\t      const char *config_filename,\n+\t\t\t\t      const char *key,\n+\t\t\t\t      const char *value,\n+\t\t\t\t      const char *value_pattern,\n+\t\t\t\t      unsigned flags);\n \n /**\n  * rename or remove sections in the config file\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500714","messageId":"5e73ef6cec809a3f1009d302b8721b56b048898d.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 09/20] config: expose `repo_config_clear()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:46Z","receivedAt":"2024-08-13T09:13:50Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"While we already have `repo_config_clear()` as an alternative to\n`git_config_clear()` that doesn't rely on `the_repository`, it is not\nexposed to callers outside of the config subsystem. Do so.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 2 +-\n config.h | 1 +\n 2 files changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/config.c b/config.c\nindex ac89b708e7..476cd73c9e 100644\n--- a/config.c\n+++ b/config.c\n@@ -2564,7 +2564,7 @@ static void git_config_check_init(struct repository *repo)\n \trepo_read_config(repo);\n }\n \n-static void repo_config_clear(struct repository *repo)\n+void repo_config_clear(struct repository *repo)\n {\n \tif (!repo->config || !repo->config->hash_initialized)\n \t\treturn;\ndiff --git a/config.h b/config.h\nindex b13e1bfb8d..8eb3efa0c4 100644\n--- a/config.h\n+++ b/config.h\n@@ -651,6 +651,7 @@ int git_config_get_string_multi(const char *key,\n  * Resets and invalidates the config cache.\n  */\n void git_config_clear(void);\n+void repo_config_clear(struct repository *repo);\n \n /**\n  * Allocates and copies the retrieved string into the `dest` parameter for\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500715","messageId":"35e0f4579cdd17ec098f210e9f00079d412a4180.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 10/20] config: pass repo to `git_config_get_index_threads()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:49Z","receivedAt":"2024-08-13T09:13:54Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_config_get_index_threads()` to accept a `struct\nrepository` such that we can get rid of the implicit dependency on\n`the_repository`. Rename the function accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c     | 4 ++--\n config.h     | 2 +-\n read-cache.c | 8 ++++----\n 3 files changed, 7 insertions(+), 7 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 476cd73c9e..387c7282e9 100644\n--- a/config.c\n+++ b/config.c\n@@ -2826,7 +2826,7 @@ int git_config_get_max_percent_split_change(void)\n \treturn -1; /* default value */\n }\n \n-int git_config_get_index_threads(int *dest)\n+int repo_config_get_index_threads(struct repository *r, int *dest)\n {\n \tint is_bool, val;\n \n@@ -2836,7 +2836,7 @@ int git_config_get_index_threads(int *dest)\n \t\treturn 0;\n \t}\n \n-\tif (!git_config_get_bool_or_int(\"index.threads\", &is_bool, &val)) {\n+\tif (!repo_config_get_bool_or_int(r, \"index.threads\", &is_bool, &val)) {\n \t\tif (is_bool)\n \t\t\t*dest = val ? 0 : 1;\n \t\telse\ndiff --git a/config.h b/config.h\nindex 8eb3efa0c4..3f68b30047 100644\n--- a/config.h\n+++ b/config.h\n@@ -710,7 +710,7 @@ int git_config_get_maybe_bool(const char *key, int *dest);\n  */\n int git_config_get_pathname(const char *key, char **dest);\n \n-int git_config_get_index_threads(int *dest);\n+int repo_config_get_index_threads(struct repository *r, int *dest);\n int git_config_get_split_index(void);\n int git_config_get_max_percent_split_change(void);\n \ndiff --git a/read-cache.c b/read-cache.c\nindex 742369b295..ad09950153 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -2267,7 +2267,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n \n \tsrc_offset = sizeof(*hdr);\n \n-\tif (git_config_get_index_threads(&nr_threads))\n+\tif (repo_config_get_index_threads(the_repository, &nr_threads))\n \t\tnr_threads = 1;\n \n \t/* TODO: does creating more threads than cores help? */\n@@ -2787,7 +2787,7 @@ static int record_eoie(void)\n \t * used for threading is written by default if the user\n \t * explicitly requested threaded index reads.\n \t */\n-\treturn !git_config_get_index_threads(&val) && val != 1;\n+\treturn !repo_config_get_index_threads(the_repository, &val) && val != 1;\n }\n \n static int record_ieot(void)\n@@ -2802,7 +2802,7 @@ static int record_ieot(void)\n \t * written by default if the user explicitly requested\n \t * threaded index reads.\n \t */\n-\treturn !git_config_get_index_threads(&val) && val != 1;\n+\treturn !repo_config_get_index_threads(the_repository, &val) && val != 1;\n }\n \n enum write_extensions {\n@@ -2875,7 +2875,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,\n \n \thashwrite(f, &hdr, sizeof(hdr));\n \n-\tif (!HAVE_THREADS || git_config_get_index_threads(&nr_threads))\n+\tif (!HAVE_THREADS || repo_config_get_index_threads(the_repository, &nr_threads))\n \t\tnr_threads = 1;\n \n \tif (nr_threads != 1 && record_ieot()) {\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500716","messageId":"a88ed83b970eff7dedc55862f59ee4cbfccd623e.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 11/20] config: pass repo to `git_config_get_split_index()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:54Z","receivedAt":"2024-08-13T09:13:57Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_config_get_split_index()` to accept a `struct repository`\nsuch that we can get rid of the implicit dependency on `the_repository`.\nRename the function accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/update-index.c | 4 ++--\n config.c               | 4 ++--\n config.h               | 2 +-\n read-cache.c           | 2 +-\n 4 files changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/update-index.c b/builtin/update-index.c\nindex d343416ae2..35a1f957ad 100644\n--- a/builtin/update-index.c\n+++ b/builtin/update-index.c\n@@ -1156,7 +1156,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \tend_odb_transaction();\n \n \tif (split_index > 0) {\n-\t\tif (git_config_get_split_index() == 0)\n+\t\tif (repo_config_get_split_index(the_repository) == 0)\n \t\t\twarning(_(\"core.splitIndex is set to false; \"\n \t\t\t\t  \"remove or change it, if you really want to \"\n \t\t\t\t  \"enable split index\"));\n@@ -1165,7 +1165,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)\n \t\telse\n \t\t\tadd_split_index(the_repository->index);\n \t} else if (!split_index) {\n-\t\tif (git_config_get_split_index() == 1)\n+\t\tif (repo_config_get_split_index(the_repository) == 1)\n \t\t\twarning(_(\"core.splitIndex is set to true; \"\n \t\t\t\t  \"remove or change it, if you really want to \"\n \t\t\t\t  \"disable split index\"));\ndiff --git a/config.c b/config.c\nindex 387c7282e9..89fb7ce6b1 100644\n--- a/config.c\n+++ b/config.c\n@@ -2801,11 +2801,11 @@ int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestam\n \treturn -1; /* thing exists but cannot be parsed */\n }\n \n-int git_config_get_split_index(void)\n+int repo_config_get_split_index(struct repository *r)\n {\n \tint val;\n \n-\tif (!git_config_get_maybe_bool(\"core.splitindex\", &val))\n+\tif (!repo_config_get_maybe_bool(r, \"core.splitindex\", &val))\n \t\treturn val;\n \n \treturn -1; /* default value */\ndiff --git a/config.h b/config.h\nindex 3f68b30047..35cee9d4ca 100644\n--- a/config.h\n+++ b/config.h\n@@ -711,7 +711,7 @@ int git_config_get_maybe_bool(const char *key, int *dest);\n int git_config_get_pathname(const char *key, char **dest);\n \n int repo_config_get_index_threads(struct repository *r, int *dest);\n-int git_config_get_split_index(void);\n+int repo_config_get_split_index(struct repository *r);\n int git_config_get_max_percent_split_change(void);\n \n /* This dies if the configured or default date is in the future */\ndiff --git a/read-cache.c b/read-cache.c\nindex ad09950153..12c2da5a8b 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1945,7 +1945,7 @@ static void tweak_untracked_cache(struct index_state *istate)\n \n static void tweak_split_index(struct index_state *istate)\n {\n-\tswitch (git_config_get_split_index()) {\n+\tswitch (repo_config_get_split_index(the_repository)) {\n \tcase -1: /* unset: do nothing */\n \t\tbreak;\n \tcase 0: /* false */\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500717","messageId":"17c5420d6386f46a730940de15eed03d2f9db75a.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 12/20] config: pass repo to `git_config_get_max_percent_split_change()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:57Z","receivedAt":"2024-08-13T09:14:00Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_config_get_max_percent_split_change()` to accept a `struct\nrepository` such that we can get rid of the implicit dependency on\n`the_repository`. Rename the function accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c     | 4 ++--\n config.h     | 2 +-\n read-cache.c | 2 +-\n 3 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 89fb7ce6b1..f1d2fb6d4c 100644\n--- a/config.c\n+++ b/config.c\n@@ -2811,11 +2811,11 @@ int repo_config_get_split_index(struct repository *r)\n \treturn -1; /* default value */\n }\n \n-int git_config_get_max_percent_split_change(void)\n+int repo_config_get_max_percent_split_change(struct repository *r)\n {\n \tint val = -1;\n \n-\tif (!git_config_get_int(\"splitindex.maxpercentchange\", &val)) {\n+\tif (!repo_config_get_int(r, \"splitindex.maxpercentchange\", &val)) {\n \t\tif (0 <= val && val <= 100)\n \t\t\treturn val;\n \ndiff --git a/config.h b/config.h\nindex 35cee9d4ca..dd7127b8e9 100644\n--- a/config.h\n+++ b/config.h\n@@ -712,7 +712,7 @@ int git_config_get_pathname(const char *key, char **dest);\n \n int repo_config_get_index_threads(struct repository *r, int *dest);\n int repo_config_get_split_index(struct repository *r);\n-int git_config_get_max_percent_split_change(void);\n+int repo_config_get_max_percent_split_change(struct repository *r);\n \n /* This dies if the configured or default date is in the future */\n int git_config_get_expiry(const char *key, const char **output);\ndiff --git a/read-cache.c b/read-cache.c\nindex 12c2da5a8b..1e52db7f36 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -3275,7 +3275,7 @@ static const int default_max_percent_split_change = 20;\n static int too_many_not_shared_entries(struct index_state *istate)\n {\n \tint i, not_shared = 0;\n-\tint max_split = git_config_get_max_percent_split_change();\n+\tint max_split = repo_config_get_max_percent_split_change(the_repository);\n \n \tswitch (max_split) {\n \tcase -1:\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500718","messageId":"f39d4a32440dcebdad6084f570723d967abbde17.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 13/20] config: pass repo to `git_config_get_expiry()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:13:59Z","receivedAt":"2024-08-13T09:14:02Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_config_get_expiry()` to accept a `struct repository` such\nthat we can get rid of the implicit dependency on `the_repository`.\nRename the function accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/gc.c | 6 +++---\n config.c     | 4 ++--\n config.h     | 2 +-\n read-cache.c | 4 ++--\n 4 files changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex 2ca6288c6b..dc87c65906 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -167,9 +167,9 @@ static void gc_config(void)\n \tgit_config_get_bool(\"gc.autodetach\", &detach_auto);\n \tgit_config_get_bool(\"gc.cruftpacks\", &cruft_packs);\n \tgit_config_get_ulong(\"gc.maxcruftsize\", &max_cruft_size);\n-\tgit_config_get_expiry(\"gc.pruneexpire\", &prune_expire);\n-\tgit_config_get_expiry(\"gc.worktreepruneexpire\", &prune_worktrees_expire);\n-\tgit_config_get_expiry(\"gc.logexpiry\", &gc_log_expire);\n+\trepo_config_get_expiry(the_repository, \"gc.pruneexpire\", &prune_expire);\n+\trepo_config_get_expiry(the_repository, \"gc.worktreepruneexpire\", &prune_worktrees_expire);\n+\trepo_config_get_expiry(the_repository, \"gc.logexpiry\", &gc_log_expire);\n \n \tgit_config_get_ulong(\"gc.bigpackthreshold\", &big_pack_threshold);\n \tgit_config_get_ulong(\"pack.deltacachesize\", &max_delta_cache_size);\ndiff --git a/config.c b/config.c\nindex f1d2fb6d4c..4138dc50ce 100644\n--- a/config.c\n+++ b/config.c\n@@ -2766,9 +2766,9 @@ int git_config_get_pathname(const char *key, char **dest)\n \treturn repo_config_get_pathname(the_repository, key, dest);\n }\n \n-int git_config_get_expiry(const char *key, const char **output)\n+int repo_config_get_expiry(struct repository *r, const char *key, const char **output)\n {\n-\tint ret = git_config_get_string(key, (char **)output);\n+\tint ret = repo_config_get_string(r, key, (char **)output);\n \tif (ret)\n \t\treturn ret;\n \tif (strcmp(*output, \"now\")) {\ndiff --git a/config.h b/config.h\nindex dd7127b8e9..7674617a1d 100644\n--- a/config.h\n+++ b/config.h\n@@ -715,7 +715,7 @@ int repo_config_get_split_index(struct repository *r);\n int repo_config_get_max_percent_split_change(struct repository *r);\n \n /* This dies if the configured or default date is in the future */\n-int git_config_get_expiry(const char *key, const char **output);\n+int repo_config_get_expiry(struct repository *r, const char *key, const char **output);\n \n /* parse either \"this many days\" integer, or \"5.days.ago\" approxidate */\n int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now);\ndiff --git a/read-cache.c b/read-cache.c\nindex 1e52db7f36..18394d7180 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -3184,8 +3184,8 @@ static unsigned long get_shared_index_expire_date(void)\n \tstatic int shared_index_expire_date_prepared;\n \n \tif (!shared_index_expire_date_prepared) {\n-\t\tgit_config_get_expiry(\"splitindex.sharedindexexpire\",\n-\t\t\t\t      &shared_index_expire);\n+\t\trepo_config_get_expiry(the_repository, \"splitindex.sharedindexexpire\",\n+\t\t\t\t       &shared_index_expire);\n \t\tshared_index_expire_date = approxidate(shared_index_expire);\n \t\tshared_index_expire_date_prepared = 1;\n \t}\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500719","messageId":"111f77e653a2f67e4f315ba553d65155bbc75066.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 14/20] config: pass repo to `git_config_get_expiry_in_days()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:14:03Z","receivedAt":"2024-08-13T09:14:07Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_config_get_expiry_in_days()` to accept a `struct\nrepository` such that we can get rid of the implicit dependency on\n`the_repository`. Rename the function accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 5 +++--\n config.h | 3 ++-\n rerere.c | 6 ++++--\n 3 files changed, 9 insertions(+), 5 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 4138dc50ce..33d9af29c8 100644\n--- a/config.c\n+++ b/config.c\n@@ -2779,13 +2779,14 @@ int repo_config_get_expiry(struct repository *r, const char *key, const char **o\n \treturn ret;\n }\n \n-int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestamp_t now)\n+int repo_config_get_expiry_in_days(struct repository *r, const char *key,\n+\t\t\t\t   timestamp_t *expiry, timestamp_t now)\n {\n \tconst char *expiry_string;\n \tintmax_t days;\n \ttimestamp_t when;\n \n-\tif (git_config_get_string_tmp(key, &expiry_string))\n+\tif (repo_config_get_string_tmp(r, key, &expiry_string))\n \t\treturn 1; /* no such thing */\n \n \tif (git_parse_signed(expiry_string, &days, maximum_signed_value_of_type(int))) {\ndiff --git a/config.h b/config.h\nindex 7674617a1d..3a5016afea 100644\n--- a/config.h\n+++ b/config.h\n@@ -718,7 +718,8 @@ int repo_config_get_max_percent_split_change(struct repository *r);\n int repo_config_get_expiry(struct repository *r, const char *key, const char **output);\n \n /* parse either \"this many days\" integer, or \"5.days.ago\" approxidate */\n-int git_config_get_expiry_in_days(const char *key, timestamp_t *, timestamp_t now);\n+int repo_config_get_expiry_in_days(struct repository *r, const char *key,\n+\t\t\t\t   timestamp_t *, timestamp_t now);\n \n /**\n  * First prints the error message specified by the caller in `err` and then\ndiff --git a/rerere.c b/rerere.c\nindex 3a3888cce2..578a4fe378 100644\n--- a/rerere.c\n+++ b/rerere.c\n@@ -1203,8 +1203,10 @@ void rerere_gc(struct repository *r, struct string_list *rr)\n \tif (setup_rerere(r, rr, 0) < 0)\n \t\treturn;\n \n-\tgit_config_get_expiry_in_days(\"gc.rerereresolved\", &cutoff_resolve, now);\n-\tgit_config_get_expiry_in_days(\"gc.rerereunresolved\", &cutoff_noresolve, now);\n+\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereresolved\",\n+\t\t\t\t       &cutoff_resolve, now);\n+\trepo_config_get_expiry_in_days(the_repository, \"gc.rerereunresolved\",\n+\t\t\t\t       &cutoff_noresolve, now);\n \tgit_config(git_default_config, NULL);\n \tdir = opendir(git_path(\"rr-cache\"));\n \tif (!dir)\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500720","messageId":"6adee5633a7093f62c7b3041ae23afb528bb9452.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 15/20] config: pass repo to `git_die_config()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:14:07Z","receivedAt":"2024-08-13T09:14:13Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor `git_die_config()` to accept a `struct repository` such that we\ncan get rid of the implicit dependency on `the_repository`. Rename the\nfunction accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/fast-import.c |  4 ++--\n builtin/notes.c       |  2 +-\n config.c              | 12 ++++++------\n config.h              |  3 ++-\n 4 files changed, 11 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/fast-import.c b/builtin/fast-import.c\nindex d21c4053a7..0249503c70 100644\n--- a/builtin/fast-import.c\n+++ b/builtin/fast-import.c\n@@ -3481,8 +3481,8 @@ static void git_pack_config(void)\n \tif (!git_config_get_int(\"pack.indexversion\", &indexversion_value)) {\n \t\tpack_idx_opts.version = indexversion_value;\n \t\tif (pack_idx_opts.version > 2)\n-\t\t\tgit_die_config(\"pack.indexversion\",\n-\t\t\t\t\t\"bad pack.indexVersion=%\"PRIu32, pack_idx_opts.version);\n+\t\t\tgit_die_config(the_repository, \"pack.indexversion\",\n+\t\t\t\t       \"bad pack.indexVersion=%\"PRIu32, pack_idx_opts.version);\n \t}\n \tif (!git_config_get_ulong(\"pack.packsizelimit\", &packsizelimit_value))\n \t\tmax_packsize = packsizelimit_value;\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex d9c356e354..c0fa86d847 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -868,7 +868,7 @@ static int git_config_get_notes_strategy(const char *key,\n \tif (git_config_get_string(key, &value))\n \t\treturn 1;\n \tif (parse_notes_merge_strategy(value, strategy))\n-\t\tgit_die_config(key, _(\"unknown notes merge strategy %s\"), value);\n+\t\tgit_die_config(the_repository, key, _(\"unknown notes merge strategy %s\"), value);\n \n \tfree(value);\n \treturn 0;\ndiff --git a/config.c b/config.c\nindex 33d9af29c8..e35fc90238 100644\n--- a/config.c\n+++ b/config.c\n@@ -2611,7 +2611,7 @@ int repo_config_get_string(struct repository *repo,\n \tgit_config_check_init(repo);\n \tret = git_configset_get_string(repo->config, key, dest);\n \tif (ret < 0)\n-\t\tgit_die_config(key, NULL);\n+\t\tgit_die_config(repo, key, NULL);\n \treturn ret;\n }\n \n@@ -2622,7 +2622,7 @@ int repo_config_get_string_tmp(struct repository *repo,\n \tgit_config_check_init(repo);\n \tret = git_configset_get_string_tmp(repo->config, key, dest);\n \tif (ret < 0)\n-\t\tgit_die_config(key, NULL);\n+\t\tgit_die_config(repo, key, NULL);\n \treturn ret;\n }\n \n@@ -2668,7 +2668,7 @@ int repo_config_get_pathname(struct repository *repo,\n \tgit_config_check_init(repo);\n \tret = git_configset_get_pathname(repo->config, key, dest);\n \tif (ret < 0)\n-\t\tgit_die_config(key, NULL);\n+\t\tgit_die_config(repo, key, NULL);\n \treturn ret;\n }\n \n@@ -2774,7 +2774,7 @@ int repo_config_get_expiry(struct repository *r, const char *key, const char **o\n \tif (strcmp(*output, \"now\")) {\n \t\ttimestamp_t now = approxidate(\"now\");\n \t\tif (approxidate(*output) >= now)\n-\t\t\tgit_die_config(key, _(\"Invalid %s: '%s'\"), key, *output);\n+\t\t\tgit_die_config(r, key, _(\"Invalid %s: '%s'\"), key, *output);\n \t}\n \treturn ret;\n }\n@@ -2858,7 +2858,7 @@ void git_die_config_linenr(const char *key, const char *filename, int linenr)\n \t\t    key, filename, linenr);\n }\n \n-void git_die_config(const char *key, const char *err, ...)\n+void git_die_config(struct repository *r, const char *key, const char *err, ...)\n {\n \tconst struct string_list *values;\n \tstruct key_value_info *kv_info;\n@@ -2870,7 +2870,7 @@ void git_die_config(const char *key, const char *err, ...)\n \t\terror_fn(err, params);\n \t\tva_end(params);\n \t}\n-\tif (git_config_get_value_multi(key, &values))\n+\tif (repo_config_get_value_multi(r, key, &values))\n \t\tBUG(\"for key '%s' we must have a value to report on\", key);\n \tkv_info = values->items[values->nr - 1].util;\n \tgit_die_config_linenr(key, kv_info->filename, kv_info->linenr);\ndiff --git a/config.h b/config.h\nindex 3a5016afea..947307c591 100644\n--- a/config.h\n+++ b/config.h\n@@ -726,7 +726,8 @@ int repo_config_get_expiry_in_days(struct repository *r, const char *key,\n  * dies printing the line number and the file name of the highest priority\n  * value for the configuration variable `key`.\n  */\n-NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));\n+NORETURN void git_die_config(struct repository *r, const char *key, const char *err, ...)\n+\t__attribute__((format(printf, 3, 4)));\n \n /**\n  * Helper function which formats the die error message according to the\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500721","messageId":"b8c54b751c2b1af77b1fb6b324ca845ccdeeb669.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 16/20] config: pass repo to functions that rename or copy sections","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:14:12Z","receivedAt":"2024-08-13T09:14:15Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Refactor functions that rename or copy config sections to accept a\n`struct repository` such that we can get rid of the implicit dependency\non `the_repository`. Rename the functions accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n builtin/branch.c            |  7 ++++---\n builtin/config.c            | 16 ++++++++--------\n builtin/remote.c            |  4 ++--\n builtin/submodule--helper.c |  2 +-\n config.c                    | 30 ++++++++++++++++--------------\n config.h                    |  8 ++++----\n submodule.c                 |  2 +-\n 7 files changed, 36 insertions(+), 33 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 48cac74f97..3f870741bf 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -210,7 +210,7 @@ static void delete_branch_config(const char *branchname)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n \tstrbuf_addf(&buf, \"branch.%s\", branchname);\n-\tif (git_config_rename_section(buf.buf, NULL) < 0)\n+\tif (repo_config_rename_section(the_repository, buf.buf, NULL) < 0)\n \t\twarning(_(\"update of config-file failed\"));\n \tstrbuf_release(&buf);\n }\n@@ -659,9 +659,10 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int\n \n \tstrbuf_addf(&oldsection, \"branch.%s\", interpreted_oldname);\n \tstrbuf_addf(&newsection, \"branch.%s\", interpreted_newname);\n-\tif (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0)\n+\tif (!copy && repo_config_rename_section(the_repository, oldsection.buf, newsection.buf) < 0)\n \t\tdie(_(\"branch is renamed, but update of config-file failed\"));\n-\tif (copy && strcmp(interpreted_oldname, interpreted_newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0)\n+\tif (copy && strcmp(interpreted_oldname, interpreted_newname) &&\n+\t    repo_config_copy_section(the_repository, oldsection.buf, newsection.buf) < 0)\n \t\tdie(_(\"branch is copied, but update of config-file failed\"));\n \tstrbuf_release(&oldref);\n \tstrbuf_release(&newref);\ndiff --git a/builtin/config.c b/builtin/config.c\nindex 20a0b64090..e00d983596 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -1026,8 +1026,8 @@ static int cmd_config_rename_section(int argc, const char **argv, const char *pr\n \tlocation_options_init(&location_opts, prefix);\n \tcheck_write(&location_opts.source);\n \n-\tret = git_config_rename_section_in_file(location_opts.source.file,\n-\t\t\t\t\t\targv[0], argv[1]);\n+\tret = repo_config_rename_section_in_file(the_repository, location_opts.source.file,\n+\t\t\t\t\t\t argv[0], argv[1]);\n \tif (ret < 0)\n \t\tgoto out;\n \telse if (!ret)\n@@ -1055,8 +1055,8 @@ static int cmd_config_remove_section(int argc, const char **argv, const char *pr\n \tlocation_options_init(&location_opts, prefix);\n \tcheck_write(&location_opts.source);\n \n-\tret = git_config_rename_section_in_file(location_opts.source.file,\n-\t\t\t\t\t\targv[0], NULL);\n+\tret = repo_config_rename_section_in_file(the_repository, location_opts.source.file,\n+\t\t\t\t\t\t argv[0], NULL);\n \tif (ret < 0)\n \t\tgoto out;\n \telse if (!ret)\n@@ -1353,8 +1353,8 @@ static int cmd_config_actions(int argc, const char **argv, const char *prefix)\n \telse if (actions == ACTION_RENAME_SECTION) {\n \t\tcheck_write(&location_opts.source);\n \t\tcheck_argc(argc, 2, 2);\n-\t\tret = git_config_rename_section_in_file(location_opts.source.file,\n-\t\t\t\t\t\t\targv[0], argv[1]);\n+\t\tret = repo_config_rename_section_in_file(the_repository, location_opts.source.file,\n+\t\t\t\t\t\t\t argv[0], argv[1]);\n \t\tif (ret < 0)\n \t\t\tgoto out;\n \t\telse if (!ret)\n@@ -1365,8 +1365,8 @@ static int cmd_config_actions(int argc, const char **argv, const char *prefix)\n \telse if (actions == ACTION_REMOVE_SECTION) {\n \t\tcheck_write(&location_opts.source);\n \t\tcheck_argc(argc, 1, 1);\n-\t\tret = git_config_rename_section_in_file(location_opts.source.file,\n-\t\t\t\t\t\t\targv[0], NULL);\n+\t\tret = repo_config_rename_section_in_file(the_repository, location_opts.source.file,\n+\t\t\t\t\t\t\t argv[0], NULL);\n \t\tif (ret < 0)\n \t\t\tgoto out;\n \t\telse if (!ret)\ndiff --git a/builtin/remote.c b/builtin/remote.c\nindex 08292498bd..fef3026ef4 100644\n--- a/builtin/remote.c\n+++ b/builtin/remote.c\n@@ -736,7 +736,7 @@ static int mv(int argc, const char **argv, const char *prefix)\n \n \tstrbuf_addf(&buf, \"remote.%s\", rename.old_name);\n \tstrbuf_addf(&buf2, \"remote.%s\", rename.new_name);\n-\tif (git_config_rename_section(buf.buf, buf2.buf) < 1)\n+\tif (repo_config_rename_section(the_repository, buf.buf, buf2.buf) < 1)\n \t\treturn error(_(\"Could not rename config section '%s' to '%s'\"),\n \t\t\t\tbuf.buf, buf2.buf);\n \n@@ -944,7 +944,7 @@ static int rm(int argc, const char **argv, const char *prefix)\n \n \tif (!result) {\n \t\tstrbuf_addf(&buf, \"remote.%s\", remote->name);\n-\t\tif (git_config_rename_section(buf.buf, NULL) < 1)\n+\t\tif (repo_config_rename_section(the_repository, buf.buf, NULL) < 1)\n \t\t\treturn error(_(\"Could not remove config section '%s'\"), buf.buf);\n \n \t\thandle_push_default(remote->name, NULL);\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f1218a1995..662c87c06c 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -1455,7 +1455,7 @@ static void deinit_submodule(const char *path, const char *prefix,\n \t\t * remove the whole section so we have a clean state when\n \t\t * the user later decides to init this submodule again\n \t\t */\n-\t\tgit_config_rename_section_in_file(NULL, sub_key, NULL);\n+\t\trepo_config_rename_section_in_file(the_repository, NULL, sub_key, NULL);\n \t\tif (!(flags & OPT_QUIET))\n \t\t\tprintf(_(\"Submodule '%s' (%s) unregistered for path '%s'\\n\"),\n \t\t\t\t sub->name, sub->url, displaypath);\ndiff --git a/config.c b/config.c\nindex e35fc90238..ed39922dbb 100644\n--- a/config.c\n+++ b/config.c\n@@ -3697,9 +3697,11 @@ static int section_name_is_ok(const char *name)\n #define GIT_CONFIG_MAX_LINE_LEN (512 * 1024)\n \n /* if new_name == NULL, the section is removed instead */\n-static int git_config_copy_or_rename_section_in_file(const char *config_filename,\n-\t\t\t\t      const char *old_name,\n-\t\t\t\t      const char *new_name, int copy)\n+static int repo_config_copy_or_rename_section_in_file(\n+\tstruct repository *r,\n+\tconst char *config_filename,\n+\tconst char *old_name,\n+\tconst char *new_name, int copy)\n {\n \tint ret = 0, remove = 0;\n \tchar *filename_buf = NULL;\n@@ -3720,7 +3722,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename\n \t}\n \n \tif (!config_filename)\n-\t\tconfig_filename = filename_buf = git_pathdup(\"config\");\n+\t\tconfig_filename = filename_buf = repo_git_path(r, \"config\");\n \n \tout_fd = hold_lock_file_for_update(&lock, config_filename, 0);\n \tif (out_fd < 0) {\n@@ -3863,28 +3865,28 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename\n \treturn ret;\n }\n \n-int git_config_rename_section_in_file(const char *config_filename,\n-\t\t\t\t      const char *old_name, const char *new_name)\n+int repo_config_rename_section_in_file(struct repository *r, const char *config_filename,\n+\t\t\t\t       const char *old_name, const char *new_name)\n {\n-\treturn git_config_copy_or_rename_section_in_file(config_filename,\n+\treturn repo_config_copy_or_rename_section_in_file(r, config_filename,\n \t\t\t\t\t old_name, new_name, 0);\n }\n \n-int git_config_rename_section(const char *old_name, const char *new_name)\n+int repo_config_rename_section(struct repository *r, const char *old_name, const char *new_name)\n {\n-\treturn git_config_rename_section_in_file(NULL, old_name, new_name);\n+\treturn repo_config_rename_section_in_file(r, NULL, old_name, new_name);\n }\n \n-int git_config_copy_section_in_file(const char *config_filename,\n-\t\t\t\t      const char *old_name, const char *new_name)\n+int repo_config_copy_section_in_file(struct repository *r, const char *config_filename,\n+\t\t\t\t     const char *old_name, const char *new_name)\n {\n-\treturn git_config_copy_or_rename_section_in_file(config_filename,\n+\treturn repo_config_copy_or_rename_section_in_file(r, config_filename,\n \t\t\t\t\t old_name, new_name, 1);\n }\n \n-int git_config_copy_section(const char *old_name, const char *new_name)\n+int repo_config_copy_section(struct repository *r, const char *old_name, const char *new_name)\n {\n-\treturn git_config_copy_section_in_file(NULL, old_name, new_name);\n+\treturn repo_config_copy_section_in_file(r, NULL, old_name, new_name);\n }\n \n /*\ndiff --git a/config.h b/config.h\nindex 947307c591..589d6dae26 100644\n--- a/config.h\n+++ b/config.h\n@@ -392,11 +392,11 @@ void repo_config_set_multivar_in_file(struct repository *r,\n  * If NULL is passed through `new_name` parameter,\n  * the section will be removed from the config file.\n  */\n-int git_config_rename_section(const char *, const char *);\n+int repo_config_rename_section(struct repository *, const char *, const char *);\n \n-int git_config_rename_section_in_file(const char *, const char *, const char *);\n-int git_config_copy_section(const char *, const char *);\n-int git_config_copy_section_in_file(const char *, const char *, const char *);\n+int repo_config_rename_section_in_file(struct repository *, const char *, const char *, const char *);\n+int repo_config_copy_section(struct repository *, const char *, const char *);\n+int repo_config_copy_section_in_file(struct repository *, const char *, const char *, const char *);\n int git_config_system(void);\n int config_error_nonbool(const char *);\n #if defined(__GNUC__)\ndiff --git a/submodule.c b/submodule.c\nindex ab99a30253..bc04fc8284 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -159,7 +159,7 @@ int remove_path_from_gitmodules(const char *path)\n \t}\n \tstrbuf_addstr(&sect, \"submodule.\");\n \tstrbuf_addstr(&sect, submodule->name);\n-\tif (git_config_rename_section_in_file(GITMODULES_FILE, sect.buf, NULL) < 0) {\n+\tif (repo_config_rename_section_in_file(the_repository, GITMODULES_FILE, sect.buf, NULL) < 0) {\n \t\t/* Maybe the user already did that, don't error out here */\n \t\twarning(_(\"Could not remove .gitmodules entry for %s\"), path);\n \t\tstrbuf_release(&sect);\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500722","messageId":"1e5cd92e8ed959e83182a6c422cabb68e02dbc52.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 17/20] config: don't have setters depend on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:14:15Z","receivedAt":"2024-08-13T09:14:18Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Some of the setters that accept a `struct repository` still implicitly\nrely on `the_repository` via `git_config_set_multivar_in_file()`. While\nthis function would typically use the caller-provided path, it knows to\nfall back to using the configuration path indicated by `the_repository`.\n\nAdapt those functions to instead use the caller-provided repository.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex ed39922dbb..831c9eacb0 100644\n--- a/config.c\n+++ b/config.c\n@@ -3220,8 +3220,8 @@ int repo_config_set_worktree_gently(struct repository *r,\n \t/* Only use worktree-specific config if it is already enabled. */\n \tif (r->repository_format_worktree_config) {\n \t\tchar *file = repo_git_path(r, \"config.worktree\");\n-\t\tint ret = git_config_set_multivar_in_file_gently(\n-\t\t\t\t\tfile, key, value, NULL, NULL, 0);\n+\t\tint ret = repo_config_set_multivar_in_file_gently(\n+\t\t\t\t\tr, file, key, value, NULL, NULL, 0);\n \t\tfree(file);\n \t\treturn ret;\n \t}\n@@ -3613,10 +3613,10 @@ int repo_config_set_multivar_gently(struct repository *r, const char *key,\n \t\t\t\t    const char *value_pattern, unsigned flags)\n {\n \tchar *file = repo_git_path(r, \"config\");\n-\tint res = git_config_set_multivar_in_file_gently(file,\n-\t\t\t\t\t\t\t key, value,\n-\t\t\t\t\t\t\t value_pattern,\n-\t\t\t\t\t\t\t NULL, flags);\n+\tint res = repo_config_set_multivar_in_file_gently(r, file,\n+\t\t\t\t\t\t\t  key, value,\n+\t\t\t\t\t\t\t  value_pattern,\n+\t\t\t\t\t\t\t  NULL, flags);\n \tfree(file);\n \treturn res;\n }\n@@ -3626,8 +3626,8 @@ void repo_config_set_multivar(struct repository *r,\n \t\t\t      const char *value_pattern, unsigned flags)\n {\n \tchar *file = repo_git_path(r, \"config\");\n-\tgit_config_set_multivar_in_file(file, key, value,\n-\t\t\t\t\tvalue_pattern, flags);\n+\trepo_config_set_multivar_in_file(r, file, key, value,\n+\t\t\t\t\t value_pattern, flags);\n \tfree(file);\n }\n \n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500723","messageId":"96963364e75bb7bbeff0a9be3269b372fdf9a577.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 18/20] config: don't depend on `the_repository` with branch conditions","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:14:18Z","receivedAt":"2024-08-13T09:14:21Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"When computing branch \"includeIf\" conditions we use `the_repository` to\nobtain the main ref store. We really shouldn't depend on this global\nrepository though, but should instead use the repository that is being\npassed to us via `struct config_include_data`. Otherwise, when parsing\nconfiguration of e.g. submodules, we may end up evaluating the condition\nthe via the wrong refdb.\n\nFix this.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 9 +++++----\n 1 file changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 831c9eacb0..08437f75e5 100644\n--- a/config.c\n+++ b/config.c\n@@ -300,13 +300,14 @@ static int include_by_gitdir(const struct key_value_info *kvi,\n \treturn ret;\n }\n \n-static int include_by_branch(const char *cond, size_t cond_len)\n+static int include_by_branch(struct config_include_data *data,\n+\t\t\t     const char *cond, size_t cond_len)\n {\n \tint flags;\n \tint ret;\n \tstruct strbuf pattern = STRBUF_INIT;\n-\tconst char *refname = !the_repository->gitdir ?\n-\t\tNULL : refs_resolve_ref_unsafe(get_main_ref_store(the_repository),\n+\tconst char *refname = (!data->repo || !data->repo->gitdir) ?\n+\t\tNULL : refs_resolve_ref_unsafe(get_main_ref_store(data->repo),\n \t\t\t\t\t       \"HEAD\", 0, NULL, &flags);\n \tconst char *shortname;\n \n@@ -406,7 +407,7 @@ static int include_condition_is_true(const struct key_value_info *kvi,\n \telse if (skip_prefix_mem(cond, cond_len, \"gitdir/i:\", &cond, &cond_len))\n \t\treturn include_by_gitdir(kvi, opts, cond, cond_len, 1);\n \telse if (skip_prefix_mem(cond, cond_len, \"onbranch:\", &cond, &cond_len))\n-\t\treturn include_by_branch(cond, cond_len);\n+\t\treturn include_by_branch(inc, cond, cond_len);\n \telse if (skip_prefix_mem(cond, cond_len, \"hasconfig:remote.*.url:\", &cond,\n \t\t\t\t   &cond_len))\n \t\treturn include_by_remote_url(inc, cond, cond_len);\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500724","messageId":"124f5794e6677da0ca3cac1e90c381ebb43fdca6.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 19/20] global: prepare for hiding away repo-less config functions","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:14:21Z","receivedAt":"2024-08-13T09:14:23Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to hide config functions that implicitly depend on\n`the_repository` behind the `USE_THE_REPOSITORY_VARIABLE` macro. This\nwill uncover a bunch of dependents that transitively relied on the\nglobal variable, but didn't define the macro yet.\n\nAdapt them such that we define the macro to prepare for this change.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n compat/fsmonitor/fsm-ipc-darwin.c | 2 ++\n compat/precompose_utf8.c          | 1 +\n connect.c                         | 2 ++\n credential.c                      | 2 ++\n daemon.c                          | 2 ++\n editor.c                          | 2 ++\n fsmonitor.c                       | 2 ++\n gpg-interface.c                   | 2 ++\n graph.c                           | 2 ++\n imap-send.c                       | 2 ++\n mailinfo.c                        | 2 ++\n merge-ll.c                        | 2 ++\n parallel-checkout.c               | 2 ++\n protocol.c                        | 2 ++\n refs.c                            | 2 ++\n refs/packed-backend.c             | 2 ++\n refs/reftable-backend.c           | 2 ++\n sideband.c                        | 2 ++\n t/helper/test-advise.c            | 2 ++\n t/helper/test-config.c            | 2 ++\n t/helper/test-userdiff.c          | 2 ++\n trailer.c                         | 2 ++\n versioncmp.c                      | 2 ++\n 23 files changed, 45 insertions(+)\n\ndiff --git a/compat/fsmonitor/fsm-ipc-darwin.c b/compat/fsmonitor/fsm-ipc-darwin.c\nindex 52f4f29720..fe149a1b37 100644\n--- a/compat/fsmonitor/fsm-ipc-darwin.c\n+++ b/compat/fsmonitor/fsm-ipc-darwin.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 \"gettext.h\"\ndiff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c\nindex 0bd5c24250..f7cc7b3be5 100644\n--- a/compat/precompose_utf8.c\n+++ b/compat/precompose_utf8.c\n@@ -4,6 +4,7 @@\n  */\n \n #define PRECOMPOSE_UNICODE_C\n+#define USE_THE_REPOSITORY_VARIABLE\n \n #include \"git-compat-util.h\"\n #include \"config.h\"\ndiff --git a/connect.c b/connect.c\nindex cf84e631e9..6829ab3974 100644\n--- a/connect.c\n+++ b/connect.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 \"environment.h\"\ndiff --git a/credential.c b/credential.c\nindex 4b1a2b94fe..ee46351ce0 100644\n--- a/credential.c\n+++ b/credential.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"config.h\"\ndiff --git a/daemon.c b/daemon.c\nindex 17d331b2f3..c65b068b76 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"config.h\"\ndiff --git a/editor.c b/editor.c\nindex e93b4fdb09..6b9ce81d5f 100644\n--- a/editor.c\n+++ b/editor.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"abspath.h\"\n #include \"advice.h\"\ndiff --git a/fsmonitor.c b/fsmonitor.c\nindex 2b17d60bbb..28130f748f 100644\n--- a/fsmonitor.c\n+++ b/fsmonitor.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 \"dir.h\"\ndiff --git a/gpg-interface.c b/gpg-interface.c\nindex 5c824aeb25..6587085cd1 100644\n--- a/gpg-interface.c\n+++ b/gpg-interface.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"commit.h\"\n #include \"config.h\"\ndiff --git a/graph.c b/graph.c\nindex 1ca34770ee..091c14cf4f 100644\n--- a/graph.c\n+++ b/graph.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"gettext.h\"\n #include \"config.h\"\ndiff --git a/imap-send.c b/imap-send.c\nindex 01404e5047..b2eb3d2dd0 100644\n--- a/imap-send.c\n+++ b/imap-send.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 \"config.h\"\n #include \"credential.h\"\ndiff --git a/mailinfo.c b/mailinfo.c\nindex 94b9b0abf2..95228531a6 100644\n--- a/mailinfo.c\n+++ b/mailinfo.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 \"gettext.h\"\ndiff --git a/merge-ll.c b/merge-ll.c\nindex 180c19df67..badb6dea57 100644\n--- a/merge-ll.c\n+++ b/merge-ll.c\n@@ -4,6 +4,8 @@\n  * Copyright (c) 2007 Junio C Hamano\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"config.h\"\n #include \"convert.h\"\ndiff --git a/parallel-checkout.c b/parallel-checkout.c\nindex 08b960aac8..01736f1352 100644\n--- a/parallel-checkout.c\n+++ b/parallel-checkout.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 \"entry.h\"\ndiff --git a/protocol.c b/protocol.c\nindex 079ba75acf..bae7226ff4 100644\n--- a/protocol.c\n+++ b/protocol.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 \"environment.h\"\ndiff --git a/refs.c b/refs.c\nindex 0afc70b51b..284c64dfc5 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -2,6 +2,8 @@\n  * The backend-independent part of the reference module.\n  */\n \n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"advice.h\"\n #include \"config.h\"\ndiff --git a/refs/packed-backend.c b/refs/packed-backend.c\nindex 89976aa359..ba2ad90d10 100644\n--- a/refs/packed-backend.c\n+++ b/refs/packed-backend.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 \"../dir.h\"\ndiff --git a/refs/reftable-backend.c b/refs/reftable-backend.c\nindex bf4446afd3..df67923d21 100644\n--- a/refs/reftable-backend.c\n+++ b/refs/reftable-backend.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"../git-compat-util.h\"\n #include \"../abspath.h\"\n #include \"../chdir-notify.h\"\ndiff --git a/sideband.c b/sideband.c\nindex 5d8907151f..5b6b872a1c 100644\n--- a/sideband.c\n+++ b/sideband.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"git-compat-util.h\"\n #include \"color.h\"\n #include \"config.h\"\ndiff --git a/t/helper/test-advise.c b/t/helper/test-advise.c\nindex 8a3fd0009a..6967c8e25c 100644\n--- a/t/helper/test-advise.c\n+++ b/t/helper/test-advise.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"test-tool.h\"\n #include \"advice.h\"\n #include \"config.h\"\ndiff --git a/t/helper/test-config.c b/t/helper/test-config.c\nindex ed444ca4c2..e193079ed5 100644\n--- a/t/helper/test-config.c\n+++ b/t/helper/test-config.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"test-tool.h\"\n #include \"config.h\"\n #include \"setup.h\"\ndiff --git a/t/helper/test-userdiff.c b/t/helper/test-userdiff.c\nindex 0ce31ce59f..94c48ababb 100644\n--- a/t/helper/test-userdiff.c\n+++ b/t/helper/test-userdiff.c\n@@ -1,3 +1,5 @@\n+#define USE_THE_REPOSITORY_VARIABLE\n+\n #include \"test-tool.h\"\n #include \"setup.h\"\n #include \"userdiff.h\"\ndiff --git a/trailer.c b/trailer.c\nindex 72e5136c73..682d74505b 100644\n--- a/trailer.c\n+++ b/trailer.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 \"environment.h\"\ndiff --git a/versioncmp.c b/versioncmp.c\nindex 45e676cbca..e3b2a6e330 100644\n--- a/versioncmp.c\n+++ b/versioncmp.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-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500725","messageId":"467cd481f54e6e8735a221482e435e3cd5419291.1723540226.git.ps@pks.im","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"[PATCH v2 20/20] config: hide functions using `the_repository` by default","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:14:23Z","receivedAt":"2024-08-13T09:14:27Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The config subsystem provides a bunch of legacy functions that read or\nset configuration for `the_repository`. The use of those functions is\ndiscouraged, and it is easy to miss the implicit dependency on\n`the_repository` that calls to those functions may cause.\n\nMove all config-related functions that use `the_repository` into a block\nthat gets only conditionally compiled depending on whether or not the\nmacro has been defined. This also removes all dependencies on that\nvariable in \"config.c\", allowing us to remove the definition of said\npreprocessor macro.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n config.c | 130 -----------------------------\n config.h | 249 ++++++++++++++++++++++++++++++++++++++-----------------\n 2 files changed, 171 insertions(+), 208 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 08437f75e5..c4fdbf6e1b 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@@ -2695,78 +2693,6 @@ void git_protected_config(config_fn_t fn, void *data)\n \tconfigset_iter(&protected_config, fn, data);\n }\n \n-/* Functions used historically to read configuration from 'the_repository' */\n-void git_config(config_fn_t fn, void *data)\n-{\n-\trepo_config(the_repository, fn, data);\n-}\n-\n-void git_config_clear(void)\n-{\n-\trepo_config_clear(the_repository);\n-}\n-\n-int git_config_get(const char *key)\n-{\n-\treturn repo_config_get(the_repository, key);\n-}\n-\n-int git_config_get_value(const char *key, const char **value)\n-{\n-\treturn repo_config_get_value(the_repository, key, value);\n-}\n-\n-int git_config_get_value_multi(const char *key, const struct string_list **dest)\n-{\n-\treturn repo_config_get_value_multi(the_repository, key, dest);\n-}\n-\n-int git_config_get_string_multi(const char *key,\n-\t\t\t\tconst struct string_list **dest)\n-{\n-\treturn repo_config_get_string_multi(the_repository, key, dest);\n-}\n-\n-int git_config_get_string(const char *key, char **dest)\n-{\n-\treturn repo_config_get_string(the_repository, key, dest);\n-}\n-\n-int git_config_get_string_tmp(const char *key, const char **dest)\n-{\n-\treturn repo_config_get_string_tmp(the_repository, key, dest);\n-}\n-\n-int git_config_get_int(const char *key, int *dest)\n-{\n-\treturn repo_config_get_int(the_repository, key, dest);\n-}\n-\n-int git_config_get_ulong(const char *key, unsigned long *dest)\n-{\n-\treturn repo_config_get_ulong(the_repository, key, dest);\n-}\n-\n-int git_config_get_bool(const char *key, int *dest)\n-{\n-\treturn repo_config_get_bool(the_repository, key, dest);\n-}\n-\n-int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest)\n-{\n-\treturn repo_config_get_bool_or_int(the_repository, key, is_bool, dest);\n-}\n-\n-int git_config_get_maybe_bool(const char *key, int *dest)\n-{\n-\treturn repo_config_get_maybe_bool(the_repository, key, dest);\n-}\n-\n-int git_config_get_pathname(const char *key, char **dest)\n-{\n-\treturn repo_config_get_pathname(the_repository, key, dest);\n-}\n-\n int repo_config_get_expiry(struct repository *r, const char *key, const char **output)\n {\n \tint ret = repo_config_get_string(r, key, (char **)output);\n@@ -3186,35 +3112,17 @@ int repo_config_set_in_file_gently(struct repository *r, const char *config_file\n \treturn repo_config_set_multivar_in_file_gently(r, config_filename, key, value, NULL, comment, 0);\n }\n \n-int git_config_set_in_file_gently(const char *config_filename,\n-\t\t\t\t  const char *key, const char *comment, const char *value)\n-{\n-\treturn repo_config_set_in_file_gently(the_repository, config_filename,\n-\t\t\t\t\t      key, comment, value);\n-}\n-\n void repo_config_set_in_file(struct repository *r, const char *config_filename,\n \t\t\t     const char *key, const char *value)\n {\n \trepo_config_set_multivar_in_file(r, config_filename, key, value, NULL, 0);\n }\n \n-void git_config_set_in_file(const char *config_filename,\n-\t\t\t    const char *key, const char *value)\n-{\n-\trepo_config_set_in_file(the_repository, config_filename, key, value);\n-}\n-\n int repo_config_set_gently(struct repository *r, const char *key, const char *value)\n {\n \treturn repo_config_set_multivar_gently(r, key, value, NULL, 0);\n }\n \n-int git_config_set_gently(const char *key, const char *value)\n-{\n-\treturn repo_config_set_gently(the_repository, key, value);\n-}\n-\n int repo_config_set_worktree_gently(struct repository *r,\n \t\t\t\t    const char *key, const char *value)\n {\n@@ -3236,11 +3144,6 @@ void repo_config_set(struct repository *r, const char *key, const char *value)\n \ttrace2_cmd_set_config(key, value);\n }\n \n-void git_config_set(const char *key, const char *value)\n-{\n-\trepo_config_set(the_repository, key, value);\n-}\n-\n char *git_config_prepare_comment_string(const char *comment)\n {\n \tsize_t leading_blanks;\n@@ -3569,17 +3472,6 @@ int repo_config_set_multivar_in_file_gently(struct repository *r,\n \tgoto out_free;\n }\n \n-int git_config_set_multivar_in_file_gently(const char *config_filename,\n-\t\t\t\t\t   const char *key, const char *value,\n-\t\t\t\t\t   const char *value_pattern,\n-\t\t\t\t\t   const char *comment,\n-\t\t\t\t\t   unsigned flags)\n-{\n-\treturn repo_config_set_multivar_in_file_gently(the_repository, config_filename,\n-\t\t\t\t\t\t       key, value, value_pattern,\n-\t\t\t\t\t\t       comment, flags);\n-}\n-\n void repo_config_set_multivar_in_file(struct repository *r,\n \t\t\t\t      const char *config_filename,\n \t\t\t\t      const char *key, const char *value,\n@@ -3594,21 +3486,6 @@ void repo_config_set_multivar_in_file(struct repository *r,\n \t\tdie(_(\"could not unset '%s'\"), key);\n }\n \n-void git_config_set_multivar_in_file(const char *config_filename,\n-\t\t\t\t     const char *key, const char *value,\n-\t\t\t\t     const char *value_pattern, unsigned flags)\n-{\n-\trepo_config_set_multivar_in_file(the_repository, config_filename,\n-\t\t\t\t\t key, value, value_pattern, flags);\n-}\n-\n-int git_config_set_multivar_gently(const char *key, const char *value,\n-\t\t\t\t   const char *value_pattern, unsigned flags)\n-{\n-\treturn repo_config_set_multivar_gently(the_repository, key, value,\n-\t\t\t\t\t       value_pattern, flags);\n-}\n-\n int repo_config_set_multivar_gently(struct repository *r, const char *key,\n \t\t\t\t    const char *value,\n \t\t\t\t    const char *value_pattern, unsigned flags)\n@@ -3632,13 +3509,6 @@ void repo_config_set_multivar(struct repository *r,\n \tfree(file);\n }\n \n-void git_config_set_multivar(const char *key, const char *value,\n-\t\t\t     const char *value_pattern, unsigned flags)\n-{\n-\trepo_config_set_multivar(the_repository, key, value,\n-\t\t\t\t value_pattern, flags);\n-}\n-\n static size_t section_name_match (const char *buf, const char *name)\n {\n \tsize_t i = 0, j = 0;\ndiff --git a/config.h b/config.h\nindex 589d6dae26..4d319a4193 100644\n--- a/config.h\n+++ b/config.h\n@@ -26,7 +26,7 @@ struct object_id;\n /* git_config_parse_key() returns these negated: */\n #define CONFIG_INVALID_KEY 1\n #define CONFIG_NO_SECTION_OR_NAME 2\n-/* git_config_set_gently(), git_config_set_multivar_gently() return the above or these: */\n+/* repo_config_set_gently(), repo_config_set_multivar_gently() return the above or these: */\n #define CONFIG_NO_LOCK -1\n #define CONFIG_INVALID_FILE 3\n #define CONFIG_NO_WRITE 4\n@@ -170,9 +170,9 @@ int git_default_config(const char *, const char *,\n \n /**\n  * Read a specific file in git-config format.\n- * This function takes the same callback and data parameters as `git_config`.\n+ * This function takes the same callback and data parameters as `repo_config`.\n  *\n- * Unlike git_config(), this function does not respect includes.\n+ * Unlike repo_config(), this function does not respect includes.\n  */\n int git_config_from_file(config_fn_t fn, const char *, void *);\n \n@@ -198,9 +198,9 @@ void read_very_early_config(config_fn_t cb, void *data);\n /**\n  * Most programs will simply want to look up variables in all config files\n  * that Git knows about, using the normal precedence rules. To do this,\n- * call `git_config` with a callback function and void data pointer.\n+ * call `repo_config` with a callback function and void data pointer.\n  *\n- * `git_config` will read all config sources in order of increasing\n+ * `repo_config` will read all config sources in order of increasing\n  * priority. Thus a callback should typically overwrite previously-seen\n  * entries with new ones (e.g., if both the user-wide `~/.gitconfig` and\n  * repo-specific `.git/config` contain `color.ui`, the config machinery\n@@ -210,11 +210,11 @@ void read_very_early_config(config_fn_t cb, void *data);\n  *\n  * Unlike git_config_from_file(), this function respects includes.\n  */\n-void git_config(config_fn_t fn, void *);\n+void repo_config(struct repository *r, config_fn_t fn, void *);\n \n /**\n  * Lets the caller examine config while adjusting some of the default\n- * behavior of `git_config`. It should almost never be used by \"regular\"\n+ * behavior of `repo_config`. It should almost never be used by \"regular\"\n  * Git code that is looking up configuration variables.\n  * It is intended for advanced callers like `git-config`, which are\n  * intentionally tweaking the normal config-lookup process.\n@@ -223,12 +223,12 @@ void git_config(config_fn_t fn, void *);\n  * - `config_source`\n  * If this parameter is non-NULL, it specifies the source to parse for\n  * configuration, rather than looking in the usual files. See `struct\n- * git_config_source` in `config.h` for details. Regular `git_config` defaults\n+ * git_config_source` in `config.h` for details. Regular `repo_config` defaults\n  * to `NULL`.\n  *\n  * - `opts`\n  * Specify options to adjust the behavior of parsing config files. See `struct\n- * config_options` in `config.h` for details. As an example: regular `git_config`\n+ * config_options` in `config.h` for details. As an example: regular `repo_config`\n  * sets `opts.respect_includes` to `1` by default.\n  */\n int config_with_options(config_fn_t fn, void *,\n@@ -297,7 +297,6 @@ int git_config_pathname(char **, const char *, const char *);\n \n int git_config_expiry_date(timestamp_t *, const char *, const char *);\n int git_config_color(char *, const char *, const char *);\n-int git_config_set_in_file_gently(const char *, const char *, const char *, const char *);\n int repo_config_set_in_file_gently(struct repository *r, const char *config_filename,\n \t\t\t\t   const char *key, const char *comment, const char *value);\n \n@@ -305,10 +304,8 @@ int repo_config_set_in_file_gently(struct repository *r, const char *config_file\n  * write config values to a specific config file, takes a key/value pair as\n  * parameter.\n  */\n-void git_config_set_in_file(const char *, const char *, const char *);\n void repo_config_set_in_file(struct repository *, const char *, const char *, const char *);\n \n-int git_config_set_gently(const char *, const char *);\n int repo_config_set_gently(struct repository *r, const char *, const char *);\n \n /**\n@@ -321,14 +318,13 @@ int repo_config_set_worktree_gently(struct repository *, const char *, const cha\n /**\n  * write config values to `.git/config`, takes a key/value pair as parameter.\n  */\n-void git_config_set(const char *, const char *);\n void repo_config_set(struct repository *, const char *, const char *);\n \n int git_config_parse_key(const char *, char **, size_t *);\n \n /*\n  * The following macros specify flag bits that alter the behavior\n- * of the git_config_set_multivar*() methods.\n+ * of the repo_config_set_multivar*() methods.\n  */\n \n /*\n@@ -345,11 +341,8 @@ int git_config_parse_key(const char *, char **, size_t *);\n  */\n #define CONFIG_FLAGS_FIXED_VALUE (1 << 1)\n \n-int git_config_set_multivar_gently(const char *, const char *, const char *, unsigned);\n int repo_config_set_multivar_gently(struct repository *, const char *, const char *, const char *, unsigned);\n-void git_config_set_multivar(const char *, const char *, const char *, unsigned);\n void repo_config_set_multivar(struct repository *r, const char *, const char *, const char *, unsigned);\n-int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, const char *, unsigned);\n int repo_config_set_multivar_in_file_gently(struct repository *, const char *, const char *, const char *, const char *, const char *, unsigned);\n \n char *git_config_prepare_comment_string(const char *);\n@@ -374,11 +367,6 @@ char *git_config_prepare_comment_string(const char *);\n  *\n  * It returns 0 on success.\n  */\n-void git_config_set_multivar_in_file(const char *config_filename,\n-\t\t\t\t     const char *key,\n-\t\t\t\t     const char *value,\n-\t\t\t\t     const char *value_pattern,\n-\t\t\t\t     unsigned flags);\n void repo_config_set_multivar_in_file(struct repository *r,\n \t\t\t\t      const char *config_filename,\n \t\t\t\t      const char *key,\n@@ -563,39 +551,11 @@ int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *i\n int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest);\n int git_configset_get_pathname(struct config_set *cs, const char *key, char **dest);\n \n-/* Functions for reading a repository's config */\n-struct repository;\n-void repo_config(struct repository *repo, config_fn_t fn, void *data);\n-\n /**\n  * Run only the discover part of the repo_config_get_*() functions\n  * below, in addition to 1 if not found, returns negative values on\n  * error (e.g. if the key itself is invalid).\n  */\n-RESULT_MUST_BE_USED\n-int repo_config_get(struct repository *repo, const char *key);\n-int repo_config_get_value(struct repository *repo,\n-\t\t\t  const char *key, const char **value);\n-RESULT_MUST_BE_USED\n-int repo_config_get_value_multi(struct repository *repo, const char *key,\n-\t\t\t\tconst struct string_list **dest);\n-RESULT_MUST_BE_USED\n-int repo_config_get_string_multi(struct repository *repo, const char *key,\n-\t\t\t\t const struct string_list **dest);\n-int repo_config_get_string(struct repository *repo,\n-\t\t\t   const char *key, char **dest);\n-int repo_config_get_string_tmp(struct repository *repo,\n-\t\t\t       const char *key, const char **dest);\n-int repo_config_get_int(struct repository *repo,\n-\t\t\tconst char *key, int *dest);\n-int repo_config_get_ulong(struct repository *repo,\n-\t\t\t  const char *key, unsigned long *dest);\n-int repo_config_get_bool(struct repository *repo,\n-\t\t\t const char *key, int *dest);\n-int repo_config_get_bool_or_int(struct repository *repo,\n-\t\t\t\tconst char *key, int *is_bool, int *dest);\n-int repo_config_get_maybe_bool(struct repository *repo,\n-\t\t\t       const char *key, int *dest);\n int repo_config_get_pathname(struct repository *repo,\n \t\t\t     const char *key, char **dest);\n \n@@ -611,17 +571,17 @@ void git_protected_config(config_fn_t fn, void *data);\n  * -------------------------------\n  *\n  * For programs wanting to query for specific variables in a non-callback\n- * manner, the config API provides two functions `git_config_get_value`\n- * and `git_config_get_value_multi`. They both read values from an internal\n+ * manner, the config API provides two functions `repo_config_get_value`\n+ * and `repo_config_get_value_multi`. They both read values from an internal\n  * cache generated previously from reading the config files.\n  *\n- * For those git_config_get*() functions that aren't documented,\n+ * For those repo_config_get*() functions that aren't documented,\n  * consult the corresponding repo_config_get*() function's\n  * documentation.\n  */\n \n RESULT_MUST_BE_USED\n-int git_config_get(const char *key);\n+int repo_config_get(struct repository *r, const char *key);\n \n /**\n  * Finds the highest-priority value for the configuration variable `key`,\n@@ -630,7 +590,7 @@ int git_config_get(const char *key);\n  * `value`. The caller should not free or modify `value`, as it is owned\n  * by the cache.\n  */\n-int git_config_get_value(const char *key, const char **value);\n+int repo_config_get_value(struct repository *r, const char *key, const char **value);\n \n /**\n  * Finds and returns the value list, sorted in order of increasing priority\n@@ -641,16 +601,15 @@ int git_config_get_value(const char *key, const char **value);\n  * owned by the cache.\n  */\n RESULT_MUST_BE_USED\n-int git_config_get_value_multi(const char *key,\n-\t\t\t       const struct string_list **dest);\n-RESULT_MUST_BE_USED\n-int git_config_get_string_multi(const char *key,\n+int repo_config_get_value_multi(struct repository *r, const char *key,\n \t\t\t\tconst struct string_list **dest);\n+RESULT_MUST_BE_USED\n+int repo_config_get_string_multi(struct repository *r, const char *key,\n+\t\t\t\t const struct string_list **dest);\n \n /**\n  * Resets and invalidates the config cache.\n  */\n-void git_config_clear(void);\n void repo_config_clear(struct repository *repo);\n \n /**\n@@ -659,14 +618,15 @@ void repo_config_clear(struct repository *repo);\n  * error message and returns -1. When the configuration variable `key` is\n  * not found, returns 1 without touching `dest`.\n  */\n-int git_config_get_string(const char *key, char **dest);\n+int repo_config_get_string(struct repository *r, const char *key, char **dest);\n \n /**\n- * Similar to `git_config_get_string`, but does not allocate any new\n+ * Similar to `repo_config_get_string`, but does not allocate any new\n  * memory; on success `dest` will point to memory owned by the config\n  * machinery, which could be invalidated if it is discarded and reloaded.\n  */\n-int git_config_get_string_tmp(const char *key, const char **dest);\n+int repo_config_get_string_tmp(struct repository *r,\n+\t\t\t       const char *key, const char **dest);\n \n /**\n  * Finds and parses the value to an integer for the configuration variable\n@@ -674,12 +634,13 @@ int git_config_get_string_tmp(const char *key, const char **dest);\n  * `dest` and returns 0. When the configuration variable `key` is not found,\n  * returns 1 without touching `dest`.\n  */\n-int git_config_get_int(const char *key, int *dest);\n+int repo_config_get_int(struct repository *r, const char *key, int *dest);\n \n /**\n- * Similar to `git_config_get_int` but for unsigned longs.\n+ * Similar to `repo_config_get_int` but for unsigned longs.\n  */\n-int git_config_get_ulong(const char *key, unsigned long *dest);\n+int repo_config_get_ulong(struct repository *r,\n+\t\t\t  const char *key, unsigned long *dest);\n \n /**\n  * Finds and parses the value into a boolean value, for the configuration\n@@ -690,25 +651,21 @@ int git_config_get_ulong(const char *key, unsigned long *dest);\n  * configuration variable `key` is not found, returns 1 without touching\n  * `dest`.\n  */\n-int git_config_get_bool(const char *key, int *dest);\n+int repo_config_get_bool(struct repository *r, const char *key, int *dest);\n \n /**\n- * Similar to `git_config_get_bool`, except that integers are copied as-is,\n+ * Similar to `repo_config_get_bool`, except that integers are copied as-is,\n  * and `is_bool` flag is unset.\n  */\n-int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);\n+int repo_config_get_bool_or_int(struct repository *r, const char *key,\n+\t\t\t\tint *is_bool, int *dest);\n \n /**\n- * Similar to `git_config_get_bool`, except that it returns -1 on error\n+ * Similar to `repo_config_get_bool`, except that it returns -1 on error\n  * rather than dying.\n  */\n-int git_config_get_maybe_bool(const char *key, int *dest);\n-\n-/**\n- * Similar to `git_config_get_string`, but expands `~` or `~user` into\n- * the user's home directory when found at the beginning of the path.\n- */\n-int git_config_get_pathname(const char *key, char **dest);\n+int repo_config_get_maybe_bool(struct repository *r,\n+\t\t\t      const char *key, int *dest);\n \n int repo_config_get_index_threads(struct repository *r, int *dest);\n int repo_config_get_split_index(struct repository *r);\n@@ -732,7 +689,7 @@ NORETURN void git_die_config(struct repository *r, const char *key, const char *\n /**\n  * Helper function which formats the die error message according to the\n  * parameters entered. Used by `git_die_config()`. It can be used by callers\n- * handling `git_config_get_value_multi()` to print the correct error message\n+ * handling `repo_config_get_value_multi()` to print the correct error message\n  * for the desired value.\n  */\n NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr);\n@@ -741,4 +698,140 @@ NORETURN void git_die_config_linenr(const char *key, const char *filename, int l\n \tlookup_config(mapping, ARRAY_SIZE(mapping), var)\n int lookup_config(const char **mapping, int nr_mapping, const char *var);\n \n+# ifdef USE_THE_REPOSITORY_VARIABLE\n+static inline void git_config(config_fn_t fn, void *data)\n+{\n+\trepo_config(the_repository, fn, data);\n+}\n+\n+static inline void git_config_clear(void)\n+{\n+\trepo_config_clear(the_repository);\n+}\n+\n+static inline int git_config_get(const char *key)\n+{\n+\treturn repo_config_get(the_repository, key);\n+}\n+\n+static inline int git_config_get_value(const char *key, const char **value)\n+{\n+\treturn repo_config_get_value(the_repository, key, value);\n+}\n+\n+static inline int git_config_get_value_multi(const char *key, const struct string_list **dest)\n+{\n+\treturn repo_config_get_value_multi(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_string_multi(const char *key,\n+\t\t\t\tconst struct string_list **dest)\n+{\n+\treturn repo_config_get_string_multi(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_string(const char *key, char **dest)\n+{\n+\treturn repo_config_get_string(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_string_tmp(const char *key, const char **dest)\n+{\n+\treturn repo_config_get_string_tmp(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_int(const char *key, int *dest)\n+{\n+\treturn repo_config_get_int(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_ulong(const char *key, unsigned long *dest)\n+{\n+\treturn repo_config_get_ulong(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_bool(const char *key, int *dest)\n+{\n+\treturn repo_config_get_bool(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest)\n+{\n+\treturn repo_config_get_bool_or_int(the_repository, key, is_bool, dest);\n+}\n+\n+static inline int git_config_get_maybe_bool(const char *key, int *dest)\n+{\n+\treturn repo_config_get_maybe_bool(the_repository, key, dest);\n+}\n+\n+static inline int git_config_get_pathname(const char *key, char **dest)\n+{\n+\treturn repo_config_get_pathname(the_repository, key, dest);\n+}\n+\n+static inline void git_config_set_in_file(const char *config_filename,\n+\t\t\t\t\t  const char *key, const char *value)\n+{\n+\trepo_config_set_in_file(the_repository, config_filename, key, value);\n+}\n+\n+static inline int git_config_set_gently(const char *key, const char *value)\n+{\n+\treturn repo_config_set_gently(the_repository, key, value);\n+}\n+\n+static inline void git_config_set(const char *key, const char *value)\n+{\n+\trepo_config_set(the_repository, key, value);\n+}\n+\n+static inline int git_config_set_in_file_gently(\n+\tconst char *config_filename,\n+\tconst char *key,\n+\tconst char *comment,\n+\tconst char *value)\n+{\n+\treturn repo_config_set_in_file_gently(the_repository, config_filename,\n+\t\t\t\t\t      key, comment, value);\n+}\n+\n+static inline int git_config_set_multivar_in_file_gently(\n+\tconst char *config_filename,\n+\tconst char *key, const char *value,\n+\tconst char *value_pattern,\n+\tconst char *comment,\n+\tunsigned flags)\n+{\n+\treturn repo_config_set_multivar_in_file_gently(the_repository, config_filename,\n+\t\t\t\t\t\t       key, value, value_pattern,\n+\t\t\t\t\t\t       comment, flags);\n+}\n+\n+static inline void git_config_set_multivar_in_file(\n+\tconst char *config_filename,\n+\tconst char *key,\n+\tconst char *value,\n+\tconst char *value_pattern,\n+\tunsigned flags)\n+{\n+\trepo_config_set_multivar_in_file(the_repository, config_filename,\n+\t\t\t\t\t key, value, value_pattern, flags);\n+}\n+\n+static inline int git_config_set_multivar_gently(const char *key, const char *value,\n+\t\t\t\t   const char *value_pattern, unsigned flags)\n+{\n+\treturn repo_config_set_multivar_gently(the_repository, key, value,\n+\t\t\t\t\t       value_pattern, flags);\n+}\n+\n+static inline void git_config_set_multivar(const char *key, const char *value,\n+\t\t\t     const char *value_pattern, unsigned flags)\n+{\n+\trepo_config_set_multivar(the_repository, key, value,\n+\t\t\t\t value_pattern, flags);\n+}\n+# endif /* USE_THE_REPOSITORY_VARIABLE */\n+\n #endif /* CONFIG_H */\n-- \n2.46.0.46.g406f326d27.dirty\n\n"},{"id":"500730","messageId":"ZrsmiWeu8JsX54nU@tanuki","threadId":"61914","inReplyTo":"xmqq5xs9eh4p.fsf@gitster.g","subject":"Re: [PATCH 02/20] path: expose `do_git_common_path()` as `strbuf_git_common_pathv()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:25:29Z","receivedAt":"2024-08-13T09:25:34Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Aug 09, 2024 at 10:32:54AM -0700, Junio C Hamano wrote:\n> Justin Tobler <jltobler@gmail.com> writes:\n> \n> >> -static void do_git_common_path(const struct repository *repo,\n> >> -\t\t\t       struct strbuf *buf,\n> >> -\t\t\t       const char *fmt,\n> >> -\t\t\t       va_list args)\n> >> +void strbuf_git_common_pathv(struct strbuf *sb,\n> >> +\t\t\t     const struct repository *repo,\n> >> +\t\t\t     const char *fmt,\n> >> +\t\t\t     va_list args)\n> >\n> > Here we reorder the arguments to make `strbuf` first. I assume we are do\n> > this to align with the preexisting `strbuf_git_common_path()` and use\n> > the \"strbuf_\" prefix in the function name.\n> \n> I thought that we already established as a general guideline that\n> \"strbuf_\" should be cleaned up so that functions that happen to use\n> strbuf merely as a way to carry parameters into or results out of\n> them but are not primarily about string manipulation are renamed out\n> of the \"strbuf_\" namespace.\n> \n>   https://lore.kernel.org/git/ZqiLA0bGYZfH1OWD@tanuki/\n> \n> And this is about getting a path, which is communicated via a\n> \"struct strbuf\", and not the standard \"char *\".  That is a prime\n> example of a function that we do *not* want to stress strbuf-ness\n> of the function.\n> \n> > In the previous commit we used the \"repo_\" prefix for\n> > `repo_git_pathv()`. Would it make sense to be consistent here? All these\n> > functions are operating on the provided buffer, but for a given\n> > repository. Not sure what would be most appropriate here.\n> \n> Yes, if the function is about obtaining the path for a file in a\n> given repository's metadata directory, and its association with\n> \"strbuf\" is that it merely happens to use it instead of \"char *\",\n> it should not be named as if \"strbuf_\" ness is the primary\n> characteristics of the function.\n> \n> strbuf_cleanup_path() should also be renamed for the same reason.\n\nAgreed. I was doing it for consistency's sake in this case, but let's\nrather not make the overall interface any weirder than it already is.\n\nPatrick\n"},{"id":"500731","messageId":"Zrsmjl7BVWhxuolz@tanuki","threadId":"61914","inReplyTo":"cqc4xlbrusu5edfsh2snvekkd2qfwjxu3x33pzizp22rsuidbw@pz4e3fsqfhgv","subject":"Re: [PATCH 06/20] path: stop relying on `the_repository` in `worktree_git_path()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:25:34Z","receivedAt":"2024-08-13T09:25:37Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Aug 09, 2024 at 02:02:21PM -0500, Justin Tobler wrote:\n> On 24/08/07 08:57AM, Patrick Steinhardt wrote:\n> > When not provided a worktree, then `worktree_git_path()` will fall back\n> > to returning a path relative to the main repository. In this case, we\n> > implicitly rely on `the_repository` to derive the path. Remove this\n> > dependency by passing a `struct repository` as parameter.\n> \n> Are there many situations where `worktree_git_path()` would expect to\n> not be provided a worktree? I wonder whether this implicit behavior is\n> really necessary to begin with.\n\nYeah, there are cases. I found that to be somewhat weird at first, but I\ndoes make the logic easier to handle because you don't need to special\ncase whether you do or don't have a worktree.\n\n> > diff --git a/path.h b/path.h\n> > index 3d21b9cd16..6228ca03d7 100644\n> > --- a/path.h\n> > +++ b/path.h\n> > @@ -97,9 +97,10 @@ const char *git_path(const char *fmt, ...)\n> >   * Similar to git_path() but can produce paths for a specified\n> >   * worktree instead of current one\n> >   */\n> \n> Now that the previously implicit behavior is more explicit, it might be\n> update the comment to explain that the provided repository is used as a\n> fallback.\n\nGood idea.\n\nPatrick\n"},{"id":"500732","messageId":"ZrsmkrbGYtfl2Mnc@tanuki","threadId":"61914","inReplyTo":"mc4omj4mi23fhmqp4xeafcluzf2iidp4uaf3h3gaxcalm3igvk@a7abzjynshfw","subject":"Re: [PATCH 07/20] path: hide functions using `the_repository` by default","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:25:38Z","receivedAt":"2024-08-13T09:25:41Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Aug 09, 2024 at 02:43:59PM -0500, Justin Tobler wrote:\n> On 24/08/07 08:57AM, Patrick Steinhardt wrote:\n> > +# ifdef USE_THE_REPOSITORY_VARIABLE\n> > +#  include \"strbuf.h\"\n> > +#  include \"repository.h\"\n> \n> Naive question, what is the purpose of providing the include statements\n> here? Wouldn't they always already be included?\n\nNot necessarily, no. Most headers only have a forward declaration of\n`struct strbuf` and `struct repository`. For one this means that we\ncannot access the strbuf contents like we do in the function definitions\nin this header now. Second, it means that we cannot access `the_repository`.\n\nPatrick\n"},{"id":"500733","messageId":"ZrsmlVfjIoFw3gur@tanuki","threadId":"61914","inReplyTo":"rg5j5ehur5a2qvpt65ezfub5dmmqrbn7if5f2r7ibweuupsnm2@qeciml3qvdvy","subject":"Re: [PATCH 08/20] config: introduce missing setters that take repo as parameter","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:25:41Z","receivedAt":"2024-08-13T09:25:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Aug 09, 2024 at 03:07:37PM -0500, Justin Tobler wrote:\n> On 24/08/07 08:57AM, Patrick Steinhardt wrote:\n> > diff --git a/config.c b/config.c\n> > index 6421894614..ac89b708e7 100644\n> > --- a/config.c\n> > +++ b/config.c\n> > @@ -3178,21 +3178,39 @@ static void maybe_remove_section(struct config_store_data *store,\n> >  \t\t*end_offset = store->parsed[store->parsed_nr - 1].end;\n> >  }\n> >  \n> > +int repo_config_set_in_file_gently(struct repository *r, const char *config_filename,\n> > +\t\t\t\t   const char *key, const char *comment, const char *value)\n> \n> Instead of prefixing with `repo_`, should we instead use the `config_`\n> prefix? Maybe `config_repo_`? It might be nice for names to align with\n> the config subsystem here.\n\nI think I agree, but we extensively use the `repo_config_` prefix for\nall functions that take a repository as input in this subsystem. So in\nthis case I think we should stick with that, but we may eventually want\nto revisit this.\n\nPatrick\n"},{"id":"500734","messageId":"ZrsmmYWtJuJWGMW0@tanuki","threadId":"61914","inReplyTo":"unahz22fciepxsgt74jdk63i3yminzjwsdqee3ti5mrii2cz3s@jf6ussbyx637","subject":"Re: [PATCH 18/20] config: don't depend on `the_repository` with branch conditions","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:25:45Z","receivedAt":"2024-08-13T09:25:51Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Aug 09, 2024 at 03:47:50PM -0500, Justin Tobler wrote:\n> On 24/08/07 08:58AM, Patrick Steinhardt wrote:\n> > When computing branch \"includeIf\" conditions we use `the_repository` to\n> > obtain the main ref store. We really shouldn't depend on this global\n> > repository though, but should instead use the repository that is being\n> > passed to us via `struct config_include_data`. Otherwise, when parsing\n> > configuration of e.g. submodules, we may end up evaluating the condition\n> > the via the wrong refdb.\n> > \n> > Fix this.\n> > \n> > Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> > ---\n> >  config.c | 9 +++++----\n> >  1 file changed, 5 insertions(+), 4 deletions(-)\n> > \n> > diff --git a/config.c b/config.c\n> > index 831c9eacb0..08437f75e5 100644\n> > --- a/config.c\n> > +++ b/config.c\n> > @@ -300,13 +300,14 @@ static int include_by_gitdir(const struct key_value_info *kvi,\n> >  \treturn ret;\n> >  }\n> >  \n> > -static int include_by_branch(const char *cond, size_t cond_len)\n> > +static int include_by_branch(struct config_include_data *data,\n> > +\t\t\t     const char *cond, size_t cond_len)\n> >  {\n> >  \tint flags;\n> >  \tint ret;\n> >  \tstruct strbuf pattern = STRBUF_INIT;\n> > -\tconst char *refname = !the_repository->gitdir ?\n> > -\t\tNULL : refs_resolve_ref_unsafe(get_main_ref_store(the_repository),\n> > +\tconst char *refname = (!data->repo || !data->repo->gitdir) ?\n> > +\t\tNULL : refs_resolve_ref_unsafe(get_main_ref_store(data->repo),\n> >  \t\t\t\t\t       \"HEAD\", 0, NULL, &flags);\n> >  \tconst char *shortname;\n> \n> This works the same so long as `config_include_data` always has its\n> repository set. I wonder if for `!data->repo` we should instead signal a\n> BUG? Otherwise we would silently return NULL in such cases. Maybe that\n> would be the desired behavior though?\n\nIt is expected that the repository may not be set, namely when reading\nconfiguration via `read_early_config()` and `read_very_early_config()`.\nWe wouldn't want to hit the refdb there, so that is fine.\n\nWe also have `read_protected_config()`, which requires a bit more\nthought. It does respect includes, so you may think we want to read the\nrefdb there. But protected config is defined as having system, global or\ncommand scope, which to me means that we shouldn't end up reading config\ndata from the current repository. So not hitting the refdb there also\nseems like the right thing to do.\n\nPatrick\n"},{"id":"500735","messageId":"ZrsmoFK1nKzwSN2d@tanuki","threadId":"61914","inReplyTo":"xl37sjpibmamkxdmpvfy44sijseuk5doizdlbnuodnbd6pdhxj@dws5e4wdu5lg","subject":"Re: [PATCH 01/20] path: expose `do_git_path()` as `repo_git_pathv()`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-13T09:25:52Z","receivedAt":"2024-08-13T09:25:56Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Aug 09, 2024 at 11:58:31AM -0500, Justin Tobler wrote:\n> On 24/08/07 08:56AM, Patrick Steinhardt wrote:\n> > We're about to move functions of the \"path\" subsytem that do not use a\n> \n> s/subsytem/subsystem/\n> \n> > `struct repository` into \"path.h\" as static inlined functions. This will\n> > require us to call `do_git_path()`, which is internal to \"path.c\".\n> \n> So in other words, functions leveraging `the_repository` in \"path.c\" are\n> going to be moved to \"path.h\". Since these functions depend on\n> `do_git_path()`, we need to expose it. Makes sense so far.\n\nYup.\n\n> > Expose the function as `repo_git_pathv()` to prepare for the change.\n> > \n> > Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> [snip]\n> > +/*\n> > + * Print a path into the git directory of repository `repo` into the provided\n> > + * buffer.\n> > + */\n> > +void repo_git_pathv(const struct repository *repo,\n> > +\t\t    const struct worktree *wt, struct strbuf *buf,\n> > +\t\t    const char *fmt, va_list args);\n> > +\n> \n> Out of curiousity, do we have a preferred convention for how functions\n> accepting `va_list` are named? Searching through the codebase, I don't\n> see a ton of consistency, but I have noticed examples prefixed with \"v\".\n\nWe of course have `strbuf_vaddf()` and the likes of `vsnprintf()` and\n`xstrvmt()`, which indeed have the \"v\" as a prefix. But is\n`repo_git_vpath()` better than `repo_git_pathv()` in this case here? I\ndunno.\n\nIn any case, we already have `strbuf_git_common_pathv()`. So I'm leaning\nmore towards local consistency as opposed to global consistency. Even if\nnaming in our config interface feels like the wild west anyway.\n\nPatrick\n"},{"id":"500793","messageId":"xmqq4j7oa23i.fsf@gitster.g","threadId":"61914","inReplyTo":"ZrsmiWeu8JsX54nU@tanuki","subject":"Re: [PATCH 02/20] path: expose `do_git_common_path()` as `strbuf_git_common_pathv()`","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-13T15:12:33Z","receivedAt":"2024-08-13T15:12:35Z","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>> Yes, if the function is about obtaining the path for a file in a\n>> given repository's metadata directory, and its association with\n>> \"strbuf\" is that it merely happens to use it instead of \"char *\",\n>> it should not be named as if \"strbuf_\" ness is the primary\n>> characteristics of the function.\n>> \n>> strbuf_cleanup_path() should also be renamed for the same reason.\n>\n> Agreed. I was doing it for consistency's sake in this case, but let's\n> rather not make the overall interface any weirder than it already is.\n\nThanks, then we are in agreement.\n\n"},{"id":"500805","messageId":"xmqqwmkk5p2p.fsf@gitster.g","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"Re: [PATCH v2 00/20] Stop using `the_repository` in \"config.c\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-13T17:07:26Z","receivedAt":"2024-08-13T17:07:29Z","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 second version of my patch series that drops the dependency\n> on `the_repository` in both \"path.c\" and \"config.c\".\n>\n> Changes compared to v1:\n>\n>   - Various typo fixes in commit messages.\n>\n>   - Rename `strbuf_git_common_pathv()` to `repo_common_pathv()`.\n>\n>   - Reorder arguments of `strbuf_edit_interactively()` such that the\n>     `struct repository` gets passed as first argument.\n>\n>   - Document behaviour of `worktree_git_path()` when no worktree is\n>     given.\n>\n>   - Wrap some overly long lines.\n>\n> Thanks!\n\nNicely done.  I found that both of the two larger changes relative\nto the previous iteration are sensible.\n\n"},{"id":"500929","messageId":"20240814182850.1273188-1-calvinwan@google.com","threadId":"61914","inReplyTo":"bbaa85ebad458c60c59784b690be8be2ddbe76fc.1723540226.git.ps@pks.im","subject":"Re: [PATCH v2 05/20] path: stop relying on `the_repository` when reporting garbage","fromName":"Calvin Wan","fromEmail":"calvinwan@google.com","sentAt":"2024-08-14T18:28:50Z","receivedAt":"2024-08-14T18:28:54Z","isPatch":true,"sender":{"key":"calvinwan@google.com","avatar":"https://avatars.githubusercontent.com/u/92547554?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n> We access `the_repository` in `report_linked_checkout_garbage()` both\n> directly and indirectly via `get_git_dir()`. Remove this dependency by\n> instead passing a `struct repository` as parameter.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  builtin/count-objects.c | 2 +-\n>  path.c                  | 6 +++---\n>  path.h                  | 2 +-\n>  3 files changed, 5 insertions(+), 5 deletions(-)\n> \n> diff --git a/path.c b/path.c\n> index 069db6ff8f..97a07fafc7 100644\n> --- a/path.c\n> +++ b/path.c\n> @@ -365,15 +365,15 @@ static void update_common_dir(struct strbuf *buf, int git_dir_len,\n>  \t\tstrbuf_addstr(buf, LOCK_SUFFIX);\n>  }\n>  \n> -void report_linked_checkout_garbage(void)\n> +void report_linked_checkout_garbage(struct repository *r)\n>  {\n>  \tstruct strbuf sb = STRBUF_INIT;\n>  \tconst struct common_dir *p;\n>  \tint len;\n>  \n> -\tif (!the_repository->different_commondir)\n> +\tif (!r->different_commondir)\n>  \t\treturn;\n> -\tstrbuf_addf(&sb, \"%s/\", get_git_dir());\n> +\tstrbuf_addf(&sb, \"%s/\", r->gitdir);\n>  \tlen = sb.len;\n>  \tfor (p = common_list; p->path; p++) {\n>  \t\tconst char *path = p->path;\n\nCallers have two options here for accessing the gitdir: one is including\nenvironment.h and calling get_git_dir(). The other is passing in `struct\nrepository *r` and accessing r->gitdir. It's not entirely clear which\nshould be used in what scenario. Sure with the second option the user\nhas the option of passing something in that isn't `the_repository` but\npractically speaking that's not happening here and also in the large\nmajority of other scenarios.\n\nI'm OK with this patch for the purposes of the series, but do you think\nin the future we should introduce get_git_dir(struct repository *r) and\nchange get_git_dir() into get_env_git_dir() that simply calls\nget_git_dir(the_repository)?\n"},{"id":"500934","messageId":"20240814192957.1518560-1-calvinwan@google.com","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"Re: [PATCH v2 00/20] Stop using `the_repository` in \"config.c\"","fromName":"Calvin Wan","fromEmail":"calvinwan@google.com","sentAt":"2024-08-14T19:29:57Z","receivedAt":"2024-08-14T19:30:01Z","isPatch":true,"sender":{"key":"calvinwan@google.com","avatar":"https://avatars.githubusercontent.com/u/92547554?v=4"},"body":"Hi Patrick,\n\nGlad to see us slowly getting rid of the global, `the_repository`! I had\nmissed your original series[1] introducing the\nUSE_THE_REPOSITORY_AVAILABLE macro, but going thru it provided all the\ncontext necessary for this series.\n\nI see there have been a few cleanups since the first version, and I\ndidn't spot any typos on my end. Overall, this is a good step towards\nreducing our dependency on `the_repository` by removing it from the\nconfig subsystem. Additionally, this makes libifying that subsystem much\neasier since removing globals usage is a prerequisite for libification.\nI only left a non-blocking comment on one of the patches, but besides\nthat this series LGTM. Feel free to cc me on any related series in the\nfuture!\n\n[1] https://lore.kernel.org/git/cover.1718106284.git.ps@pks.im/\n\nReviewed-by: Calvin Wan <calvinwan@google.com>\n"},{"id":"500945","messageId":"doivvzjzsrxngrafcywfxbs355epthuxdu5x3kxe2mvwnzgpf5@pgotr3bbyb4u","threadId":"61914","inReplyTo":"cover.1723540226.git.ps@pks.im","subject":"Re: [PATCH v2 00/20] Stop using `the_repository` in \"config.c\"","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2024-08-15T00:58:56Z","receivedAt":"2024-08-15T00:59:45Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 24/08/13 11:13AM, Patrick Steinhardt wrote:\n> Hi,\n> \n> this is the second version of my patch series that drops the dependency\n> on `the_repository` in both \"path.c\" and \"config.c\".\n> \n> Changes compared to v1:\n> \n>   - Various typo fixes in commit messages.\n> \n>   - Rename `strbuf_git_common_pathv()` to `repo_common_pathv()`.\n> \n>   - Reorder arguments of `strbuf_edit_interactively()` such that the\n>     `struct repository` gets passed as first argument.\n> \n>   - Document behaviour of `worktree_git_path()` when no worktree is\n>     given.\n> \n>   - Wrap some overly long lines.\n> \n> Thanks!\n\nAfter reviewing the changes in this version, the series looks good to\nme! Thanks :)\n\n-Justin\n"},{"id":"500948","messageId":"Zr2OXEwmySOc9gpL@tanuki","threadId":"61914","inReplyTo":"20240814192957.1518560-1-calvinwan@google.com","subject":"Re: [PATCH v2 00/20] Stop using `the_repository` in \"config.c\"","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-15T05:13:07Z","receivedAt":"2024-08-15T05:13:13Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Aug 14, 2024 at 07:29:57PM +0000, Calvin Wan wrote:\n> Hi Patrick,\n> \n> Glad to see us slowly getting rid of the global, `the_repository`! I had\n> missed your original series[1] introducing the\n> USE_THE_REPOSITORY_AVAILABLE macro, but going thru it provided all the\n> context necessary for this series.\n> \n> I see there have been a few cleanups since the first version, and I\n> didn't spot any typos on my end. Overall, this is a good step towards\n> reducing our dependency on `the_repository` by removing it from the\n> config subsystem. Additionally, this makes libifying that subsystem much\n> easier since removing globals usage is a prerequisite for libification.\n> I only left a non-blocking comment on one of the patches, but besides\n> that this series LGTM. Feel free to cc me on any related series in the\n> future!\n> \n> [1] https://lore.kernel.org/git/cover.1718106284.git.ps@pks.im/\n\nThanks, will do!\n\nPatrick\n"},{"id":"500951","messageId":"Zr2RaQCbi3Tpstz7@tanuki","threadId":"61914","inReplyTo":"20240814182850.1273188-1-calvinwan@google.com","subject":"Re: [PATCH v2 05/20] path: stop relying on `the_repository` when reporting garbage","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-15T05:26:01Z","receivedAt":"2024-08-15T05:26:07Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Aug 14, 2024 at 06:28:50PM +0000, Calvin Wan wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> > We access `the_repository` in `report_linked_checkout_garbage()` both\n> > directly and indirectly via `get_git_dir()`. Remove this dependency by\n> > instead passing a `struct repository` as parameter.\n> > \n> > Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> > ---\n> >  builtin/count-objects.c | 2 +-\n> >  path.c                  | 6 +++---\n> >  path.h                  | 2 +-\n> >  3 files changed, 5 insertions(+), 5 deletions(-)\n> > \n> > diff --git a/path.c b/path.c\n> > index 069db6ff8f..97a07fafc7 100644\n> > --- a/path.c\n> > +++ b/path.c\n> > @@ -365,15 +365,15 @@ static void update_common_dir(struct strbuf *buf, int git_dir_len,\n> >  \t\tstrbuf_addstr(buf, LOCK_SUFFIX);\n> >  }\n> >  \n> > -void report_linked_checkout_garbage(void)\n> > +void report_linked_checkout_garbage(struct repository *r)\n> >  {\n> >  \tstruct strbuf sb = STRBUF_INIT;\n> >  \tconst struct common_dir *p;\n> >  \tint len;\n> >  \n> > -\tif (!the_repository->different_commondir)\n> > +\tif (!r->different_commondir)\n> >  \t\treturn;\n> > -\tstrbuf_addf(&sb, \"%s/\", get_git_dir());\n> > +\tstrbuf_addf(&sb, \"%s/\", r->gitdir);\n> >  \tlen = sb.len;\n> >  \tfor (p = common_list; p->path; p++) {\n> >  \t\tconst char *path = p->path;\n> \n> Callers have two options here for accessing the gitdir: one is including\n> environment.h and calling get_git_dir(). The other is passing in `struct\n> repository *r` and accessing r->gitdir. It's not entirely clear which\n> should be used in what scenario. Sure with the second option the user\n> has the option of passing something in that isn't `the_repository` but\n> practically speaking that's not happening here and also in the large\n> majority of other scenarios.\n> \n> I'm OK with this patch for the purposes of the series, but do you think\n> in the future we should introduce get_git_dir(struct repository *r) and\n> change get_git_dir() into get_env_git_dir() that simply calls\n> get_git_dir(the_repository)?\n\nGood question. `get_git_dir()` is implemented like this:\n\n        const char *get_git_dir(void)\n        {\n            if (!the_repository->gitdir)\n                BUG(\"git environment hasn't been setup\");\n            return the_repository->gitdir;\n        }\n\nWe could of course introduce something like `repo_get_git_dir()` that\ntakes an arbitrary repository as input, like this:\n\n        const char *repo_get_git_dir(struct repository *r)\n        {\n            if (!r->gitdir)\n                BUG(\"git environment hasn't been setup\");\n            return r->gitdir;\n        }\n\nThe only benefit that this has is that we double check whether\n`r->gitdir` has actually been set in the first place. I don't really\nthink that check is all that useful though, because I expect that the\ncaller either has a repository, and given that a repository always has a\n`gitdir` I'd always expect it to be populated. Or they don't have a\ngitdir, but in that case they cannot call `repo_get_git_dir()` in the\nfirst place because we'd already segfault before hitting the BUG when\ntrying to dereference a NULL pointer.\n\nSo I'm not entirely sure of the benefit of such a function over just\naccessing `r->gitdir` directly.\n\nPatrick\n"}]}