{"thread":{"id":"65095","subject":"[PATCH v1] environment: migrate encoding settings to repo-settings","startedAt":"2026-02-28T04:07:41Z","lastAt":"2026-03-02T08:58:31Z","messageCount":13,"participants":["Tian Yuchen"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"537373","messageId":"20260228040727.2057192-1-a3205153416@gmail.com","threadId":"65095","inReplyTo":null,"subject":"[PATCH v1] environment: migrate encoding settings to repo-settings","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-02-28T04:07:27Z","receivedAt":"2026-02-28T04:07:41Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"Global variables 'git_commit_encoding' and 'git_log_output_encoding'\nhinder the ongoing libification effort by binding functions to a\nsingle global state.\n\nMove both variables into 'struct repo_settings' to enable lazy loading.\nThey are migrated together in this patch because the log encoding\ndirectly falls back to the commit encoding.\n\nUpdate callers to use the new 'repo_get_commit_output_encoding()' and\n'repo_get_log_output_encoding()' apis. Functions now accept 'struct\nrepository' to bubble up dependency where possible. For callers in the\n'builtin/' directory, and for core library functions that do not yet\nreceive a repository context, 'the_repository' is used as a fallback.\n\nAdditionally, in 'revision.c', ensure 'prepare_repo_settings()' is\ntriggered before CLI overrides, for example, '--encoding', to prevent\nlazy-loading from mistakenly overwriting command-line choice later.\n\nAll tests passed, no memory leak.\n\nSigned-off-by: Tian Yuchen <a3205153416@gmail.com>\n---\nThis patch serves as a proof of concept for migration workflow preposed\nin my GSoC 2026 proposal, regarding global state libification.\n\nThe patch has been verified against the full test suite and compiled with \n'SANITIZE=address,undefined' to ensure clean memory ownership.\n\nAny thought on whether this patch meets the project's standards would be\ndeeply appreciated.\n\nRegards, Yuchen\n\n builtin/am.c       |  4 ++--\n builtin/blame.c    |  2 +-\n builtin/commit.c   |  6 +++---\n builtin/log.c      |  2 +-\n builtin/mailinfo.c |  2 +-\n builtin/rev-list.c |  2 +-\n builtin/shortlog.c |  2 +-\n bundle.c           |  2 +-\n commit.c           |  6 +++---\n environment.c      | 37 +++++++++++--------------------------\n environment.h      |  7 ++-----\n log-tree.c         |  4 ++--\n pretty.c           |  2 +-\n remote-curl.c      |  3 ++-\n replay.c           |  2 +-\n repo-settings.c    |  7 +++++++\n repo-settings.h    |  3 +++\n revision.c         | 11 ++++++-----\n sequencer.c        | 16 ++++++++--------\n submodule.c        |  2 +-\n 20 files changed, 58 insertions(+), 64 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex e0c767e223..96b8c00007 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1216,7 +1216,7 @@ static int parse_mail(struct am_state *state, const char *mail)\n \tsetup_mailinfo(the_repository, &mi);\n \n \tif (state->utf8)\n-\t\tmi.metainfo_charset = get_commit_output_encoding();\n+\t\tmi.metainfo_charset = repo_get_commit_output_encoding(the_repository);\n \telse\n \t\tmi.metainfo_charset = NULL;\n \n@@ -1355,7 +1355,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit)\n \tstruct ident_split id;\n \n \tbuffer = repo_logmsg_reencode(the_repository, commit, NULL,\n-\t\t\t\t      get_commit_output_encoding());\n+\t\t\t\t      repo_get_commit_output_encoding(the_repository));\n \n \tident_line = find_commit_header(buffer, \"author\", &ident_len);\n \tif (!ident_line)\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex eac2fe7320..cc82182c51 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -202,7 +202,7 @@ static void get_commit_info(struct commit *commit, struct commit_info *ret)\n \tconst char *subject, *encoding;\n \tconst char *message;\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = repo_get_log_output_encoding(the_repository);\n \tmessage = repo_logmsg_reencode(the_repository, commit, NULL, encoding);\n \tget_ac_line(message, \"\\nauthor \",\n \t\t    &ret->author, &ret->author_mail,\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 9e3a09d532..2bbdd4c4c3 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -794,7 +794,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\t\tc = lookup_commit_reference_by_name(squash_message);\n \t\t\tif (!c)\n \t\t\t\tdie(_(\"could not lookup commit '%s'\"), squash_message);\n-\t\t\tctx.output_encoding = get_commit_output_encoding();\n+\t\t\tctx.output_encoding = repo_get_commit_output_encoding(the_repository);\n \t\t\trepo_format_commit_message(the_repository, c,\n \t\t\t\t\t\t   \"squash! %s\\n\\n\", &sb,\n \t\t\t\t\t\t   &ctx);\n@@ -829,7 +829,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\tcommit = lookup_commit_reference_by_name(fixup_commit);\n \t\tif (!commit)\n \t\t\tdie(_(\"could not lookup commit '%s'\"), fixup_commit);\n-\t\tctx.output_encoding = get_commit_output_encoding();\n+\t\tctx.output_encoding = repo_get_commit_output_encoding(the_repository);\n \t\tfmt = xstrfmt(\"%s! %%s\\n\\n\", fixup_prefix);\n \t\trepo_format_commit_message(the_repository, commit, fmt, &sb,\n \t\t\t\t\t   &ctx);\n@@ -1235,7 +1235,7 @@ static const char *read_commit_message(const char *name)\n \tcommit = lookup_commit_reference_by_name(name);\n \tif (!commit)\n \t\tdie(_(\"could not lookup commit '%s'\"), name);\n-\tout_enc = get_commit_output_encoding();\n+\tout_enc = repo_get_commit_output_encoding(the_repository);\n \treturn repo_logmsg_reencode(the_repository, commit, NULL, out_enc);\n }\n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 8ab6d3a943..1c9ec09098 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -568,7 +568,7 @@ static void show_tagger(const char *buf, struct rev_info *rev)\n \n \tpp.fmt = rev->commit_format;\n \tpp.date_mode = rev->date_mode;\n-\tpp_user_info(&pp, \"Tagger\", &out, buf, get_log_output_encoding());\n+\tpp_user_info(&pp, \"Tagger\", &out, buf, repo_get_log_output_encoding(the_repository));\n \tfprintf(rev->diffopt.file, \"%s\", out.buf);\n \tstrbuf_release(&out);\n }\ndiff --git a/builtin/mailinfo.c b/builtin/mailinfo.c\nindex 8de7ba7de1..eab4e05850 100644\n--- a/builtin/mailinfo.c\n+++ b/builtin/mailinfo.c\n@@ -93,7 +93,7 @@ int cmd_mailinfo(int argc,\n \n \tswitch (meta_charset.policy) {\n \tcase CHARSET_DEFAULT:\n-\t\tmi.metainfo_charset = get_commit_output_encoding();\n+\t\tmi.metainfo_charset = repo_get_commit_output_encoding(the_repository);\n \t\tbreak;\n \tcase CHARSET_NO_REENCODE:\n \t\tmi.metainfo_charset = NULL;\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex ddea8aa251..3c6a2914d8 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -304,7 +304,7 @@ static void show_commit(struct commit *commit, void *data)\n \t\tctx.date_mode = revs->date_mode;\n \t\tctx.date_mode_explicit = revs->date_mode_explicit;\n \t\tctx.fmt = revs->commit_format;\n-\t\tctx.output_encoding = get_log_output_encoding();\n+\t\tctx.output_encoding = repo_get_log_output_encoding(the_repository);\n \t\tctx.color = revs->diffopt.use_color;\n \t\tctx.rev = revs;\n \t\tpretty_print_commit(&ctx, commit, &buf);\ndiff --git a/builtin/shortlog.c b/builtin/shortlog.c\nindex d80bf1a7d0..ce9f20de2f 100644\n--- a/builtin/shortlog.c\n+++ b/builtin/shortlog.c\n@@ -248,7 +248,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)\n \tctx.fmt = CMIT_FMT_USERFORMAT;\n \tctx.abbrev = log->abbrev;\n \tctx.date_mode = log->date_mode;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = repo_get_log_output_encoding(the_repository);\n \n \tif (!log->summary) {\n \t\tif (log->user_format)\ndiff --git a/bundle.c b/bundle.c\nindex 42327f9739..7914a57b43 100644\n--- a/bundle.c\n+++ b/bundle.c\n@@ -461,7 +461,7 @@ static void write_bundle_prerequisites(struct commit *commit, void *data)\n \twrite_or_die(bpi->fd, buf.buf, buf.len);\n \n \tctx.fmt = CMIT_FMT_ONELINE;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = repo_get_log_output_encoding(the_repository);\n \tstrbuf_reset(&buf);\n \tpretty_print_commit(&ctx, commit, &buf);\n \tstrbuf_trim(&buf);\ndiff --git a/commit.c b/commit.c\nindex d16ae73345..d558db52dc 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1673,7 +1673,7 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \tsize_t i;\n \n \t/* Not having i18n.commitencoding is the same as having utf-8 */\n-\tencoding_is_utf8 = is_encoding_utf8(git_commit_encoding);\n+\tencoding_is_utf8 = is_encoding_utf8(repo_get_commit_output_encoding(the_repository));\n \n \tstrbuf_grow(buffer, 8192); /* should avoid reallocs for the headers */\n \tstrbuf_addf(buffer, \"tree %s\\n\", oid_to_hex(tree));\n@@ -1694,7 +1694,7 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \t\tcommitter = git_committer_info(IDENT_STRICT);\n \tstrbuf_addf(buffer, \"committer %s\\n\", committer);\n \tif (!encoding_is_utf8)\n-\t\tstrbuf_addf(buffer, \"encoding %s\\n\", git_commit_encoding);\n+\t\tstrbuf_addf(buffer, \"encoding %s\\n\", repo_get_commit_output_encoding(the_repository));\n \n \twhile (extra) {\n \t\tadd_extra_header(buffer, extra);\n@@ -1723,7 +1723,7 @@ int commit_tree_extended(const char *msg, size_t msg_len,\n \tsize_t i, nparents;\n \n \t/* Not having i18n.commitencoding is the same as having utf-8 */\n-\tencoding_is_utf8 = is_encoding_utf8(git_commit_encoding);\n+\tencoding_is_utf8 = is_encoding_utf8(repo_get_commit_output_encoding(the_repository));\n \n \todb_assert_oid_type(the_repository->objects, tree, OBJ_TREE);\n \ndiff --git a/environment.c b/environment.c\nindex 0026eb2274..9c2a26c3c1 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -50,8 +50,6 @@ int ignore_case;\n int assume_unchanged;\n int is_bare_repository_cfg = -1; /* unspecified */\n int warn_on_object_refname_ambiguity = 1;\n-char *git_commit_encoding;\n-char *git_log_output_encoding;\n char *apply_default_whitespace;\n char *apply_default_ignorewhitespace;\n char *git_attributes_file;\n@@ -197,15 +195,21 @@ const char *strip_namespace(const char *namespaced_ref)\n \treturn NULL;\n }\n \n-const char *get_log_output_encoding(void)\n+const char *repo_get_log_output_encoding(struct repository *r)\n {\n-\treturn git_log_output_encoding ? git_log_output_encoding\n-\t\t: get_commit_output_encoding();\n+\tprepare_repo_settings(r);\n+\n+\treturn r->settings.log_output_encoding ?\n+\t\tr->settings.log_output_encoding :\n+\t\trepo_get_commit_output_encoding(r);\n }\n \n-const char *get_commit_output_encoding(void)\n+const char *repo_get_commit_output_encoding(struct repository *r)\n {\n-\treturn git_commit_encoding ? git_commit_encoding : \"UTF-8\";\n+\tprepare_repo_settings(r);\n+\n+\treturn r->settings.commit_encoding ?\n+\t\tr->settings.commit_encoding : \"UTF-8\";\n }\n \n int use_optional_locks(void)\n@@ -566,22 +570,6 @@ static int git_default_sparse_config(const char *var, const char *value)\n \treturn 0;\n }\n \n-static int git_default_i18n_config(const char *var, const char *value)\n-{\n-\tif (!strcmp(var, \"i18n.commitencoding\")) {\n-\t\tFREE_AND_NULL(git_commit_encoding);\n-\t\treturn git_config_string(&git_commit_encoding, var, value);\n-\t}\n-\n-\tif (!strcmp(var, \"i18n.logoutputencoding\")) {\n-\t\tFREE_AND_NULL(git_log_output_encoding);\n-\t\treturn git_config_string(&git_log_output_encoding, var, value);\n-\t}\n-\n-\t/* Add other config variables here and to Documentation/config.adoc. */\n-\treturn 0;\n-}\n-\n static int git_default_branch_config(const char *var, const char *value)\n {\n \tif (!strcmp(var, \"branch.autosetupmerge\")) {\n@@ -688,9 +676,6 @@ int git_default_config(const char *var, const char *value,\n \t    starts_with(var, \"committer.\"))\n \t\treturn git_ident_config(var, value, ctx, cb);\n \n-\tif (starts_with(var, \"i18n.\"))\n-\t\treturn git_default_i18n_config(var, value);\n-\n \tif (starts_with(var, \"branch.\"))\n \t\treturn git_default_branch_config(var, value);\n \ndiff --git a/environment.h b/environment.h\nindex 27f657af04..eba8d5786c 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -193,11 +193,8 @@ extern enum object_creation_mode object_creation_mode;\n \n extern int grafts_keep_true_parents;\n \n-const char *get_log_output_encoding(void);\n-const char *get_commit_output_encoding(void);\n-\n-extern char *git_commit_encoding;\n-extern char *git_log_output_encoding;\n+const char *repo_get_log_output_encoding(struct repository *r);\n+const char *repo_get_commit_output_encoding(struct repository *r);\n \n extern char *editor_program;\n extern char *askpass_program;\ndiff --git a/log-tree.c b/log-tree.c\nindex 7e048701d0..aea3cbf7c6 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -859,7 +859,7 @@ void show_log(struct rev_info *opt)\n \n \t\traw = (opt->commit_format == CMIT_FMT_USERFORMAT);\n \t\tformat_display_notes(&commit->object.oid, &notebuf,\n-\t\t\t\t     get_log_output_encoding(), raw);\n+\t\t\t\t     repo_get_log_output_encoding(the_repository), raw);\n \t\tctx.notes_message = strbuf_detach(&notebuf, NULL);\n \t}\n \n@@ -879,7 +879,7 @@ void show_log(struct rev_info *opt)\n \tctx.mailmap = opt->mailmap;\n \tctx.color = opt->diffopt.use_color;\n \tctx.expand_tabs_in_log = opt->expand_tabs_in_log;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = repo_get_log_output_encoding(the_repository);\n \tctx.rev = opt;\n \tif (opt->from_ident.mail_begin && opt->from_ident.name_begin)\n \t\tctx.from_ident = &opt->from_ident;\ndiff --git a/pretty.c b/pretty.c\nindex e0646bbc5d..e939d0ff3b 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -2298,7 +2298,7 @@ void pretty_print_commit(struct pretty_print_context *pp,\n \t\treturn;\n \t}\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = repo_get_log_output_encoding(the_repository);\n \tmsg = reencoded = repo_logmsg_reencode(the_repository, commit, NULL,\n \t\t\t\t\t       encoding);\n \ndiff --git a/remote-curl.c b/remote-curl.c\nindex 92e40bb682..cd7e5e701a 100644\n--- a/remote-curl.c\n+++ b/remote-curl.c\n@@ -379,7 +379,8 @@ static int show_http_message(struct strbuf *type, struct strbuf *charset,\n \tif (strcmp(type->buf, \"text/plain\"))\n \t\treturn -1;\n \tif (charset->len)\n-\t\tstrbuf_reencode(msg, charset->buf, get_log_output_encoding());\n+\t\tstrbuf_reencode(msg, charset->buf,\n+\t\t\t\trepo_get_log_output_encoding(the_repository));\n \n \tstrbuf_trim(msg);\n \tif (!msg->len)\ndiff --git a/replay.c b/replay.c\nindex f97d652f33..45d539f8fc 100644\n--- a/replay.c\n+++ b/replay.c\n@@ -56,7 +56,7 @@ static struct commit *create_commit(struct repository *repo,\n \tchar *sign_commit = NULL; /* FIXME: cli users might want to sign again */\n \tstruct commit_extra_header *extra = NULL;\n \tstruct strbuf msg = STRBUF_INIT;\n-\tconst char *out_enc = get_commit_output_encoding();\n+\tconst char *out_enc = repo_get_commit_output_encoding(repo);\n \tconst char *message = repo_logmsg_reencode(repo, based_on,\n \t\t\t\t\t\t   NULL, out_enc);\n \tconst char *orig_message = NULL;\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 208e09ff17..de3b4c6ef1 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -32,6 +32,7 @@ void prepare_repo_settings(struct repository *r)\n \tint experimental;\n \tint value;\n \tconst char *strval;\n+\tchar *alloc_strval;\n \tint manyfiles;\n \tint read_changed_paths;\n \tunsigned long ulongval;\n@@ -154,6 +155,12 @@ void prepare_repo_settings(struct repository *r)\n \n \tif (!repo_config_get_ulong(r, \"core.packedgitlimit\", &ulongval))\n \t\tr->settings.packed_git_limit = ulongval;\n+\n+\tif (!repo_config_get_string(r, \"i18n.commitencoding\", &alloc_strval))\n+\t\tr->settings.commit_encoding = alloc_strval;\n+\n+\tif (!repo_config_get_string(r, \"i18n.logoutputencoding\", &alloc_strval))\n+\t\tr->settings.log_output_encoding = alloc_strval;\n }\n \n void repo_settings_clear(struct repository *r)\ndiff --git a/repo-settings.h b/repo-settings.h\nindex cad9c3f0cc..9a6b91a3a9 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -70,6 +70,9 @@ struct repo_settings {\n \tint max_allowed_tree_depth;\n \n \tchar *hooks_path;\n+\n+\tchar *commit_encoding;\n+\tchar *log_output_encoding;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\ndiff --git a/revision.c b/revision.c\nindex 29972c3a19..961ecd1d6c 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2675,11 +2675,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t} else if (!strcmp(arg, \"--invert-grep\")) {\n \t\trevs->grep_filter.no_body_match = 1;\n \t} else if ((argcount = parse_long_opt(\"encoding\", argv, &optarg))) {\n-\t\tfree(git_log_output_encoding);\n+\t\tprepare_repo_settings(revs->repo);\n+\t\tfree(revs->repo->settings.log_output_encoding);\n \t\tif (strcmp(optarg, \"none\"))\n-\t\t\tgit_log_output_encoding = xstrdup(optarg);\n+\t\t\trevs->repo->settings.log_output_encoding = xstrdup(optarg);\n \t\telse\n-\t\t\tgit_log_output_encoding = xstrdup(\"\");\n+\t\t\trevs->repo->settings.log_output_encoding = xstrdup(\"\");\n \t\treturn argcount;\n \t} else if (!strcmp(arg, \"--reverse\")) {\n \t\trevs->reverse ^= 1;\n@@ -3129,7 +3130,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \n \tdiff_setup_done(&revs->diffopt);\n \n-\tif (!is_encoding_utf8(get_log_output_encoding()))\n+\tif (!is_encoding_utf8(repo_get_log_output_encoding(the_repository)))\n \t\trevs->grep_filter.ignore_locale = 1;\n \tcompile_grep_patterns(&revs->grep_filter);\n \n@@ -4063,7 +4064,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)\n \t * so we will not end up with a buffer that has two different encodings\n \t * in it.\n \t */\n-\tencoding = get_log_output_encoding();\n+\tencoding = repo_get_log_output_encoding(the_repository);\n \tmessage = repo_logmsg_reencode(the_repository, commit, NULL, encoding);\n \n \t/* Copy the commit to temporary if we are using \"fake\" headers */\ndiff --git a/sequencer.c b/sequencer.c\nindex a3eb39bb25..612f47fd12 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -486,7 +486,7 @@ static int get_message(struct commit *commit, struct commit_message *out)\n \tint subject_len;\n \n \tout->message = repo_logmsg_reencode(the_repository, commit, NULL,\n-\t\t\t\t\t    get_commit_output_encoding());\n+\t\t\t\t\t    repo_get_commit_output_encoding(the_repository));\n \tabbrev = short_commit_name(the_repository, commit);\n \n \tsubject_len = find_commit_subject(out->message, &subject);\n@@ -1539,7 +1539,7 @@ static int try_to_commit(struct repository *r,\n \n \tif (flags & AMEND_MSG) {\n \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", \"gpgsig-sha256\", NULL };\n-\t\tconst char *out_enc = get_commit_output_encoding();\n+\t\tconst char *out_enc = repo_get_commit_output_encoding(r);\n \t\tconst char *message = repo_logmsg_reencode(r, current_head,\n \t\t\t\t\t\t\t   NULL, out_enc);\n \n@@ -2054,7 +2054,7 @@ static int update_squash_messages(struct repository *r,\n \tstruct strbuf buf = STRBUF_INIT;\n \tint res = 0;\n \tconst char *message, *body;\n-\tconst char *encoding = get_commit_output_encoding();\n+\tconst char *encoding = repo_get_commit_output_encoding(r);\n \n \tif (!is_fixup(command))\n \t\tBUG(\"not a FIXUP or SQUASH %d\", command);\n@@ -3344,7 +3344,7 @@ static int walk_revs_populate_todo(struct todo_list *todo_list,\n \tif (prepare_revs(opts))\n \t\treturn -1;\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = repo_get_log_output_encoding(the_repository);\n \n \twhile ((commit = get_revision(opts->revs))) {\n \t\tstruct todo_item *item = append_new_todo(todo_list);\n@@ -3730,7 +3730,7 @@ static int make_patch(struct repository *r,\n \t}\n \n \tif (!file_exists(rebase_path_message())) {\n-\t\tconst char *encoding = get_commit_output_encoding();\n+\t\tconst char *encoding = repo_get_commit_output_encoding(r);\n \t\tconst char *commit_buffer = repo_logmsg_reencode(r,\n \t\t\t\t\t\t\t\t commit, NULL,\n \t\t\t\t\t\t\t\t encoding);\n@@ -4187,7 +4187,7 @@ static int do_merge(struct repository *r,\n \t}\n \n \tif (commit) {\n-\t\tconst char *encoding = get_commit_output_encoding();\n+\t\tconst char *encoding = repo_get_commit_output_encoding(r);\n \t\tconst char *message = repo_logmsg_reencode(r, commit, NULL,\n \t\t\t\t\t\t\t   encoding);\n \t\tconst char *body;\n@@ -5311,7 +5311,7 @@ static int commit_staged_changes(struct repository *r,\n \t\t\t\tstruct commit *commit;\n \t\t\t\tconst char *msg;\n \t\t\t\tconst char *path = rebase_path_squash_msg();\n-\t\t\t\tconst char *encoding = get_commit_output_encoding();\n+\t\t\t\tconst char *encoding = repo_get_commit_output_encoding(r);\n \n \t\t\t\tif (parse_head(r, &commit)) {\n \t\t\t\t\tret = error(_(\"could not parse HEAD\"));\n@@ -6092,7 +6092,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out,\n \tget_commit_format(format, &revs);\n \tfree(format);\n \tpp.fmt = revs.commit_format;\n-\tpp.output_encoding = get_log_output_encoding();\n+\tpp.output_encoding = repo_get_log_output_encoding(r);\n \n \tsetup_revisions_from_strvec(argv, &revs, NULL);\n \tif (argv->nr > 1) {\ndiff --git a/submodule.c b/submodule.c\nindex 508938e4da..59f5c79d7f 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -479,7 +479,7 @@ static void print_submodule_diff_summary(struct repository *r, struct rev_info *\n \twhile ((commit = get_revision(rev))) {\n \t\tstruct pretty_print_context ctx = {0};\n \t\tctx.date_mode = rev->date_mode;\n-\t\tctx.output_encoding = get_log_output_encoding();\n+\t\tctx.output_encoding = repo_get_log_output_encoding(r);\n \t\tstrbuf_setlen(&sb, 0);\n \t\trepo_format_commit_message(r, commit, format, &sb,\n \t\t\t\t      &ctx);\n-- \n2.43.0\n\n"},{"id":"537402","messageId":"20260228190201.3684705-1-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260228040727.2057192-1-a3205153416@gmail.com","subject":"[PATCH v2 0/3] migrate encoding settings and bubble up repository","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-02-28T19:01:58Z","receivedAt":"2026-02-28T19:02:13Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"Hi everyone,\n\nAs part of the ongoing libification effort and my GSoC 2026 proposal,\nthis series migrates commit and log encoding settings into 'struct\nrepo_settings' and bubbles up the 'struct repository *' dependency.\n\nPreviously, 'git_commit_encoding' and 'git_log_output_encoding' were\nglobal, where core APIs implicitly rely on 'the_repository'. This\nseries resolves this in three steps:\n\n  - Patch 1: Moves encoding configs into 'repo_settings' using lazy\n    -loading, safely handling CLI overrides in 'revision.c'.\n\n  - Patch 2: Updates 'commit_tree()' and related APIs in 'commit.c'\n    to accept a repository context, passing it down the call chain.\n\n  - Patch 3: Updates 'pretty_print_commit()' and 'pp_commit_easy()'.\n    We leverage existing contextual pointers ('diffopt->repo' and \n    'revs->repo') to pass the repository downwards.\n\nTo maintain a clean boundary, leaf callers in 'builtin/' and top-level\ncomponents (e.g., 'bundle.c') fall back to 'the_repository'.\n\n(Though series passes the full test suite and is verified with 'S\nANITIZE=address,undefined', I'm quite certain I must have inadvertently\nleft out some parts. Therefore, this patch series is currently more\nof a self-archival exercise than a final submission.\n\nFor example, I might have left out some of the exsiting contextual\npointers in patch 2. Will check in the following days.)\n\nRegards,\n\nYuchen\n\nTian Yuchen (3):\n  environment: migrate encoding settings to repo-settings\n  commit: pass 'struct repository' to commit creation APIs\n  pretty: pass 'struct repository' to pretty_print_commit()\n\n builtin/am.c          |  6 +++---\n builtin/blame.c       |  2 +-\n builtin/checkout.c    |  4 ++--\n builtin/commit-tree.c |  2 +-\n builtin/commit.c      |  8 ++++----\n builtin/history.c     |  2 +-\n builtin/log.c         |  4 ++--\n builtin/mailinfo.c    |  2 +-\n builtin/merge.c       |  6 +++---\n builtin/rebase.c      |  2 +-\n builtin/reset.c       |  2 +-\n builtin/rev-list.c    |  4 ++--\n builtin/shortlog.c    |  4 ++--\n builtin/show-branch.c |  2 +-\n builtin/stash.c       | 12 ++++++------\n bundle.c              |  4 ++--\n commit.c              | 31 +++++++++++++++++--------------\n commit.h              |  6 ++++--\n diff.c                |  2 +-\n environment.c         | 37 +++++++++++--------------------------\n environment.h         |  7 ++-----\n log-tree.c            |  6 +++---\n notes-cache.c         |  4 ++--\n notes-cache.h         |  2 +-\n notes-utils.c         |  2 +-\n pretty.c              | 13 +++++++------\n pretty.h              |  4 ++--\n range-diff.c          | 10 +++++-----\n remote-curl.c         |  3 ++-\n replay.c              |  4 ++--\n repo-settings.c       |  7 +++++++\n repo-settings.h       |  3 +++\n revision.c            | 11 ++++++-----\n sequencer.c           | 36 ++++++++++++++++++------------------\n submodule.c           |  2 +-\n 35 files changed, 128 insertions(+), 128 deletions(-)\n\n-- \n2.43.0\n\n"},{"id":"537403","messageId":"20260228190201.3684705-2-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260228190201.3684705-1-a3205153416@gmail.com","subject":"[PATCH v2 1/3] environment: migrate encoding settings to repo-settings","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-02-28T19:01:59Z","receivedAt":"2026-02-28T19:05:58Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"Global variables 'git_commit_encoding' and 'git_log_output_encoding'\nhinder the ongoing libification effort by binding functions to a\nsingle global state.\n\nMove both variables into 'struct repo_settings' to enable lazy loading.\nThey are migrated together in this patch because the log encoding\ndirectly falls back to the commit encoding.\n\nUpdate callers to use the new 'repo_get_commit_output_encoding()' and\n'repo_get_log_output_encoding()' apis. Functions now accept 'struct\nrepository' to bubble up dependency where possible. For callers in the\n'builtin/' directory, and for core library functions that do not yet\nreceive a repository context, 'the_repository' is used as a fallback.\n\nAdditionally, in 'revision.c', ensure 'prepare_repo_settings()' is\ntriggered before CLI overrides, for example, '--encoding', to prevent\nlazy-loading from mistakenly overwriting command-line choice later.\n\nAll tests passed, no memory leak.\n\nSigned-off-by: Tian Yuchen <a3205153416@gmail.com>\n---\n builtin/am.c       |  4 ++--\n builtin/blame.c    |  2 +-\n builtin/commit.c   |  6 +++---\n builtin/log.c      |  2 +-\n builtin/mailinfo.c |  2 +-\n builtin/rev-list.c |  2 +-\n builtin/shortlog.c |  2 +-\n bundle.c           |  2 +-\n commit.c           |  6 +++---\n environment.c      | 37 +++++++++++--------------------------\n environment.h      |  7 ++-----\n log-tree.c         |  4 ++--\n pretty.c           |  2 +-\n remote-curl.c      |  3 ++-\n replay.c           |  2 +-\n repo-settings.c    |  7 +++++++\n repo-settings.h    |  3 +++\n revision.c         | 11 ++++++-----\n sequencer.c        | 16 ++++++++--------\n submodule.c        |  2 +-\n 20 files changed, 58 insertions(+), 64 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex e0c767e223..96b8c00007 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1216,7 +1216,7 @@ static int parse_mail(struct am_state *state, const char *mail)\n \tsetup_mailinfo(the_repository, &mi);\n \n \tif (state->utf8)\n-\t\tmi.metainfo_charset = get_commit_output_encoding();\n+\t\tmi.metainfo_charset = repo_get_commit_output_encoding(the_repository);\n \telse\n \t\tmi.metainfo_charset = NULL;\n \n@@ -1355,7 +1355,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit)\n \tstruct ident_split id;\n \n \tbuffer = repo_logmsg_reencode(the_repository, commit, NULL,\n-\t\t\t\t      get_commit_output_encoding());\n+\t\t\t\t      repo_get_commit_output_encoding(the_repository));\n \n \tident_line = find_commit_header(buffer, \"author\", &ident_len);\n \tif (!ident_line)\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex eac2fe7320..cc82182c51 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -202,7 +202,7 @@ static void get_commit_info(struct commit *commit, struct commit_info *ret)\n \tconst char *subject, *encoding;\n \tconst char *message;\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = repo_get_log_output_encoding(the_repository);\n \tmessage = repo_logmsg_reencode(the_repository, commit, NULL, encoding);\n \tget_ac_line(message, \"\\nauthor \",\n \t\t    &ret->author, &ret->author_mail,\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 9e3a09d532..2bbdd4c4c3 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -794,7 +794,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\t\tc = lookup_commit_reference_by_name(squash_message);\n \t\t\tif (!c)\n \t\t\t\tdie(_(\"could not lookup commit '%s'\"), squash_message);\n-\t\t\tctx.output_encoding = get_commit_output_encoding();\n+\t\t\tctx.output_encoding = repo_get_commit_output_encoding(the_repository);\n \t\t\trepo_format_commit_message(the_repository, c,\n \t\t\t\t\t\t   \"squash! %s\\n\\n\", &sb,\n \t\t\t\t\t\t   &ctx);\n@@ -829,7 +829,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\tcommit = lookup_commit_reference_by_name(fixup_commit);\n \t\tif (!commit)\n \t\t\tdie(_(\"could not lookup commit '%s'\"), fixup_commit);\n-\t\tctx.output_encoding = get_commit_output_encoding();\n+\t\tctx.output_encoding = repo_get_commit_output_encoding(the_repository);\n \t\tfmt = xstrfmt(\"%s! %%s\\n\\n\", fixup_prefix);\n \t\trepo_format_commit_message(the_repository, commit, fmt, &sb,\n \t\t\t\t\t   &ctx);\n@@ -1235,7 +1235,7 @@ static const char *read_commit_message(const char *name)\n \tcommit = lookup_commit_reference_by_name(name);\n \tif (!commit)\n \t\tdie(_(\"could not lookup commit '%s'\"), name);\n-\tout_enc = get_commit_output_encoding();\n+\tout_enc = repo_get_commit_output_encoding(the_repository);\n \treturn repo_logmsg_reencode(the_repository, commit, NULL, out_enc);\n }\n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 8ab6d3a943..1c9ec09098 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -568,7 +568,7 @@ static void show_tagger(const char *buf, struct rev_info *rev)\n \n \tpp.fmt = rev->commit_format;\n \tpp.date_mode = rev->date_mode;\n-\tpp_user_info(&pp, \"Tagger\", &out, buf, get_log_output_encoding());\n+\tpp_user_info(&pp, \"Tagger\", &out, buf, repo_get_log_output_encoding(the_repository));\n \tfprintf(rev->diffopt.file, \"%s\", out.buf);\n \tstrbuf_release(&out);\n }\ndiff --git a/builtin/mailinfo.c b/builtin/mailinfo.c\nindex 8de7ba7de1..eab4e05850 100644\n--- a/builtin/mailinfo.c\n+++ b/builtin/mailinfo.c\n@@ -93,7 +93,7 @@ int cmd_mailinfo(int argc,\n \n \tswitch (meta_charset.policy) {\n \tcase CHARSET_DEFAULT:\n-\t\tmi.metainfo_charset = get_commit_output_encoding();\n+\t\tmi.metainfo_charset = repo_get_commit_output_encoding(the_repository);\n \t\tbreak;\n \tcase CHARSET_NO_REENCODE:\n \t\tmi.metainfo_charset = NULL;\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex ddea8aa251..3c6a2914d8 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -304,7 +304,7 @@ static void show_commit(struct commit *commit, void *data)\n \t\tctx.date_mode = revs->date_mode;\n \t\tctx.date_mode_explicit = revs->date_mode_explicit;\n \t\tctx.fmt = revs->commit_format;\n-\t\tctx.output_encoding = get_log_output_encoding();\n+\t\tctx.output_encoding = repo_get_log_output_encoding(the_repository);\n \t\tctx.color = revs->diffopt.use_color;\n \t\tctx.rev = revs;\n \t\tpretty_print_commit(&ctx, commit, &buf);\ndiff --git a/builtin/shortlog.c b/builtin/shortlog.c\nindex d80bf1a7d0..ce9f20de2f 100644\n--- a/builtin/shortlog.c\n+++ b/builtin/shortlog.c\n@@ -248,7 +248,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)\n \tctx.fmt = CMIT_FMT_USERFORMAT;\n \tctx.abbrev = log->abbrev;\n \tctx.date_mode = log->date_mode;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = repo_get_log_output_encoding(the_repository);\n \n \tif (!log->summary) {\n \t\tif (log->user_format)\ndiff --git a/bundle.c b/bundle.c\nindex 42327f9739..7914a57b43 100644\n--- a/bundle.c\n+++ b/bundle.c\n@@ -461,7 +461,7 @@ static void write_bundle_prerequisites(struct commit *commit, void *data)\n \twrite_or_die(bpi->fd, buf.buf, buf.len);\n \n \tctx.fmt = CMIT_FMT_ONELINE;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = repo_get_log_output_encoding(the_repository);\n \tstrbuf_reset(&buf);\n \tpretty_print_commit(&ctx, commit, &buf);\n \tstrbuf_trim(&buf);\ndiff --git a/commit.c b/commit.c\nindex d16ae73345..d558db52dc 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1673,7 +1673,7 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \tsize_t i;\n \n \t/* Not having i18n.commitencoding is the same as having utf-8 */\n-\tencoding_is_utf8 = is_encoding_utf8(git_commit_encoding);\n+\tencoding_is_utf8 = is_encoding_utf8(repo_get_commit_output_encoding(the_repository));\n \n \tstrbuf_grow(buffer, 8192); /* should avoid reallocs for the headers */\n \tstrbuf_addf(buffer, \"tree %s\\n\", oid_to_hex(tree));\n@@ -1694,7 +1694,7 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \t\tcommitter = git_committer_info(IDENT_STRICT);\n \tstrbuf_addf(buffer, \"committer %s\\n\", committer);\n \tif (!encoding_is_utf8)\n-\t\tstrbuf_addf(buffer, \"encoding %s\\n\", git_commit_encoding);\n+\t\tstrbuf_addf(buffer, \"encoding %s\\n\", repo_get_commit_output_encoding(the_repository));\n \n \twhile (extra) {\n \t\tadd_extra_header(buffer, extra);\n@@ -1723,7 +1723,7 @@ int commit_tree_extended(const char *msg, size_t msg_len,\n \tsize_t i, nparents;\n \n \t/* Not having i18n.commitencoding is the same as having utf-8 */\n-\tencoding_is_utf8 = is_encoding_utf8(git_commit_encoding);\n+\tencoding_is_utf8 = is_encoding_utf8(repo_get_commit_output_encoding(the_repository));\n \n \todb_assert_oid_type(the_repository->objects, tree, OBJ_TREE);\n \ndiff --git a/environment.c b/environment.c\nindex 0026eb2274..9c2a26c3c1 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -50,8 +50,6 @@ int ignore_case;\n int assume_unchanged;\n int is_bare_repository_cfg = -1; /* unspecified */\n int warn_on_object_refname_ambiguity = 1;\n-char *git_commit_encoding;\n-char *git_log_output_encoding;\n char *apply_default_whitespace;\n char *apply_default_ignorewhitespace;\n char *git_attributes_file;\n@@ -197,15 +195,21 @@ const char *strip_namespace(const char *namespaced_ref)\n \treturn NULL;\n }\n \n-const char *get_log_output_encoding(void)\n+const char *repo_get_log_output_encoding(struct repository *r)\n {\n-\treturn git_log_output_encoding ? git_log_output_encoding\n-\t\t: get_commit_output_encoding();\n+\tprepare_repo_settings(r);\n+\n+\treturn r->settings.log_output_encoding ?\n+\t\tr->settings.log_output_encoding :\n+\t\trepo_get_commit_output_encoding(r);\n }\n \n-const char *get_commit_output_encoding(void)\n+const char *repo_get_commit_output_encoding(struct repository *r)\n {\n-\treturn git_commit_encoding ? git_commit_encoding : \"UTF-8\";\n+\tprepare_repo_settings(r);\n+\n+\treturn r->settings.commit_encoding ?\n+\t\tr->settings.commit_encoding : \"UTF-8\";\n }\n \n int use_optional_locks(void)\n@@ -566,22 +570,6 @@ static int git_default_sparse_config(const char *var, const char *value)\n \treturn 0;\n }\n \n-static int git_default_i18n_config(const char *var, const char *value)\n-{\n-\tif (!strcmp(var, \"i18n.commitencoding\")) {\n-\t\tFREE_AND_NULL(git_commit_encoding);\n-\t\treturn git_config_string(&git_commit_encoding, var, value);\n-\t}\n-\n-\tif (!strcmp(var, \"i18n.logoutputencoding\")) {\n-\t\tFREE_AND_NULL(git_log_output_encoding);\n-\t\treturn git_config_string(&git_log_output_encoding, var, value);\n-\t}\n-\n-\t/* Add other config variables here and to Documentation/config.adoc. */\n-\treturn 0;\n-}\n-\n static int git_default_branch_config(const char *var, const char *value)\n {\n \tif (!strcmp(var, \"branch.autosetupmerge\")) {\n@@ -688,9 +676,6 @@ int git_default_config(const char *var, const char *value,\n \t    starts_with(var, \"committer.\"))\n \t\treturn git_ident_config(var, value, ctx, cb);\n \n-\tif (starts_with(var, \"i18n.\"))\n-\t\treturn git_default_i18n_config(var, value);\n-\n \tif (starts_with(var, \"branch.\"))\n \t\treturn git_default_branch_config(var, value);\n \ndiff --git a/environment.h b/environment.h\nindex 27f657af04..eba8d5786c 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -193,11 +193,8 @@ extern enum object_creation_mode object_creation_mode;\n \n extern int grafts_keep_true_parents;\n \n-const char *get_log_output_encoding(void);\n-const char *get_commit_output_encoding(void);\n-\n-extern char *git_commit_encoding;\n-extern char *git_log_output_encoding;\n+const char *repo_get_log_output_encoding(struct repository *r);\n+const char *repo_get_commit_output_encoding(struct repository *r);\n \n extern char *editor_program;\n extern char *askpass_program;\ndiff --git a/log-tree.c b/log-tree.c\nindex 7e048701d0..aea3cbf7c6 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -859,7 +859,7 @@ void show_log(struct rev_info *opt)\n \n \t\traw = (opt->commit_format == CMIT_FMT_USERFORMAT);\n \t\tformat_display_notes(&commit->object.oid, &notebuf,\n-\t\t\t\t     get_log_output_encoding(), raw);\n+\t\t\t\t     repo_get_log_output_encoding(the_repository), raw);\n \t\tctx.notes_message = strbuf_detach(&notebuf, NULL);\n \t}\n \n@@ -879,7 +879,7 @@ void show_log(struct rev_info *opt)\n \tctx.mailmap = opt->mailmap;\n \tctx.color = opt->diffopt.use_color;\n \tctx.expand_tabs_in_log = opt->expand_tabs_in_log;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = repo_get_log_output_encoding(the_repository);\n \tctx.rev = opt;\n \tif (opt->from_ident.mail_begin && opt->from_ident.name_begin)\n \t\tctx.from_ident = &opt->from_ident;\ndiff --git a/pretty.c b/pretty.c\nindex e0646bbc5d..e939d0ff3b 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -2298,7 +2298,7 @@ void pretty_print_commit(struct pretty_print_context *pp,\n \t\treturn;\n \t}\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = repo_get_log_output_encoding(the_repository);\n \tmsg = reencoded = repo_logmsg_reencode(the_repository, commit, NULL,\n \t\t\t\t\t       encoding);\n \ndiff --git a/remote-curl.c b/remote-curl.c\nindex 92e40bb682..cd7e5e701a 100644\n--- a/remote-curl.c\n+++ b/remote-curl.c\n@@ -379,7 +379,8 @@ static int show_http_message(struct strbuf *type, struct strbuf *charset,\n \tif (strcmp(type->buf, \"text/plain\"))\n \t\treturn -1;\n \tif (charset->len)\n-\t\tstrbuf_reencode(msg, charset->buf, get_log_output_encoding());\n+\t\tstrbuf_reencode(msg, charset->buf,\n+\t\t\t\trepo_get_log_output_encoding(the_repository));\n \n \tstrbuf_trim(msg);\n \tif (!msg->len)\ndiff --git a/replay.c b/replay.c\nindex f97d652f33..45d539f8fc 100644\n--- a/replay.c\n+++ b/replay.c\n@@ -56,7 +56,7 @@ static struct commit *create_commit(struct repository *repo,\n \tchar *sign_commit = NULL; /* FIXME: cli users might want to sign again */\n \tstruct commit_extra_header *extra = NULL;\n \tstruct strbuf msg = STRBUF_INIT;\n-\tconst char *out_enc = get_commit_output_encoding();\n+\tconst char *out_enc = repo_get_commit_output_encoding(repo);\n \tconst char *message = repo_logmsg_reencode(repo, based_on,\n \t\t\t\t\t\t   NULL, out_enc);\n \tconst char *orig_message = NULL;\ndiff --git a/repo-settings.c b/repo-settings.c\nindex 208e09ff17..de3b4c6ef1 100644\n--- a/repo-settings.c\n+++ b/repo-settings.c\n@@ -32,6 +32,7 @@ void prepare_repo_settings(struct repository *r)\n \tint experimental;\n \tint value;\n \tconst char *strval;\n+\tchar *alloc_strval;\n \tint manyfiles;\n \tint read_changed_paths;\n \tunsigned long ulongval;\n@@ -154,6 +155,12 @@ void prepare_repo_settings(struct repository *r)\n \n \tif (!repo_config_get_ulong(r, \"core.packedgitlimit\", &ulongval))\n \t\tr->settings.packed_git_limit = ulongval;\n+\n+\tif (!repo_config_get_string(r, \"i18n.commitencoding\", &alloc_strval))\n+\t\tr->settings.commit_encoding = alloc_strval;\n+\n+\tif (!repo_config_get_string(r, \"i18n.logoutputencoding\", &alloc_strval))\n+\t\tr->settings.log_output_encoding = alloc_strval;\n }\n \n void repo_settings_clear(struct repository *r)\ndiff --git a/repo-settings.h b/repo-settings.h\nindex cad9c3f0cc..9a6b91a3a9 100644\n--- a/repo-settings.h\n+++ b/repo-settings.h\n@@ -70,6 +70,9 @@ struct repo_settings {\n \tint max_allowed_tree_depth;\n \n \tchar *hooks_path;\n+\n+\tchar *commit_encoding;\n+\tchar *log_output_encoding;\n };\n #define REPO_SETTINGS_INIT { \\\n \t.shared_repository = -1, \\\ndiff --git a/revision.c b/revision.c\nindex 29972c3a19..961ecd1d6c 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2675,11 +2675,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t} else if (!strcmp(arg, \"--invert-grep\")) {\n \t\trevs->grep_filter.no_body_match = 1;\n \t} else if ((argcount = parse_long_opt(\"encoding\", argv, &optarg))) {\n-\t\tfree(git_log_output_encoding);\n+\t\tprepare_repo_settings(revs->repo);\n+\t\tfree(revs->repo->settings.log_output_encoding);\n \t\tif (strcmp(optarg, \"none\"))\n-\t\t\tgit_log_output_encoding = xstrdup(optarg);\n+\t\t\trevs->repo->settings.log_output_encoding = xstrdup(optarg);\n \t\telse\n-\t\t\tgit_log_output_encoding = xstrdup(\"\");\n+\t\t\trevs->repo->settings.log_output_encoding = xstrdup(\"\");\n \t\treturn argcount;\n \t} else if (!strcmp(arg, \"--reverse\")) {\n \t\trevs->reverse ^= 1;\n@@ -3129,7 +3130,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \n \tdiff_setup_done(&revs->diffopt);\n \n-\tif (!is_encoding_utf8(get_log_output_encoding()))\n+\tif (!is_encoding_utf8(repo_get_log_output_encoding(the_repository)))\n \t\trevs->grep_filter.ignore_locale = 1;\n \tcompile_grep_patterns(&revs->grep_filter);\n \n@@ -4063,7 +4064,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)\n \t * so we will not end up with a buffer that has two different encodings\n \t * in it.\n \t */\n-\tencoding = get_log_output_encoding();\n+\tencoding = repo_get_log_output_encoding(the_repository);\n \tmessage = repo_logmsg_reencode(the_repository, commit, NULL, encoding);\n \n \t/* Copy the commit to temporary if we are using \"fake\" headers */\ndiff --git a/sequencer.c b/sequencer.c\nindex a3eb39bb25..612f47fd12 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -486,7 +486,7 @@ static int get_message(struct commit *commit, struct commit_message *out)\n \tint subject_len;\n \n \tout->message = repo_logmsg_reencode(the_repository, commit, NULL,\n-\t\t\t\t\t    get_commit_output_encoding());\n+\t\t\t\t\t    repo_get_commit_output_encoding(the_repository));\n \tabbrev = short_commit_name(the_repository, commit);\n \n \tsubject_len = find_commit_subject(out->message, &subject);\n@@ -1539,7 +1539,7 @@ static int try_to_commit(struct repository *r,\n \n \tif (flags & AMEND_MSG) {\n \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", \"gpgsig-sha256\", NULL };\n-\t\tconst char *out_enc = get_commit_output_encoding();\n+\t\tconst char *out_enc = repo_get_commit_output_encoding(r);\n \t\tconst char *message = repo_logmsg_reencode(r, current_head,\n \t\t\t\t\t\t\t   NULL, out_enc);\n \n@@ -2054,7 +2054,7 @@ static int update_squash_messages(struct repository *r,\n \tstruct strbuf buf = STRBUF_INIT;\n \tint res = 0;\n \tconst char *message, *body;\n-\tconst char *encoding = get_commit_output_encoding();\n+\tconst char *encoding = repo_get_commit_output_encoding(r);\n \n \tif (!is_fixup(command))\n \t\tBUG(\"not a FIXUP or SQUASH %d\", command);\n@@ -3344,7 +3344,7 @@ static int walk_revs_populate_todo(struct todo_list *todo_list,\n \tif (prepare_revs(opts))\n \t\treturn -1;\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = repo_get_log_output_encoding(the_repository);\n \n \twhile ((commit = get_revision(opts->revs))) {\n \t\tstruct todo_item *item = append_new_todo(todo_list);\n@@ -3730,7 +3730,7 @@ static int make_patch(struct repository *r,\n \t}\n \n \tif (!file_exists(rebase_path_message())) {\n-\t\tconst char *encoding = get_commit_output_encoding();\n+\t\tconst char *encoding = repo_get_commit_output_encoding(r);\n \t\tconst char *commit_buffer = repo_logmsg_reencode(r,\n \t\t\t\t\t\t\t\t commit, NULL,\n \t\t\t\t\t\t\t\t encoding);\n@@ -4187,7 +4187,7 @@ static int do_merge(struct repository *r,\n \t}\n \n \tif (commit) {\n-\t\tconst char *encoding = get_commit_output_encoding();\n+\t\tconst char *encoding = repo_get_commit_output_encoding(r);\n \t\tconst char *message = repo_logmsg_reencode(r, commit, NULL,\n \t\t\t\t\t\t\t   encoding);\n \t\tconst char *body;\n@@ -5311,7 +5311,7 @@ static int commit_staged_changes(struct repository *r,\n \t\t\t\tstruct commit *commit;\n \t\t\t\tconst char *msg;\n \t\t\t\tconst char *path = rebase_path_squash_msg();\n-\t\t\t\tconst char *encoding = get_commit_output_encoding();\n+\t\t\t\tconst char *encoding = repo_get_commit_output_encoding(r);\n \n \t\t\t\tif (parse_head(r, &commit)) {\n \t\t\t\t\tret = error(_(\"could not parse HEAD\"));\n@@ -6092,7 +6092,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out,\n \tget_commit_format(format, &revs);\n \tfree(format);\n \tpp.fmt = revs.commit_format;\n-\tpp.output_encoding = get_log_output_encoding();\n+\tpp.output_encoding = repo_get_log_output_encoding(r);\n \n \tsetup_revisions_from_strvec(argv, &revs, NULL);\n \tif (argv->nr > 1) {\ndiff --git a/submodule.c b/submodule.c\nindex 508938e4da..59f5c79d7f 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -479,7 +479,7 @@ static void print_submodule_diff_summary(struct repository *r, struct rev_info *\n \twhile ((commit = get_revision(rev))) {\n \t\tstruct pretty_print_context ctx = {0};\n \t\tctx.date_mode = rev->date_mode;\n-\t\tctx.output_encoding = get_log_output_encoding();\n+\t\tctx.output_encoding = repo_get_log_output_encoding(r);\n \t\tstrbuf_setlen(&sb, 0);\n \t\trepo_format_commit_message(r, commit, format, &sb,\n \t\t\t\t      &ctx);\n-- \n2.43.0\n\n"},{"id":"537404","messageId":"20260228190201.3684705-3-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260228190201.3684705-1-a3205153416@gmail.com","subject":"[PATCH v2 2/3] commit: pass 'struct repository' to commit creation APIs","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-02-28T19:02:00Z","receivedAt":"2026-02-28T19:06:06Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"Following the migration of encoding settings into 'struct repo_settings',\ncore commit creation functions in 'commit.c' now require a repository\ncontext to query the commit output encoding.\n\nUpdate the signatures of 'commit_tree()' and 'commit_tree_extended()',\nas well as the internal 'write_commit_tree()', to accept 'struct\nrepository *' as their first argument so they can call\n'repo_get_commit_output_encoding(r)/(repo)' without relying on the global\n'the_repository' macro.\n\nConsequently, update all callers across the codebase to pass the\nrepository context down the call chain. To facilitate this dependency\nbubbling, update the signatures of several intermediate helper functions,\nexplicitly 'notes_cache_write()' and 'get_message()' (in sequencer.c).\n\nFor callers in the 'builtin/' directory, fallback to using\n'the_repository'.\n\nSigned-off-by: Tian Yuchen <a3205153416@gmail.com>\n---\n builtin/am.c          |  2 +-\n builtin/commit-tree.c |  2 +-\n builtin/commit.c      |  2 +-\n builtin/history.c     |  2 +-\n builtin/merge.c       |  4 ++--\n builtin/rebase.c      |  2 +-\n builtin/stash.c       | 10 +++++-----\n commit.c              | 31 +++++++++++++++++--------------\n commit.h              |  6 ++++--\n diff.c                |  2 +-\n notes-cache.c         |  4 ++--\n notes-cache.h         |  2 +-\n notes-utils.c         |  2 +-\n replay.c              |  2 +-\n sequencer.c           | 12 ++++++------\n 15 files changed, 45 insertions(+), 40 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 96b8c00007..eee3c9864c 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1699,7 +1699,7 @@ static void do_commit(const struct am_state *state)\n \t\t\t\t\t\t\t : state->author_date,\n \t\t\t\t      IDENT_STRICT);\n \n-\tif (commit_tree_extended(state->msg, state->msg_len, &tree, parents,\n+\tif (commit_tree_extended(the_repository, state->msg, state->msg_len, &tree, parents,\n \t\t\t\t &commit, author, committer, state->sign_commit,\n \t\t\t\t NULL))\n \t\tdie(_(\"failed to write commit object\"));\ndiff --git a/builtin/commit-tree.c b/builtin/commit-tree.c\nindex 30535db131..c489749588 100644\n--- a/builtin/commit-tree.c\n+++ b/builtin/commit-tree.c\n@@ -144,7 +144,7 @@ int cmd_commit_tree(int argc,\n \t\t\tdie_errno(_(\"git commit-tree: failed to read\"));\n \t}\n \n-\tif (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,\n+\tif (commit_tree(the_repository, buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,\n \t\t\tNULL, sign_commit)) {\n \t\tret = 1;\n \t\tgoto out;\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 2bbdd4c4c3..da2b8ce541 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -1931,7 +1931,7 @@ int cmd_commit(int argc,\n \t\tappend_merge_tag_headers(parents, &tail);\n \t}\n \n-\tif (commit_tree_extended(sb.buf, sb.len, &the_repository->index->cache_tree->oid,\n+\tif (commit_tree_extended(the_repository, sb.buf, sb.len, &the_repository->index->cache_tree->oid,\n \t\t\t\t parents, &oid, author_ident.buf, NULL,\n \t\t\t\t sign_commit, extra)) {\n \t\trollback_index_files();\ndiff --git a/builtin/history.c b/builtin/history.c\nindex 8dcb9a6046..ca36d065a5 100644\n--- a/builtin/history.c\n+++ b/builtin/history.c\n@@ -136,7 +136,7 @@ static int commit_tree_with_edited_message(struct repository *repo,\n \n \toriginal_extra_headers = read_commit_extra_headers(original, exclude_gpgsig);\n \n-\tret = commit_tree_extended(commit_message.buf, commit_message.len, &original_tree_oid,\n+\tret = commit_tree_extended(the_repository, commit_message.buf, commit_message.len, &original_tree_oid,\n \t\t\t\t   original->parents, &rewritten_commit_oid, original_author,\n \t\t\t\t   NULL, NULL, original_extra_headers);\n \tif (ret < 0)\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 4e456a381c..7c944fe179 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -1000,7 +1000,7 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)\n \tpptr = commit_list_append(head, pptr);\n \tpptr = commit_list_append(remoteheads->item, pptr);\n \tprepare_to_commit(remoteheads);\n-\tif (commit_tree(merge_msg.buf, merge_msg.len, &result_tree, parents,\n+\tif (commit_tree(the_repository, merge_msg.buf, merge_msg.len, &result_tree, parents,\n \t\t\t&result_commit, NULL, sign_commit))\n \t\tdie(_(\"failed to write commit object\"));\n \tfinish(head, remoteheads, &result_commit, \"In-index merge\");\n@@ -1027,7 +1027,7 @@ static int finish_automerge(struct commit *head,\n \tif (!head_subsumed || fast_forward == FF_NO)\n \t\tcommit_list_insert(head, &parents);\n \tprepare_to_commit(remoteheads);\n-\tif (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents,\n+\tif (commit_tree(the_repository, merge_msg.buf, merge_msg.len, result_tree, parents,\n \t\t\t&result_commit, NULL, sign_commit))\n \t\tdie(_(\"failed to write commit object\"));\n \tstrbuf_addf(&buf, \"Merge made by the '%s' strategy.\", wt_strategy);\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex c487e10907..7b9ab85cc0 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1647,7 +1647,7 @@ int cmd_rebase(int argc,\n \t\toptions.upstream_arg = options.upstream_name;\n \t} else {\n \t\tif (!options.onto_name) {\n-\t\t\tif (commit_tree(\"\", 0, the_hash_algo->empty_tree, NULL,\n+\t\t\tif (commit_tree(the_repository, \"\", 0, the_hash_algo->empty_tree, NULL,\n \t\t\t\t\t&squash_onto, NULL, NULL) < 0)\n \t\t\t\tdie(_(\"Could not create new root commit\"));\n \t\t\toptions.squash_onto = &squash_onto;\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex f06cfa7989..3d94726251 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -1258,7 +1258,7 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg,\n \t\tgoto done;\n \t}\n \n-\tif (commit_tree(untracked_msg.buf, untracked_msg.len,\n+\tif (commit_tree(the_repository, untracked_msg.buf, untracked_msg.len,\n \t\t\t&info->u_tree, NULL, &info->u_commit, NULL, NULL)) {\n \t\tret = -1;\n \t\tgoto done;\n@@ -1486,7 +1486,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \tcommit_list_insert(head_commit, &parents);\n \tif (write_index_as_tree(&info->i_tree, the_repository->index,\n \t\t\t\trepo_get_index_file(the_repository), 0, NULL) ||\n-\t    commit_tree(commit_tree_label.buf, commit_tree_label.len,\n+\t    commit_tree(the_repository, commit_tree_label.buf, commit_tree_label.len,\n \t\t\t&info->i_tree, parents, &info->i_commit, NULL, NULL)) {\n \t\tif (!quiet)\n \t\t\tfprintf_ln(stderr, _(\"Cannot save the current \"\n@@ -1551,7 +1551,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \t\t\t   &parents);\n \tcommit_list_insert(head_commit, &parents);\n \n-\tif (commit_tree(stash_msg_buf->buf, stash_msg_buf->len, &info->w_tree,\n+\tif (commit_tree(the_repository, stash_msg_buf->buf, stash_msg_buf->len, &info->w_tree,\n \t\t\tparents, &info->w_commit, NULL, NULL)) {\n \t\tif (!quiet)\n \t\t\tfprintf_ln(stderr, _(\"Cannot record \"\n@@ -2035,7 +2035,7 @@ static int write_commit_with_parents(struct repository *r,\n \tauthor = xmemdupz(orig_author, author_len);\n \tcommitter = xmemdupz(orig_committer, committer_len);\n \n-\tif (commit_tree_extended(msg.buf, msg.len,\n+\tif (commit_tree_extended(the_repository, msg.buf, msg.len,\n \t\t\t\t r->hash_algo->empty_tree, parents,\n \t\t\t\t out, author, committer,\n \t\t\t\t NULL, NULL)) {\n@@ -2258,7 +2258,7 @@ static int do_export_stash(struct repository *r,\n \t\t\t      \"2001-09-17T00:00:00Z\", 0);\n \n \t/* First, we create a single empty commit. */\n-\tif (commit_tree_extended(\"\", 0, r->hash_algo->empty_tree, NULL,\n+\tif (commit_tree_extended(the_repository, \"\", 0, r->hash_algo->empty_tree, NULL,\n \t\t\t\t &base, author, committer, NULL, NULL))\n \t\treturn error(_(\"unable to write base commit\"));\n \ndiff --git a/commit.c b/commit.c\nindex d558db52dc..b05cd8d9da 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1534,7 +1534,8 @@ void free_commit_extra_headers(struct commit_extra_header *extra)\n \t}\n }\n \n-int commit_tree(const char *msg, size_t msg_len, const struct object_id *tree,\n+int commit_tree(struct repository *r,\n+\t\tconst char *msg, size_t msg_len, const struct object_id *tree,\n \t\tconst struct commit_list *parents, struct object_id *ret,\n \t\tconst char *author, const char *sign_commit)\n {\n@@ -1542,7 +1543,7 @@ int commit_tree(const char *msg, size_t msg_len, const struct object_id *tree,\n \tint result;\n \n \tappend_merge_tag_headers(parents, &tail);\n-\tresult = commit_tree_extended(msg, msg_len, tree, parents, ret, author,\n+\tresult = commit_tree_extended(r, msg, msg_len, tree, parents, ret, author,\n \t\t\t\t      NULL, sign_commit, extra);\n \tfree_commit_extra_headers(extra);\n \treturn result;\n@@ -1663,17 +1664,18 @@ N_(\"Warning: commit message did not conform to UTF-8.\\n\"\n    \"You may want to amend it after fixing the message, or set the config\\n\"\n    \"variable i18n.commitEncoding to the encoding your project uses.\\n\");\n \n-static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg_len,\n-\t\t\t      const struct object_id *tree,\n-\t\t\t      const struct object_id *parents, size_t parents_len,\n-\t\t\t      const char *author, const char *committer,\n-\t\t\t      const struct commit_extra_header *extra)\n+static void write_commit_tree(struct repository *r, \n+\t\t\tstruct strbuf *buffer, const char *msg, size_t msg_len,\n+\t\t\tconst struct object_id *tree,\n+\t\t\tconst struct object_id *parents, size_t parents_len,\n+\t\t\tconst char *author, const char *committer,\n+\t\t\tconst struct commit_extra_header *extra)\n {\n \tint encoding_is_utf8;\n \tsize_t i;\n \n \t/* Not having i18n.commitencoding is the same as having utf-8 */\n-\tencoding_is_utf8 = is_encoding_utf8(repo_get_commit_output_encoding(the_repository));\n+\tencoding_is_utf8 = is_encoding_utf8(repo_get_commit_output_encoding(r));\n \n \tstrbuf_grow(buffer, 8192); /* should avoid reallocs for the headers */\n \tstrbuf_addf(buffer, \"tree %s\\n\", oid_to_hex(tree));\n@@ -1694,7 +1696,7 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \t\tcommitter = git_committer_info(IDENT_STRICT);\n \tstrbuf_addf(buffer, \"committer %s\\n\", committer);\n \tif (!encoding_is_utf8)\n-\t\tstrbuf_addf(buffer, \"encoding %s\\n\", repo_get_commit_output_encoding(the_repository));\n+\t\tstrbuf_addf(buffer, \"encoding %s\\n\", repo_get_commit_output_encoding(r));\n \n \twhile (extra) {\n \t\tadd_extra_header(buffer, extra);\n@@ -1706,14 +1708,15 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \tstrbuf_add(buffer, msg, msg_len);\n }\n \n-int commit_tree_extended(const char *msg, size_t msg_len,\n+int commit_tree_extended(\n+\t\t\t struct repository *r,\n+\t\t\t const char *msg, size_t msg_len,\n \t\t\t const struct object_id *tree,\n \t\t\t const struct commit_list *parents, struct object_id *ret,\n \t\t\t const char *author, const char *committer,\n \t\t\t const char *sign_commit,\n \t\t\t const struct commit_extra_header *extra)\n {\n-\tstruct repository *r = the_repository;\n \tint result = 0;\n \tint encoding_is_utf8;\n \tstruct strbuf buffer = STRBUF_INIT, compat_buffer = STRBUF_INIT;\n@@ -1723,7 +1726,7 @@ int commit_tree_extended(const char *msg, size_t msg_len,\n \tsize_t i, nparents;\n \n \t/* Not having i18n.commitencoding is the same as having utf-8 */\n-\tencoding_is_utf8 = is_encoding_utf8(repo_get_commit_output_encoding(the_repository));\n+\tencoding_is_utf8 = is_encoding_utf8(repo_get_commit_output_encoding(r));\n \n \todb_assert_oid_type(the_repository->objects, tree, OBJ_TREE);\n \n@@ -1736,7 +1739,7 @@ int commit_tree_extended(const char *msg, size_t msg_len,\n \tfor (const struct commit_list *p = parents; p; p = p->next)\n \t\toidcpy(&parent_buf[i++], &p->item->object.oid);\n \n-\twrite_commit_tree(&buffer, msg, msg_len, tree, parent_buf, nparents, author, committer, extra);\n+\twrite_commit_tree(r, &buffer, msg, msg_len, tree, parent_buf, nparents, author, committer, extra);\n \tif (sign_commit && sign_commit_to_strbuf(&sig, &buffer, sign_commit)) {\n \t\tresult = -1;\n \t\tgoto out;\n@@ -1764,7 +1767,7 @@ int commit_tree_extended(const char *msg, size_t msg_len,\n \t\t\tfree(mapped_parents);\n \t\t\tgoto out;\n \t\t}\n-\t\twrite_commit_tree(&compat_buffer, msg, msg_len, &mapped_tree,\n+\t\twrite_commit_tree(r, &compat_buffer, msg, msg_len, &mapped_tree,\n \t\t\t\t  mapped_parents, nparents, author, committer, compat_extra);\n \t\tfree_commit_extra_headers(compat_extra);\n \t\tfree(mapped_parents);\ndiff --git a/commit.h b/commit.h\nindex 1635de418b..b8aa748fbb 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -289,12 +289,14 @@ struct commit_extra_header {\n void append_merge_tag_headers(const struct commit_list *parents,\n \t\t\t      struct commit_extra_header ***tail);\n \n-int commit_tree(const char *msg, size_t msg_len,\n+int commit_tree(struct repository *r, \n+\t\tconst char *msg, size_t msg_len,\n \t\tconst struct object_id *tree,\n \t\tconst struct commit_list *parents, struct object_id *ret,\n \t\tconst char *author, const char *sign_commit);\n \n-int commit_tree_extended(const char *msg, size_t msg_len,\n+int commit_tree_extended(struct repository *r,\n+\t\t\t const char *msg, size_t msg_len,\n \t\t\t const struct object_id *tree,\n \t\t\t const struct commit_list *parents, struct object_id *ret,\n \t\t\t const char *author, const char *committer,\ndiff --git a/diff.c b/diff.c\nindex 35b903a9a0..f0244c14f1 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -7513,7 +7513,7 @@ size_t fill_textconv(struct repository *r,\n \t\t * Since generating a cache entry is the slow path anyway,\n \t\t * this extra overhead probably isn't a big deal.\n \t\t */\n-\t\tnotes_cache_write(driver->textconv_cache);\n+\t\tnotes_cache_write(r, driver->textconv_cache);\n \t}\n \n \treturn size;\ndiff --git a/notes-cache.c b/notes-cache.c\nindex bf5bb1f6c1..f14e0308af 100644\n--- a/notes-cache.c\n+++ b/notes-cache.c\n@@ -54,7 +54,7 @@ void notes_cache_init(struct repository *r, struct notes_cache *c,\n \tstrbuf_release(&ref);\n }\n \n-int notes_cache_write(struct notes_cache *c)\n+int notes_cache_write(struct repository *r, struct notes_cache *c)\n {\n \tstruct object_id tree_oid, commit_oid;\n \n@@ -66,7 +66,7 @@ int notes_cache_write(struct notes_cache *c)\n \n \tif (write_notes_tree(&c->tree, &tree_oid))\n \t\treturn -1;\n-\tif (commit_tree(c->validity, strlen(c->validity), &tree_oid, NULL,\n+\tif (commit_tree(r, c->validity, strlen(c->validity), &tree_oid, NULL,\n \t\t\t&commit_oid, NULL, NULL) < 0)\n \t\treturn -1;\n \tif (refs_update_ref(get_main_ref_store(the_repository), \"update notes cache\", c->tree.update_ref, &commit_oid,\ndiff --git a/notes-cache.h b/notes-cache.h\nindex 56f8c98e24..f268425fd7 100644\n--- a/notes-cache.h\n+++ b/notes-cache.h\n@@ -12,7 +12,7 @@ struct notes_cache {\n \n void notes_cache_init(struct repository *r, struct notes_cache *c,\n \t\t      const char *name, const char *validity);\n-int notes_cache_write(struct notes_cache *c);\n+int notes_cache_write(struct repository *r, struct notes_cache *c);\n \n char *notes_cache_get(struct notes_cache *c, struct object_id *oid, size_t\n \t\t      *outsize);\ndiff --git a/notes-utils.c b/notes-utils.c\nindex 5c1c75d5b8..4671a11993 100644\n--- a/notes-utils.c\n+++ b/notes-utils.c\n@@ -36,7 +36,7 @@ void create_notes_commit(struct repository *r,\n \t\t/* else: t->ref points to nothing, assume root/orphan commit */\n \t}\n \n-\tif (commit_tree(msg, msg_len, &tree_oid, parents, result_oid, NULL,\n+\tif (commit_tree(r, msg, msg_len, &tree_oid, parents, result_oid, NULL,\n \t\t\tNULL))\n \t\tdie(\"Failed to commit notes tree to database\");\n \ndiff --git a/replay.c b/replay.c\nindex 45d539f8fc..69a69deab4 100644\n--- a/replay.c\n+++ b/replay.c\n@@ -68,7 +68,7 @@ static struct commit *create_commit(struct repository *repo,\n \tstrbuf_addstr(&msg, orig_message);\n \tauthor = get_author(message);\n \treset_ident_date();\n-\tif (commit_tree_extended(msg.buf, msg.len, &tree->object.oid, parents,\n+\tif (commit_tree_extended(repo, msg.buf, msg.len, &tree->object.oid, parents,\n \t\t\t\t &ret, author, NULL, sign_commit, extra)) {\n \t\terror(_(\"failed to write commit object\"));\n \t\tgoto out;\ndiff --git a/sequencer.c b/sequencer.c\nindex 612f47fd12..b9a4f75c5f 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -480,13 +480,13 @@ static const char *short_commit_name(struct repository *r, struct commit *commit\n \treturn repo_find_unique_abbrev(r, &commit->object.oid, DEFAULT_ABBREV);\n }\n \n-static int get_message(struct commit *commit, struct commit_message *out)\n+static int get_message(struct repository *r, struct commit *commit, struct commit_message *out)\n {\n \tconst char *abbrev, *subject;\n \tint subject_len;\n \n \tout->message = repo_logmsg_reencode(the_repository, commit, NULL,\n-\t\t\t\t\t    repo_get_commit_output_encoding(the_repository));\n+\t\t\t\t\t    repo_get_commit_output_encoding(r));\n \tabbrev = short_commit_name(the_repository, commit);\n \n \tsubject_len = find_commit_subject(out->message, &subject);\n@@ -1672,7 +1672,7 @@ static int try_to_commit(struct repository *r,\n \t\tfree(email);\n \t}\n \n-\tif (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,\n+\tif (commit_tree_extended(r, msg->buf, msg->len, &tree, parents, oid,\n \t\t\t\t author, committer, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n \t\tgoto out;\n@@ -2324,7 +2324,7 @@ static int do_pick_commit(struct repository *r,\n \telse\n \t\tparent = commit->parents->item;\n \n-\tif (get_message(commit, &msg) != 0)\n+\tif (get_message(r, commit, &msg) != 0)\n \t\treturn error(_(\"cannot get commit message for %s\"),\n \t\t\toid_to_hex(&commit->object.oid));\n \n@@ -3989,7 +3989,7 @@ static int do_reset(struct repository *r,\n \tif (len == 10 && !strncmp(\"[new root]\", name, len)) {\n \t\tif (!opts->have_squash_onto) {\n \t\t\tconst char *hex;\n-\t\t\tif (commit_tree(\"\", 0, the_hash_algo->empty_tree,\n+\t\t\tif (commit_tree(r, \"\", 0, the_hash_algo->empty_tree,\n \t\t\t\t\tNULL, &opts->squash_onto,\n \t\t\t\t\tNULL, NULL))\n \t\t\t\treturn error(_(\"writing fake root commit\"));\n@@ -4831,7 +4831,7 @@ static int stopped_at_head(struct repository *r)\n \n \tif (repo_get_oid(r, \"HEAD\", &head) ||\n \t    !(commit = lookup_commit(r, &head)) ||\n-\t    repo_parse_commit(r, commit) || get_message(commit, &message))\n+\t    repo_parse_commit(r, commit) || get_message(r, commit, &message))\n \t\tfprintf(stderr, _(\"Stopped at HEAD\\n\"));\n \telse {\n \t\tfprintf(stderr, _(\"Stopped at %s\\n\"), message.label);\n-- \n2.43.0\n\n"},{"id":"537405","messageId":"20260228190201.3684705-4-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260228190201.3684705-1-a3205153416@gmail.com","subject":"[PATCH v2 3/3] pretty: pass 'struct repository' to pretty_print_commit()","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-02-28T19:02:01Z","receivedAt":"2026-02-28T19:06:10Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"Following the migration of encoding settings into 'struct repo_settings',\nthe commit formatting and logging APIs now require a repository context.\n\nUpdate the signatures of 'pretty_print_commit()' and  'pp_commit_easy()' to\naccept 'struct repository *' as their first argument, allowing them to call\n'repo_get_log_output_encoding(r)' without relying on the global\n'the_repository'.\n\nFor callers residing in the 'builtin/' directory, and for areas\nthat do not yet possess a repository context (such as 'bundle.c'),\nfallback to using 'the_repository'.\n\nSigned-off-by: Tian Yuchen <a3205153416@gmail.com>\n---\n builtin/checkout.c    |  4 ++--\n builtin/log.c         |  2 +-\n builtin/merge.c       |  2 +-\n builtin/reset.c       |  2 +-\n builtin/rev-list.c    |  2 +-\n builtin/shortlog.c    |  2 +-\n builtin/show-branch.c |  2 +-\n builtin/stash.c       |  2 +-\n bundle.c              |  2 +-\n log-tree.c            |  6 +++---\n pretty.c              | 13 +++++++------\n pretty.h              |  4 ++--\n range-diff.c          | 10 +++++-----\n revision.c            |  4 ++--\n sequencer.c           | 12 ++++++------\n 15 files changed, 35 insertions(+), 34 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex f7b313816e..64c5c9ed1a 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -689,7 +689,7 @@ static void describe_detached_head(const char *msg, struct commit *commit)\n \tstruct strbuf sb = STRBUF_INIT;\n \n \tif (!repo_parse_commit(the_repository, commit))\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &sb);\n \tif (print_sha1_ellipsis()) {\n \t\tfprintf(stderr, \"%s %s... %s\\n\", msg,\n \t\t\trepo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV),\n@@ -1077,7 +1077,7 @@ static void describe_one_orphan(struct strbuf *sb, struct commit *commit)\n \tstrbuf_add_unique_abbrev(sb, &commit->object.oid, DEFAULT_ABBREV);\n \tstrbuf_addch(sb, ' ');\n \tif (!repo_parse_commit(the_repository, commit))\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, sb);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, sb);\n \tstrbuf_addch(sb, '\\n');\n }\n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 1c9ec09098..922a0788e9 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -2521,7 +2521,7 @@ static void print_commit(char sign, struct commit *commit, int verbose,\n \t\t       repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev));\n \t} else {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &buf);\n \t\tfprintf(file, \"%c %s %s\\n\", sign,\n \t\t       repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev),\n \t\t       buf.buf);\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 7c944fe179..dff8185776 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -470,7 +470,7 @@ static void squash_message(struct commit *commit, struct commit_list *remotehead\n \t\tstrbuf_addch(&out, '\\n');\n \t\tstrbuf_addf(&out, \"commit %s\\n\",\n \t\t\toid_to_hex(&commit->object.oid));\n-\t\tpretty_print_commit(&ctx, commit, &out);\n+\t\tpretty_print_commit(the_repository, &ctx, commit, &out);\n \t}\n \twrite_file_buf(git_path_squash_msg(the_repository), out.buf, out.len);\n \tstrbuf_release(&out);\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex c48d9845f8..733f3fa905 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -141,7 +141,7 @@ static void print_new_head_line(struct commit *commit)\n \tprintf(_(\"HEAD is now at %s\"),\n \t\trepo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV));\n \n-\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);\n+\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &buf);\n \tif (buf.len > 0)\n \t\tprintf(\" %s\", buf.buf);\n \tputchar('\\n');\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex 3c6a2914d8..1ebe0e6038 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -307,7 +307,7 @@ static void show_commit(struct commit *commit, void *data)\n \t\tctx.output_encoding = repo_get_log_output_encoding(the_repository);\n \t\tctx.color = revs->diffopt.use_color;\n \t\tctx.rev = revs;\n-\t\tpretty_print_commit(&ctx, commit, &buf);\n+\t\tpretty_print_commit(the_repository, &ctx, commit, &buf);\n \t\tif (buf.len) {\n \t\t\tif (revs->commit_format != CMIT_FMT_ONELINE)\n \t\t\t\tgraph_show_oneline(revs->graph);\ndiff --git a/builtin/shortlog.c b/builtin/shortlog.c\nindex ce9f20de2f..0e47c4dc40 100644\n--- a/builtin/shortlog.c\n+++ b/builtin/shortlog.c\n@@ -252,7 +252,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)\n \n \tif (!log->summary) {\n \t\tif (log->user_format)\n-\t\t\tpretty_print_commit(&ctx, commit, &oneline);\n+\t\t\tpretty_print_commit(the_repository, &ctx, commit, &oneline);\n \t\telse\n \t\t\trepo_format_commit_message(the_repository, commit,\n \t\t\t\t\t\t   \"%s\", &oneline, &ctx);\ndiff --git a/builtin/show-branch.c b/builtin/show-branch.c\nindex f02831b085..6bfe9e2e96 100644\n--- a/builtin/show-branch.c\n+++ b/builtin/show-branch.c\n@@ -310,7 +310,7 @@ static void show_one_commit(struct commit *commit, int no_name)\n \tstruct commit_name *name = commit_to_name(commit);\n \n \tif (commit->object.parsed) {\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &pretty);\n \t\tpretty_str = pretty.buf;\n \t}\n \tskip_prefix(pretty_str, \"[PATCH] \", &pretty_str);\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex 3d94726251..caaff35cb7 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -1480,7 +1480,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \t\t\t\t\t\t  &head_commit->object.oid,\n \t\t\t\t\t\t  DEFAULT_ABBREV);\n \tstrbuf_addf(&msg, \"%s: %s \", branch_name, head_short_sha1);\n-\tpp_commit_easy(CMIT_FMT_ONELINE, head_commit, &msg);\n+\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, head_commit, &msg);\n \n \tstrbuf_addf(&commit_tree_label, \"index on %s\\n\", msg.buf);\n \tcommit_list_insert(head_commit, &parents);\ndiff --git a/bundle.c b/bundle.c\nindex 7914a57b43..4876d0a852 100644\n--- a/bundle.c\n+++ b/bundle.c\n@@ -463,7 +463,7 @@ static void write_bundle_prerequisites(struct commit *commit, void *data)\n \tctx.fmt = CMIT_FMT_ONELINE;\n \tctx.output_encoding = repo_get_log_output_encoding(the_repository);\n \tstrbuf_reset(&buf);\n-\tpretty_print_commit(&ctx, commit, &buf);\n+\tpretty_print_commit(the_repository, &ctx, commit, &buf);\n \tstrbuf_trim(&buf);\n \n \tobject = (struct object *)commit;\ndiff --git a/log-tree.c b/log-tree.c\nindex aea3cbf7c6..2039c31297 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -859,7 +859,7 @@ void show_log(struct rev_info *opt)\n \n \t\traw = (opt->commit_format == CMIT_FMT_USERFORMAT);\n \t\tformat_display_notes(&commit->object.oid, &notebuf,\n-\t\t\t\t     repo_get_log_output_encoding(the_repository), raw);\n+\t\t\t\t     repo_get_log_output_encoding(opt->repo), raw);\n \t\tctx.notes_message = strbuf_detach(&notebuf, NULL);\n \t}\n \n@@ -879,13 +879,13 @@ void show_log(struct rev_info *opt)\n \tctx.mailmap = opt->mailmap;\n \tctx.color = opt->diffopt.use_color;\n \tctx.expand_tabs_in_log = opt->expand_tabs_in_log;\n-\tctx.output_encoding = repo_get_log_output_encoding(the_repository);\n+\tctx.output_encoding = repo_get_log_output_encoding(opt->repo);\n \tctx.rev = opt;\n \tif (opt->from_ident.mail_begin && opt->from_ident.name_begin)\n \t\tctx.from_ident = &opt->from_ident;\n \tif (opt->graph)\n \t\tctx.graph_width = graph_width(opt->graph);\n-\tpretty_print_commit(&ctx, commit, &msgbuf);\n+\tpretty_print_commit(opt->repo, &ctx, commit, &msgbuf);\n \n \tif (opt->add_signoff)\n \t\tappend_signoff(&msgbuf, 0, APPEND_SIGNOFF_DEDUP);\ndiff --git a/pretty.c b/pretty.c\nindex e939d0ff3b..8bcd57905d 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -2281,7 +2281,8 @@ void pp_remainder(struct pretty_print_context *pp,\n \t}\n }\n \n-void pretty_print_commit(struct pretty_print_context *pp,\n+void pretty_print_commit(struct repository *r,\n+\t\t\t struct pretty_print_context *pp,\n \t\t\t const struct commit *commit,\n \t\t\t struct strbuf *sb)\n {\n@@ -2293,13 +2294,13 @@ void pretty_print_commit(struct pretty_print_context *pp,\n \tint need_8bit_cte = pp->need_8bit_cte;\n \n \tif (pp->fmt == CMIT_FMT_USERFORMAT) {\n-\t\trepo_format_commit_message(the_repository, commit,\n+\t\trepo_format_commit_message(r, commit,\n \t\t\t\t\t   user_format, sb, pp);\n \t\treturn;\n \t}\n \n-\tencoding = repo_get_log_output_encoding(the_repository);\n-\tmsg = reencoded = repo_logmsg_reencode(the_repository, commit, NULL,\n+\tencoding = repo_get_log_output_encoding(r);\n+\tmsg = reencoded = repo_logmsg_reencode(r, commit, NULL,\n \t\t\t\t\t       encoding);\n \n \tif (pp->fmt == CMIT_FMT_ONELINE || cmit_fmt_is_mail(pp->fmt))\n@@ -2363,10 +2364,10 @@ void pretty_print_commit(struct pretty_print_context *pp,\n \trepo_unuse_commit_buffer(the_repository, commit, reencoded);\n }\n \n-void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,\n+void pp_commit_easy(struct repository *r, enum cmit_fmt fmt, const struct commit *commit,\n \t\t    struct strbuf *sb)\n {\n \tstruct pretty_print_context pp = {0};\n \tpp.fmt = fmt;\n-\tpretty_print_commit(&pp, commit, sb);\n+\tpretty_print_commit(r, &pp, commit, sb);\n }\ndiff --git a/pretty.h b/pretty.h\nindex fac699033e..13eb0189bd 100644\n--- a/pretty.h\n+++ b/pretty.h\n@@ -82,7 +82,7 @@ void userformat_find_requirements(const char *fmt, struct userformat_want *w);\n  * Shortcut for invoking pretty_print_commit if we do not have any context.\n  * Context would be set empty except \"fmt\".\n  */\n-void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,\n+void pp_commit_easy(struct repository *r, enum cmit_fmt fmt, const struct commit *commit,\n \t\t\tstruct strbuf *sb);\n \n /*\n@@ -132,7 +132,7 @@ void get_commit_format(const char *arg, struct rev_info *);\n  * and put it into \"sb\".\n  * Please use this function if you have a context (candidate for \"pp\").\n  */\n-void pretty_print_commit(struct pretty_print_context *pp,\n+void pretty_print_commit(struct repository *r, struct pretty_print_context *pp,\n \t\t\tconst struct commit *commit,\n \t\t\tstruct strbuf *sb);\n \ndiff --git a/range-diff.c b/range-diff.c\nindex 57edff40a8..368d033ceb 100644\n--- a/range-diff.c\n+++ b/range-diff.c\n@@ -418,7 +418,7 @@ static void output_pair_header(struct diff_options *diffopt,\n \n \tif (!dashes->len)\n \t\tstrbuf_addchars(dashes, '-',\n-\t\t\t\tstrlen(repo_find_unique_abbrev(the_repository, oid, abbrev)));\n+\t\t\t\tstrlen(repo_find_unique_abbrev(diffopt->repo, oid, abbrev)));\n \n \tif (!b_util) {\n \t\tcolor = color_old;\n@@ -440,7 +440,7 @@ static void output_pair_header(struct diff_options *diffopt,\n \t\tstrbuf_addf(buf, \"%*s:  %s \", patch_no_width, \"-\", dashes->buf);\n \telse\n \t\tstrbuf_addf(buf, \"%*d:  %s \", patch_no_width, a_util->i + 1,\n-\t\t\t    repo_find_unique_abbrev(the_repository, &a_util->oid, abbrev));\n+\t\t\t    repo_find_unique_abbrev(diffopt->repo, &a_util->oid, abbrev));\n \n \tif (status == '!')\n \t\tstrbuf_addf(buf, \"%s%s\", color_reset, color);\n@@ -452,15 +452,15 @@ static void output_pair_header(struct diff_options *diffopt,\n \t\tstrbuf_addf(buf, \" %*s:  %s\", patch_no_width, \"-\", dashes->buf);\n \telse\n \t\tstrbuf_addf(buf, \" %*d:  %s\", patch_no_width, b_util->i + 1,\n-\t\t\t    repo_find_unique_abbrev(the_repository, &b_util->oid, abbrev));\n+\t\t\t    repo_find_unique_abbrev(diffopt->repo, &b_util->oid, abbrev));\n \n-\tcommit = lookup_commit_reference(the_repository, oid);\n+\tcommit = lookup_commit_reference(diffopt->repo, oid);\n \tif (commit) {\n \t\tif (status == '!')\n \t\t\tstrbuf_addf(buf, \"%s%s\", color_reset, color);\n \n \t\tstrbuf_addch(buf, ' ');\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, buf);\n+\t\tpp_commit_easy(diffopt->repo, CMIT_FMT_ONELINE, commit, buf);\n \t}\n \tstrbuf_addf(buf, \"%s\\n\", color_reset);\n \ndiff --git a/revision.c b/revision.c\nindex 961ecd1d6c..5c3c5a102d 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -3130,7 +3130,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \n \tdiff_setup_done(&revs->diffopt);\n \n-\tif (!is_encoding_utf8(repo_get_log_output_encoding(the_repository)))\n+\tif (!is_encoding_utf8(repo_get_log_output_encoding(revs->repo)))\n \t\trevs->grep_filter.ignore_locale = 1;\n \tcompile_grep_patterns(&revs->grep_filter);\n \n@@ -4064,7 +4064,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)\n \t * so we will not end up with a buffer that has two different encodings\n \t * in it.\n \t */\n-\tencoding = repo_get_log_output_encoding(the_repository);\n+\tencoding = repo_get_log_output_encoding(opt->repo);\n \tmessage = repo_logmsg_reencode(the_repository, commit, NULL, encoding);\n \n \t/* Copy the commit to temporary if we are using \"fake\" headers */\ndiff --git a/sequencer.c b/sequencer.c\nindex b9a4f75c5f..09e6dcca43 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -3332,7 +3332,7 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,\n \treturn 0;\n }\n \n-static int walk_revs_populate_todo(struct todo_list *todo_list,\n+static int walk_revs_populate_todo(struct repository *r, struct todo_list *todo_list,\n \t\t\t\tstruct replay_opts *opts)\n {\n \tenum todo_command command = opts->action == REPLAY_PICK ?\n@@ -3344,7 +3344,7 @@ static int walk_revs_populate_todo(struct todo_list *todo_list,\n \tif (prepare_revs(opts))\n \t\treturn -1;\n \n-\tencoding = repo_get_log_output_encoding(the_repository);\n+\tencoding = repo_get_log_output_encoding(r);\n \n \twhile ((commit = get_revision(opts->revs))) {\n \t\tstruct todo_item *item = append_new_todo(todo_list);\n@@ -5543,7 +5543,7 @@ int sequencer_pick_revisions(struct repository *r,\n \t * progress\n \t */\n \n-\tif (walk_revs_populate_todo(&todo_list, opts) ||\n+\tif (walk_revs_populate_todo(r, &todo_list, opts) ||\n \t\t\tcreate_seq_dir(r) < 0) {\n \t\tres = -1;\n \t\tgoto out;\n@@ -5870,7 +5870,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,\n \t\t\tcontinue;\n \n \t\tstrbuf_reset(&oneline);\n-\t\tpretty_print_commit(pp, commit, &oneline);\n+\t\tpretty_print_commit(revs->repo, pp, commit, &oneline);\n \n \t\tto_merge = commit->parents ? commit->parents->next : NULL;\n \t\tif (!to_merge) {\n@@ -6012,7 +6012,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,\n \t\t\t\tstrbuf_addf(out, \"%s onto\\n\", cmd_reset);\n \t\t\telse {\n \t\t\t\tstrbuf_reset(&oneline);\n-\t\t\t\tpretty_print_commit(pp, commit, &oneline);\n+\t\t\t\tpretty_print_commit(revs->repo, pp, commit, &oneline);\n \t\t\t\tstrbuf_addf(out, \"%s %s %s\\n\",\n \t\t\t\t\t    cmd_reset, to, oneline.buf);\n \t\t\t}\n@@ -6124,7 +6124,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out,\n \t\t\tcontinue;\n \t\tstrbuf_addf(out, \"%s %s \", insn,\n \t\t\t    oid_to_hex(&commit->object.oid));\n-\t\tpretty_print_commit(&pp, commit, out);\n+\t\tpretty_print_commit(r, &pp, commit, out);\n \t\tif (is_empty)\n \t\t\tstrbuf_addf(out, \" %s empty\", comment_line_str);\n \t\tstrbuf_addch(out, '\\n');\n-- \n2.43.0\n\n"},{"id":"537478","messageId":"20260301203539.1421152-1-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260228040727.2057192-1-a3205153416@gmail.com","subject":"[PATCH v3 0/3] environment: move encoding configs to struct repository","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-01T20:35:36Z","receivedAt":"2026-03-01T20:35:59Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"This is v3 of the series aimed at reducing the global state associated with \n'git_commit_encoding' and 'git_log_output_encoding'.\n\nChanges since v2:\nBased on the invaluable feedback from Phillip Wood, the architectural \napproach has been fundamentally adjusted. In v2, I attempted to migrate \nthese variables into 'struct repo_settings'. However, since these are \neagerly parsed user preferences, deferring them to lazy evaluation broke \nearly validation.\n\nIn this v3 series, the variables are migrated directly into 'struct repository'. \n\nAccording to the thread Phillip Wood shared, plumbing the repository pointer\nsafely through the 'git_default_config' callback machinery is highly\ninvasive. Many top-level callers pass custom structs via the 'void *cb' pointer\nso that blindly casting 'cb' to 'struct repository *' results in weird bugs (at\nleast I can't fix them all in one single patch)\n\nTherefore:\n1. The variables are parsed directly into 'the_repository' during config \n   parsing to maintain eager validation.\n2. However, the entire read/write paths (commit creation and log APIs) are \n   fully plumbed to accept any 'struct repository' instance. \n\nFuture efforts to libify the config machinery itself will only need to update\nthe parser, as the core APIs are now context-aware.\n\nTian Yuchen (3):\n  commit: plumb 'struct repository' into commit creation APIs\n  pretty: plumb 'struct repository' into pretty-print APIs\n  environment: migrate encoding configs to struct repository\n\n builtin/am.c          |  6 +++---\n builtin/blame.c       |  2 +-\n builtin/checkout.c    |  4 ++--\n builtin/commit-tree.c |  2 +-\n builtin/commit.c      |  8 ++++----\n builtin/history.c     |  2 +-\n builtin/log.c         |  4 ++--\n builtin/mailinfo.c    |  6 +++---\n builtin/merge.c       |  6 +++---\n builtin/rebase.c      |  2 +-\n builtin/reset.c       |  2 +-\n builtin/rev-list.c    |  4 ++--\n builtin/shortlog.c    |  4 ++--\n builtin/show-branch.c |  2 +-\n builtin/stash.c       | 12 ++++++------\n bundle.c              |  4 ++--\n commit.c              | 20 ++++++++++----------\n commit.h              |  4 ++--\n environment.c         | 19 ++++++++-----------\n environment.h         |  7 ++-----\n log-tree.c            |  6 +++---\n notes-cache.c         |  2 +-\n notes-utils.c         |  2 +-\n pretty.c              |  8 ++++----\n pretty.h              |  4 ++--\n range-diff.c          |  2 +-\n remote-curl.c         |  2 +-\n replay.c              |  4 ++--\n repository.c          |  2 ++\n repository.h          |  5 +++++\n revision.c            | 10 +++++-----\n sequencer.c           | 32 ++++++++++++++++----------------\n submodule.c           |  2 +-\n 33 files changed, 101 insertions(+), 100 deletions(-)\n\n-- \n2.43.0\n\n"},{"id":"537479","messageId":"20260301203539.1421152-2-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260301203539.1421152-1-a3205153416@gmail.com","subject":"[PATCH v3 1/3] commit: plumb 'struct repository' into commit creation APIs","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-01T20:35:37Z","receivedAt":"2026-03-01T20:36:03Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"To pave the way for reducing the global state tied to commit encoding\nin a subsequent patch, functions like 'commit_tree()' and\n'commit_tree_extended()' must be able to access a repository instance.\n\nPlumb the 'struct repository' pointer down the call chain for these\nAPIs. For built-ins or subsystems already dependent on global state\n(e.g., 'notes_cache_write()'), fallback to 'the_repository'.\n\nNo functional changes are introduced in this preparatory step.\n\nSigned-off-by: Tian Yuchen <a3205153416@gmail.com>\n---\n builtin/am.c          |  2 +-\n builtin/commit-tree.c |  2 +-\n builtin/commit.c      |  2 +-\n builtin/history.c     |  2 +-\n builtin/merge.c       |  4 ++--\n builtin/rebase.c      |  2 +-\n builtin/stash.c       | 10 +++++-----\n commit.c              |  7 +++----\n commit.h              |  4 ++--\n notes-cache.c         |  2 +-\n notes-utils.c         |  2 +-\n replay.c              |  2 +-\n sequencer.c           |  4 ++--\n 13 files changed, 22 insertions(+), 23 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex e0c767e223..5296124f84 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1699,7 +1699,7 @@ static void do_commit(const struct am_state *state)\n \t\t\t\t\t\t\t : state->author_date,\n \t\t\t\t      IDENT_STRICT);\n \n-\tif (commit_tree_extended(state->msg, state->msg_len, &tree, parents,\n+\tif (commit_tree_extended(the_repository, state->msg, state->msg_len, &tree, parents,\n \t\t\t\t &commit, author, committer, state->sign_commit,\n \t\t\t\t NULL))\n \t\tdie(_(\"failed to write commit object\"));\ndiff --git a/builtin/commit-tree.c b/builtin/commit-tree.c\nindex 30535db131..c489749588 100644\n--- a/builtin/commit-tree.c\n+++ b/builtin/commit-tree.c\n@@ -144,7 +144,7 @@ int cmd_commit_tree(int argc,\n \t\t\tdie_errno(_(\"git commit-tree: failed to read\"));\n \t}\n \n-\tif (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,\n+\tif (commit_tree(the_repository, buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,\n \t\t\tNULL, sign_commit)) {\n \t\tret = 1;\n \t\tgoto out;\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 9e3a09d532..d619fd2ace 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -1931,7 +1931,7 @@ int cmd_commit(int argc,\n \t\tappend_merge_tag_headers(parents, &tail);\n \t}\n \n-\tif (commit_tree_extended(sb.buf, sb.len, &the_repository->index->cache_tree->oid,\n+\tif (commit_tree_extended(the_repository, sb.buf, sb.len, &the_repository->index->cache_tree->oid,\n \t\t\t\t parents, &oid, author_ident.buf, NULL,\n \t\t\t\t sign_commit, extra)) {\n \t\trollback_index_files();\ndiff --git a/builtin/history.c b/builtin/history.c\nindex 8dcb9a6046..3d83ac021b 100644\n--- a/builtin/history.c\n+++ b/builtin/history.c\n@@ -136,7 +136,7 @@ static int commit_tree_with_edited_message(struct repository *repo,\n \n \toriginal_extra_headers = read_commit_extra_headers(original, exclude_gpgsig);\n \n-\tret = commit_tree_extended(commit_message.buf, commit_message.len, &original_tree_oid,\n+\tret = commit_tree_extended(repo, commit_message.buf, commit_message.len, &original_tree_oid,\n \t\t\t\t   original->parents, &rewritten_commit_oid, original_author,\n \t\t\t\t   NULL, NULL, original_extra_headers);\n \tif (ret < 0)\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 4e456a381c..7c944fe179 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -1000,7 +1000,7 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)\n \tpptr = commit_list_append(head, pptr);\n \tpptr = commit_list_append(remoteheads->item, pptr);\n \tprepare_to_commit(remoteheads);\n-\tif (commit_tree(merge_msg.buf, merge_msg.len, &result_tree, parents,\n+\tif (commit_tree(the_repository, merge_msg.buf, merge_msg.len, &result_tree, parents,\n \t\t\t&result_commit, NULL, sign_commit))\n \t\tdie(_(\"failed to write commit object\"));\n \tfinish(head, remoteheads, &result_commit, \"In-index merge\");\n@@ -1027,7 +1027,7 @@ static int finish_automerge(struct commit *head,\n \tif (!head_subsumed || fast_forward == FF_NO)\n \t\tcommit_list_insert(head, &parents);\n \tprepare_to_commit(remoteheads);\n-\tif (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents,\n+\tif (commit_tree(the_repository, merge_msg.buf, merge_msg.len, result_tree, parents,\n \t\t\t&result_commit, NULL, sign_commit))\n \t\tdie(_(\"failed to write commit object\"));\n \tstrbuf_addf(&buf, \"Merge made by the '%s' strategy.\", wt_strategy);\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex c487e10907..7b9ab85cc0 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1647,7 +1647,7 @@ int cmd_rebase(int argc,\n \t\toptions.upstream_arg = options.upstream_name;\n \t} else {\n \t\tif (!options.onto_name) {\n-\t\t\tif (commit_tree(\"\", 0, the_hash_algo->empty_tree, NULL,\n+\t\t\tif (commit_tree(the_repository, \"\", 0, the_hash_algo->empty_tree, NULL,\n \t\t\t\t\t&squash_onto, NULL, NULL) < 0)\n \t\t\t\tdie(_(\"Could not create new root commit\"));\n \t\t\toptions.squash_onto = &squash_onto;\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex f06cfa7989..785c1f9e5d 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -1258,7 +1258,7 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg,\n \t\tgoto done;\n \t}\n \n-\tif (commit_tree(untracked_msg.buf, untracked_msg.len,\n+\tif (commit_tree(the_repository, untracked_msg.buf, untracked_msg.len,\n \t\t\t&info->u_tree, NULL, &info->u_commit, NULL, NULL)) {\n \t\tret = -1;\n \t\tgoto done;\n@@ -1486,7 +1486,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \tcommit_list_insert(head_commit, &parents);\n \tif (write_index_as_tree(&info->i_tree, the_repository->index,\n \t\t\t\trepo_get_index_file(the_repository), 0, NULL) ||\n-\t    commit_tree(commit_tree_label.buf, commit_tree_label.len,\n+\t    commit_tree(the_repository, commit_tree_label.buf, commit_tree_label.len,\n \t\t\t&info->i_tree, parents, &info->i_commit, NULL, NULL)) {\n \t\tif (!quiet)\n \t\t\tfprintf_ln(stderr, _(\"Cannot save the current \"\n@@ -1551,7 +1551,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \t\t\t   &parents);\n \tcommit_list_insert(head_commit, &parents);\n \n-\tif (commit_tree(stash_msg_buf->buf, stash_msg_buf->len, &info->w_tree,\n+\tif (commit_tree(the_repository, stash_msg_buf->buf, stash_msg_buf->len, &info->w_tree,\n \t\t\tparents, &info->w_commit, NULL, NULL)) {\n \t\tif (!quiet)\n \t\t\tfprintf_ln(stderr, _(\"Cannot record \"\n@@ -2035,7 +2035,7 @@ static int write_commit_with_parents(struct repository *r,\n \tauthor = xmemdupz(orig_author, author_len);\n \tcommitter = xmemdupz(orig_committer, committer_len);\n \n-\tif (commit_tree_extended(msg.buf, msg.len,\n+\tif (commit_tree_extended(r, msg.buf, msg.len,\n \t\t\t\t r->hash_algo->empty_tree, parents,\n \t\t\t\t out, author, committer,\n \t\t\t\t NULL, NULL)) {\n@@ -2258,7 +2258,7 @@ static int do_export_stash(struct repository *r,\n \t\t\t      \"2001-09-17T00:00:00Z\", 0);\n \n \t/* First, we create a single empty commit. */\n-\tif (commit_tree_extended(\"\", 0, r->hash_algo->empty_tree, NULL,\n+\tif (commit_tree_extended(the_repository, \"\", 0, r->hash_algo->empty_tree, NULL,\n \t\t\t\t &base, author, committer, NULL, NULL))\n \t\treturn error(_(\"unable to write base commit\"));\n \ndiff --git a/commit.c b/commit.c\nindex d16ae73345..71a2b7bbe5 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1534,7 +1534,7 @@ void free_commit_extra_headers(struct commit_extra_header *extra)\n \t}\n }\n \n-int commit_tree(const char *msg, size_t msg_len, const struct object_id *tree,\n+int commit_tree(struct repository *r, const char *msg, size_t msg_len, const struct object_id *tree,\n \t\tconst struct commit_list *parents, struct object_id *ret,\n \t\tconst char *author, const char *sign_commit)\n {\n@@ -1542,7 +1542,7 @@ int commit_tree(const char *msg, size_t msg_len, const struct object_id *tree,\n \tint result;\n \n \tappend_merge_tag_headers(parents, &tail);\n-\tresult = commit_tree_extended(msg, msg_len, tree, parents, ret, author,\n+\tresult = commit_tree_extended(r, msg, msg_len, tree, parents, ret, author,\n \t\t\t\t      NULL, sign_commit, extra);\n \tfree_commit_extra_headers(extra);\n \treturn result;\n@@ -1706,14 +1706,13 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \tstrbuf_add(buffer, msg, msg_len);\n }\n \n-int commit_tree_extended(const char *msg, size_t msg_len,\n+int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len,\n \t\t\t const struct object_id *tree,\n \t\t\t const struct commit_list *parents, struct object_id *ret,\n \t\t\t const char *author, const char *committer,\n \t\t\t const char *sign_commit,\n \t\t\t const struct commit_extra_header *extra)\n {\n-\tstruct repository *r = the_repository;\n \tint result = 0;\n \tint encoding_is_utf8;\n \tstruct strbuf buffer = STRBUF_INIT, compat_buffer = STRBUF_INIT;\ndiff --git a/commit.h b/commit.h\nindex 1635de418b..d3d664d0ff 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -289,12 +289,12 @@ struct commit_extra_header {\n void append_merge_tag_headers(const struct commit_list *parents,\n \t\t\t      struct commit_extra_header ***tail);\n \n-int commit_tree(const char *msg, size_t msg_len,\n+int commit_tree(struct repository *r, const char *msg, size_t msg_len,\n \t\tconst struct object_id *tree,\n \t\tconst struct commit_list *parents, struct object_id *ret,\n \t\tconst char *author, const char *sign_commit);\n \n-int commit_tree_extended(const char *msg, size_t msg_len,\n+int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len,\n \t\t\t const struct object_id *tree,\n \t\t\t const struct commit_list *parents, struct object_id *ret,\n \t\t\t const char *author, const char *committer,\ndiff --git a/notes-cache.c b/notes-cache.c\nindex bf5bb1f6c1..5dbbd94ea3 100644\n--- a/notes-cache.c\n+++ b/notes-cache.c\n@@ -66,7 +66,7 @@ int notes_cache_write(struct notes_cache *c)\n \n \tif (write_notes_tree(&c->tree, &tree_oid))\n \t\treturn -1;\n-\tif (commit_tree(c->validity, strlen(c->validity), &tree_oid, NULL,\n+\tif (commit_tree(the_repository, c->validity, strlen(c->validity), &tree_oid, NULL,\n \t\t\t&commit_oid, NULL, NULL) < 0)\n \t\treturn -1;\n \tif (refs_update_ref(get_main_ref_store(the_repository), \"update notes cache\", c->tree.update_ref, &commit_oid,\ndiff --git a/notes-utils.c b/notes-utils.c\nindex 5c1c75d5b8..4671a11993 100644\n--- a/notes-utils.c\n+++ b/notes-utils.c\n@@ -36,7 +36,7 @@ void create_notes_commit(struct repository *r,\n \t\t/* else: t->ref points to nothing, assume root/orphan commit */\n \t}\n \n-\tif (commit_tree(msg, msg_len, &tree_oid, parents, result_oid, NULL,\n+\tif (commit_tree(r, msg, msg_len, &tree_oid, parents, result_oid, NULL,\n \t\t\tNULL))\n \t\tdie(\"Failed to commit notes tree to database\");\n \ndiff --git a/replay.c b/replay.c\nindex f97d652f33..8704547aa1 100644\n--- a/replay.c\n+++ b/replay.c\n@@ -68,7 +68,7 @@ static struct commit *create_commit(struct repository *repo,\n \tstrbuf_addstr(&msg, orig_message);\n \tauthor = get_author(message);\n \treset_ident_date();\n-\tif (commit_tree_extended(msg.buf, msg.len, &tree->object.oid, parents,\n+\tif (commit_tree_extended(repo, msg.buf, msg.len, &tree->object.oid, parents,\n \t\t\t\t &ret, author, NULL, sign_commit, extra)) {\n \t\terror(_(\"failed to write commit object\"));\n \t\tgoto out;\ndiff --git a/sequencer.c b/sequencer.c\nindex a3eb39bb25..627020d65b 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1672,7 +1672,7 @@ static int try_to_commit(struct repository *r,\n \t\tfree(email);\n \t}\n \n-\tif (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,\n+\tif (commit_tree_extended(r, msg->buf, msg->len, &tree, parents, oid,\n \t\t\t\t author, committer, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n \t\tgoto out;\n@@ -3989,7 +3989,7 @@ static int do_reset(struct repository *r,\n \tif (len == 10 && !strncmp(\"[new root]\", name, len)) {\n \t\tif (!opts->have_squash_onto) {\n \t\t\tconst char *hex;\n-\t\t\tif (commit_tree(\"\", 0, the_hash_algo->empty_tree,\n+\t\t\tif (commit_tree(r, \"\", 0, the_hash_algo->empty_tree,\n \t\t\t\t\tNULL, &opts->squash_onto,\n \t\t\t\t\tNULL, NULL))\n \t\t\t\treturn error(_(\"writing fake root commit\"));\n-- \n2.43.0\n\n"},{"id":"537480","messageId":"20260301203539.1421152-3-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260301203539.1421152-1-a3205153416@gmail.com","subject":"[PATCH v3 2/3] pretty: plumb 'struct repository' into pretty-print APIs","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-01T20:35:38Z","receivedAt":"2026-03-01T20:36:09Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"To prepare for the elimination of the global state associated with\n'log_output_encoding', functions responsible for formatting commit\nmessages, such as 'pretty_print_commit()' and 'pp_commit_easy()',\nmust be able to access a repository instance.\n\nPlumb the 'struct repository' pointer down the call chain for these\nAPIs. Where no such context is readily available in built-ins or\nhigh-level functions, fallback to 'the_repository'.\n\nSigned-off-by: Tian Yuchen <a3205153416@gmail.com>\n---\n builtin/checkout.c    | 4 ++--\n builtin/log.c         | 2 +-\n builtin/merge.c       | 2 +-\n builtin/reset.c       | 2 +-\n builtin/rev-list.c    | 2 +-\n builtin/shortlog.c    | 2 +-\n builtin/show-branch.c | 2 +-\n builtin/stash.c       | 2 +-\n bundle.c              | 2 +-\n log-tree.c            | 2 +-\n pretty.c              | 6 +++---\n pretty.h              | 4 ++--\n range-diff.c          | 2 +-\n sequencer.c           | 6 +++---\n 14 files changed, 20 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex f7b313816e..64c5c9ed1a 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -689,7 +689,7 @@ static void describe_detached_head(const char *msg, struct commit *commit)\n \tstruct strbuf sb = STRBUF_INIT;\n \n \tif (!repo_parse_commit(the_repository, commit))\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &sb);\n \tif (print_sha1_ellipsis()) {\n \t\tfprintf(stderr, \"%s %s... %s\\n\", msg,\n \t\t\trepo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV),\n@@ -1077,7 +1077,7 @@ static void describe_one_orphan(struct strbuf *sb, struct commit *commit)\n \tstrbuf_add_unique_abbrev(sb, &commit->object.oid, DEFAULT_ABBREV);\n \tstrbuf_addch(sb, ' ');\n \tif (!repo_parse_commit(the_repository, commit))\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, sb);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, sb);\n \tstrbuf_addch(sb, '\\n');\n }\n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 8ab6d3a943..0758aed580 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -2521,7 +2521,7 @@ static void print_commit(char sign, struct commit *commit, int verbose,\n \t\t       repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev));\n \t} else {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &buf);\n \t\tfprintf(file, \"%c %s %s\\n\", sign,\n \t\t       repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev),\n \t\t       buf.buf);\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 7c944fe179..dff8185776 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -470,7 +470,7 @@ static void squash_message(struct commit *commit, struct commit_list *remotehead\n \t\tstrbuf_addch(&out, '\\n');\n \t\tstrbuf_addf(&out, \"commit %s\\n\",\n \t\t\toid_to_hex(&commit->object.oid));\n-\t\tpretty_print_commit(&ctx, commit, &out);\n+\t\tpretty_print_commit(the_repository, &ctx, commit, &out);\n \t}\n \twrite_file_buf(git_path_squash_msg(the_repository), out.buf, out.len);\n \tstrbuf_release(&out);\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex c48d9845f8..733f3fa905 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -141,7 +141,7 @@ static void print_new_head_line(struct commit *commit)\n \tprintf(_(\"HEAD is now at %s\"),\n \t\trepo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV));\n \n-\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);\n+\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &buf);\n \tif (buf.len > 0)\n \t\tprintf(\" %s\", buf.buf);\n \tputchar('\\n');\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex ddea8aa251..57c7b8d3ff 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -307,7 +307,7 @@ static void show_commit(struct commit *commit, void *data)\n \t\tctx.output_encoding = get_log_output_encoding();\n \t\tctx.color = revs->diffopt.use_color;\n \t\tctx.rev = revs;\n-\t\tpretty_print_commit(&ctx, commit, &buf);\n+\t\tpretty_print_commit(the_repository, &ctx, commit, &buf);\n \t\tif (buf.len) {\n \t\t\tif (revs->commit_format != CMIT_FMT_ONELINE)\n \t\t\t\tgraph_show_oneline(revs->graph);\ndiff --git a/builtin/shortlog.c b/builtin/shortlog.c\nindex d80bf1a7d0..109785fd00 100644\n--- a/builtin/shortlog.c\n+++ b/builtin/shortlog.c\n@@ -252,7 +252,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)\n \n \tif (!log->summary) {\n \t\tif (log->user_format)\n-\t\t\tpretty_print_commit(&ctx, commit, &oneline);\n+\t\t\tpretty_print_commit(the_repository, &ctx, commit, &oneline);\n \t\telse\n \t\t\trepo_format_commit_message(the_repository, commit,\n \t\t\t\t\t\t   \"%s\", &oneline, &ctx);\ndiff --git a/builtin/show-branch.c b/builtin/show-branch.c\nindex f02831b085..6bfe9e2e96 100644\n--- a/builtin/show-branch.c\n+++ b/builtin/show-branch.c\n@@ -310,7 +310,7 @@ static void show_one_commit(struct commit *commit, int no_name)\n \tstruct commit_name *name = commit_to_name(commit);\n \n \tif (commit->object.parsed) {\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &pretty);\n \t\tpretty_str = pretty.buf;\n \t}\n \tskip_prefix(pretty_str, \"[PATCH] \", &pretty_str);\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex 785c1f9e5d..a522bb6de5 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -1480,7 +1480,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \t\t\t\t\t\t  &head_commit->object.oid,\n \t\t\t\t\t\t  DEFAULT_ABBREV);\n \tstrbuf_addf(&msg, \"%s: %s \", branch_name, head_short_sha1);\n-\tpp_commit_easy(CMIT_FMT_ONELINE, head_commit, &msg);\n+\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, head_commit, &msg);\n \n \tstrbuf_addf(&commit_tree_label, \"index on %s\\n\", msg.buf);\n \tcommit_list_insert(head_commit, &parents);\ndiff --git a/bundle.c b/bundle.c\nindex 42327f9739..3bc2ed9ee9 100644\n--- a/bundle.c\n+++ b/bundle.c\n@@ -463,7 +463,7 @@ static void write_bundle_prerequisites(struct commit *commit, void *data)\n \tctx.fmt = CMIT_FMT_ONELINE;\n \tctx.output_encoding = get_log_output_encoding();\n \tstrbuf_reset(&buf);\n-\tpretty_print_commit(&ctx, commit, &buf);\n+\tpretty_print_commit(the_repository, &ctx, commit, &buf);\n \tstrbuf_trim(&buf);\n \n \tobject = (struct object *)commit;\ndiff --git a/log-tree.c b/log-tree.c\nindex 7e048701d0..fd2fb0bed6 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -885,7 +885,7 @@ void show_log(struct rev_info *opt)\n \t\tctx.from_ident = &opt->from_ident;\n \tif (opt->graph)\n \t\tctx.graph_width = graph_width(opt->graph);\n-\tpretty_print_commit(&ctx, commit, &msgbuf);\n+\tpretty_print_commit(opt->repo, &ctx, commit, &msgbuf);\n \n \tif (opt->add_signoff)\n \t\tappend_signoff(&msgbuf, 0, APPEND_SIGNOFF_DEDUP);\ndiff --git a/pretty.c b/pretty.c\nindex e0646bbc5d..51e3480431 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -2281,7 +2281,7 @@ void pp_remainder(struct pretty_print_context *pp,\n \t}\n }\n \n-void pretty_print_commit(struct pretty_print_context *pp,\n+void pretty_print_commit(struct repository *r, struct pretty_print_context *pp,\n \t\t\t const struct commit *commit,\n \t\t\t struct strbuf *sb)\n {\n@@ -2363,10 +2363,10 @@ void pretty_print_commit(struct pretty_print_context *pp,\n \trepo_unuse_commit_buffer(the_repository, commit, reencoded);\n }\n \n-void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,\n+void pp_commit_easy(struct repository *r, enum cmit_fmt fmt, const struct commit *commit,\n \t\t    struct strbuf *sb)\n {\n \tstruct pretty_print_context pp = {0};\n \tpp.fmt = fmt;\n-\tpretty_print_commit(&pp, commit, sb);\n+\tpretty_print_commit(r, &pp, commit, sb);\n }\ndiff --git a/pretty.h b/pretty.h\nindex fac699033e..13eb0189bd 100644\n--- a/pretty.h\n+++ b/pretty.h\n@@ -82,7 +82,7 @@ void userformat_find_requirements(const char *fmt, struct userformat_want *w);\n  * Shortcut for invoking pretty_print_commit if we do not have any context.\n  * Context would be set empty except \"fmt\".\n  */\n-void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,\n+void pp_commit_easy(struct repository *r, enum cmit_fmt fmt, const struct commit *commit,\n \t\t\tstruct strbuf *sb);\n \n /*\n@@ -132,7 +132,7 @@ void get_commit_format(const char *arg, struct rev_info *);\n  * and put it into \"sb\".\n  * Please use this function if you have a context (candidate for \"pp\").\n  */\n-void pretty_print_commit(struct pretty_print_context *pp,\n+void pretty_print_commit(struct repository *r, struct pretty_print_context *pp,\n \t\t\tconst struct commit *commit,\n \t\t\tstruct strbuf *sb);\n \ndiff --git a/range-diff.c b/range-diff.c\nindex 57edff40a8..31d38c2318 100644\n--- a/range-diff.c\n+++ b/range-diff.c\n@@ -460,7 +460,7 @@ static void output_pair_header(struct diff_options *diffopt,\n \t\t\tstrbuf_addf(buf, \"%s%s\", color_reset, color);\n \n \t\tstrbuf_addch(buf, ' ');\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, buf);\n+\t\tpp_commit_easy(diffopt->repo, CMIT_FMT_ONELINE, commit, buf);\n \t}\n \tstrbuf_addf(buf, \"%s\\n\", color_reset);\n \ndiff --git a/sequencer.c b/sequencer.c\nindex 627020d65b..e6b3e05fce 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -5870,7 +5870,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,\n \t\t\tcontinue;\n \n \t\tstrbuf_reset(&oneline);\n-\t\tpretty_print_commit(pp, commit, &oneline);\n+\t\tpretty_print_commit(revs->repo, pp, commit, &oneline);\n \n \t\tto_merge = commit->parents ? commit->parents->next : NULL;\n \t\tif (!to_merge) {\n@@ -6012,7 +6012,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,\n \t\t\t\tstrbuf_addf(out, \"%s onto\\n\", cmd_reset);\n \t\t\telse {\n \t\t\t\tstrbuf_reset(&oneline);\n-\t\t\t\tpretty_print_commit(pp, commit, &oneline);\n+\t\t\t\tpretty_print_commit(revs->repo, pp, commit, &oneline);\n \t\t\t\tstrbuf_addf(out, \"%s %s %s\\n\",\n \t\t\t\t\t    cmd_reset, to, oneline.buf);\n \t\t\t}\n@@ -6124,7 +6124,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out,\n \t\t\tcontinue;\n \t\tstrbuf_addf(out, \"%s %s \", insn,\n \t\t\t    oid_to_hex(&commit->object.oid));\n-\t\tpretty_print_commit(&pp, commit, out);\n+\t\tpretty_print_commit(r, &pp, commit, out);\n \t\tif (is_empty)\n \t\t\tstrbuf_addf(out, \" %s empty\", comment_line_str);\n \t\tstrbuf_addch(out, '\\n');\n-- \n2.43.0\n\n"},{"id":"537481","messageId":"20260301203539.1421152-4-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260301203539.1421152-1-a3205153416@gmail.com","subject":"[PATCH v3 3/3] environment: migrate encoding configs to struct repository","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-01T20:35:39Z","receivedAt":"2026-03-01T20:36:12Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"The global variables 'git_commit_encoding' and 'git_log_output_encoding'\nprevent libification.\n\nMigrate these variables into 'struct repository'. Note that these variables\nare not migrated to 'repo_settings'. As user preferences, they must be parsed\neagerly to maintain immediate UX feedback.\n\nWhile the core read and write APIs (updated in previous patches) now\nutilize the 'struct repository' pointer, the config parsing step\n('git_default_i18n_config') currently parses these values into\n'the_repository', since safely plumbing a repository pointer through\nthe 'git_default_config' callback machinery is highly invasive due to\nthe diverse and custom structures currently passed via the 'void *cb'\nparameter.\n\nSigned-off-by: Tian Yuchen <a3205153416@gmail.com>\n---\n builtin/am.c       |  4 ++--\n builtin/blame.c    |  2 +-\n builtin/commit.c   |  6 +++---\n builtin/log.c      |  2 +-\n builtin/mailinfo.c |  6 +++---\n builtin/rev-list.c |  2 +-\n builtin/shortlog.c |  2 +-\n bundle.c           |  2 +-\n commit.c           | 13 +++++++------\n environment.c      | 19 ++++++++-----------\n environment.h      |  7 ++-----\n log-tree.c         |  4 ++--\n pretty.c           |  2 +-\n remote-curl.c      |  2 +-\n replay.c           |  2 +-\n repository.c       |  2 ++\n repository.h       |  5 +++++\n revision.c         | 10 +++++-----\n sequencer.c        | 22 +++++++++++-----------\n submodule.c        |  2 +-\n 20 files changed, 59 insertions(+), 57 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 5296124f84..990b6c54e7 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1216,7 +1216,7 @@ static int parse_mail(struct am_state *state, const char *mail)\n \tsetup_mailinfo(the_repository, &mi);\n \n \tif (state->utf8)\n-\t\tmi.metainfo_charset = get_commit_output_encoding();\n+\t\tmi.metainfo_charset = get_commit_output_encoding(the_repository);\n \telse\n \t\tmi.metainfo_charset = NULL;\n \n@@ -1355,7 +1355,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit)\n \tstruct ident_split id;\n \n \tbuffer = repo_logmsg_reencode(the_repository, commit, NULL,\n-\t\t\t\t      get_commit_output_encoding());\n+\t\t\t\t      get_commit_output_encoding(the_repository));\n \n \tident_line = find_commit_header(buffer, \"author\", &ident_len);\n \tif (!ident_line)\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex eac2fe7320..0ad9f2c9f7 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -202,7 +202,7 @@ static void get_commit_info(struct commit *commit, struct commit_info *ret)\n \tconst char *subject, *encoding;\n \tconst char *message;\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = get_log_output_encoding(the_repository);\n \tmessage = repo_logmsg_reencode(the_repository, commit, NULL, encoding);\n \tget_ac_line(message, \"\\nauthor \",\n \t\t    &ret->author, &ret->author_mail,\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex d619fd2ace..caf5896d97 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -794,7 +794,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\t\tc = lookup_commit_reference_by_name(squash_message);\n \t\t\tif (!c)\n \t\t\t\tdie(_(\"could not lookup commit '%s'\"), squash_message);\n-\t\t\tctx.output_encoding = get_commit_output_encoding();\n+\t\t\tctx.output_encoding = get_commit_output_encoding(the_repository);\n \t\t\trepo_format_commit_message(the_repository, c,\n \t\t\t\t\t\t   \"squash! %s\\n\\n\", &sb,\n \t\t\t\t\t\t   &ctx);\n@@ -829,7 +829,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\tcommit = lookup_commit_reference_by_name(fixup_commit);\n \t\tif (!commit)\n \t\t\tdie(_(\"could not lookup commit '%s'\"), fixup_commit);\n-\t\tctx.output_encoding = get_commit_output_encoding();\n+\t\tctx.output_encoding = get_commit_output_encoding(the_repository);\n \t\tfmt = xstrfmt(\"%s! %%s\\n\\n\", fixup_prefix);\n \t\trepo_format_commit_message(the_repository, commit, fmt, &sb,\n \t\t\t\t\t   &ctx);\n@@ -1235,7 +1235,7 @@ static const char *read_commit_message(const char *name)\n \tcommit = lookup_commit_reference_by_name(name);\n \tif (!commit)\n \t\tdie(_(\"could not lookup commit '%s'\"), name);\n-\tout_enc = get_commit_output_encoding();\n+\tout_enc = get_commit_output_encoding(the_repository);\n \treturn repo_logmsg_reencode(the_repository, commit, NULL, out_enc);\n }\n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 0758aed580..8edb3c54e7 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -568,7 +568,7 @@ static void show_tagger(const char *buf, struct rev_info *rev)\n \n \tpp.fmt = rev->commit_format;\n \tpp.date_mode = rev->date_mode;\n-\tpp_user_info(&pp, \"Tagger\", &out, buf, get_log_output_encoding());\n+\tpp_user_info(&pp, \"Tagger\", &out, buf, get_log_output_encoding(the_repository));\n \tfprintf(rev->diffopt.file, \"%s\", out.buf);\n \tstrbuf_release(&out);\n }\ndiff --git a/builtin/mailinfo.c b/builtin/mailinfo.c\nindex 8de7ba7de1..4f17cf1598 100644\n--- a/builtin/mailinfo.c\n+++ b/builtin/mailinfo.c\n@@ -52,7 +52,7 @@ static int parse_opt_quoted_cr(const struct option *opt, const char *arg, int un\n int cmd_mailinfo(int argc,\n \t\t const char **argv,\n \t\t const char *prefix,\n-\t\t struct repository *repo UNUSED)\n+\t\t struct repository *repo)\n {\n \tstruct metainfo_charset meta_charset;\n \tstruct mailinfo mi;\n@@ -83,7 +83,7 @@ int cmd_mailinfo(int argc,\n \t\tOPT_END()\n \t};\n \n-\tsetup_mailinfo(the_repository, &mi);\n+\tsetup_mailinfo(repo, &mi);\n \tmeta_charset.policy = CHARSET_DEFAULT;\n \n \targc = parse_options(argc, argv, prefix, options, mailinfo_usage, 0);\n@@ -93,7 +93,7 @@ int cmd_mailinfo(int argc,\n \n \tswitch (meta_charset.policy) {\n \tcase CHARSET_DEFAULT:\n-\t\tmi.metainfo_charset = get_commit_output_encoding();\n+\t\tmi.metainfo_charset = get_commit_output_encoding(repo);\n \t\tbreak;\n \tcase CHARSET_NO_REENCODE:\n \t\tmi.metainfo_charset = NULL;\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex 57c7b8d3ff..3732edae8b 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -304,7 +304,7 @@ static void show_commit(struct commit *commit, void *data)\n \t\tctx.date_mode = revs->date_mode;\n \t\tctx.date_mode_explicit = revs->date_mode_explicit;\n \t\tctx.fmt = revs->commit_format;\n-\t\tctx.output_encoding = get_log_output_encoding();\n+\t\tctx.output_encoding = get_log_output_encoding(the_repository);\n \t\tctx.color = revs->diffopt.use_color;\n \t\tctx.rev = revs;\n \t\tpretty_print_commit(the_repository, &ctx, commit, &buf);\ndiff --git a/builtin/shortlog.c b/builtin/shortlog.c\nindex 109785fd00..79606e57be 100644\n--- a/builtin/shortlog.c\n+++ b/builtin/shortlog.c\n@@ -248,7 +248,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)\n \tctx.fmt = CMIT_FMT_USERFORMAT;\n \tctx.abbrev = log->abbrev;\n \tctx.date_mode = log->date_mode;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = get_log_output_encoding(the_repository);\n \n \tif (!log->summary) {\n \t\tif (log->user_format)\ndiff --git a/bundle.c b/bundle.c\nindex 3bc2ed9ee9..3b98cdd6fd 100644\n--- a/bundle.c\n+++ b/bundle.c\n@@ -461,7 +461,7 @@ static void write_bundle_prerequisites(struct commit *commit, void *data)\n \twrite_or_die(bpi->fd, buf.buf, buf.len);\n \n \tctx.fmt = CMIT_FMT_ONELINE;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = get_log_output_encoding(the_repository);\n \tstrbuf_reset(&buf);\n \tpretty_print_commit(the_repository, &ctx, commit, &buf);\n \tstrbuf_trim(&buf);\ndiff --git a/commit.c b/commit.c\nindex 71a2b7bbe5..cb8ec675d1 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1663,7 +1663,8 @@ N_(\"Warning: commit message did not conform to UTF-8.\\n\"\n    \"You may want to amend it after fixing the message, or set the config\\n\"\n    \"variable i18n.commitEncoding to the encoding your project uses.\\n\");\n \n-static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg_len,\n+static void write_commit_tree(struct repository *r, struct strbuf *buffer,\n+\t\t\t      const char *msg, size_t msg_len,\n \t\t\t      const struct object_id *tree,\n \t\t\t      const struct object_id *parents, size_t parents_len,\n \t\t\t      const char *author, const char *committer,\n@@ -1673,7 +1674,7 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \tsize_t i;\n \n \t/* Not having i18n.commitencoding is the same as having utf-8 */\n-\tencoding_is_utf8 = is_encoding_utf8(git_commit_encoding);\n+\tencoding_is_utf8 = is_encoding_utf8(get_commit_output_encoding(r));\n \n \tstrbuf_grow(buffer, 8192); /* should avoid reallocs for the headers */\n \tstrbuf_addf(buffer, \"tree %s\\n\", oid_to_hex(tree));\n@@ -1694,7 +1695,7 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \t\tcommitter = git_committer_info(IDENT_STRICT);\n \tstrbuf_addf(buffer, \"committer %s\\n\", committer);\n \tif (!encoding_is_utf8)\n-\t\tstrbuf_addf(buffer, \"encoding %s\\n\", git_commit_encoding);\n+\t\tstrbuf_addf(buffer, \"encoding %s\\n\", get_commit_output_encoding(r));\n \n \twhile (extra) {\n \t\tadd_extra_header(buffer, extra);\n@@ -1722,7 +1723,7 @@ int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len,\n \tsize_t i, nparents;\n \n \t/* Not having i18n.commitencoding is the same as having utf-8 */\n-\tencoding_is_utf8 = is_encoding_utf8(git_commit_encoding);\n+\tencoding_is_utf8 = is_encoding_utf8(get_commit_output_encoding(r));\n \n \todb_assert_oid_type(the_repository->objects, tree, OBJ_TREE);\n \n@@ -1735,7 +1736,7 @@ int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len,\n \tfor (const struct commit_list *p = parents; p; p = p->next)\n \t\toidcpy(&parent_buf[i++], &p->item->object.oid);\n \n-\twrite_commit_tree(&buffer, msg, msg_len, tree, parent_buf, nparents, author, committer, extra);\n+\twrite_commit_tree(r, &buffer, msg, msg_len, tree, parent_buf, nparents, author, committer, extra);\n \tif (sign_commit && sign_commit_to_strbuf(&sig, &buffer, sign_commit)) {\n \t\tresult = -1;\n \t\tgoto out;\n@@ -1763,7 +1764,7 @@ int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len,\n \t\t\tfree(mapped_parents);\n \t\t\tgoto out;\n \t\t}\n-\t\twrite_commit_tree(&compat_buffer, msg, msg_len, &mapped_tree,\n+\t\twrite_commit_tree(r, &compat_buffer, msg, msg_len, &mapped_tree,\n \t\t\t\t  mapped_parents, nparents, author, committer, compat_extra);\n \t\tfree_commit_extra_headers(compat_extra);\n \t\tfree(mapped_parents);\ndiff --git a/environment.c b/environment.c\nindex 0026eb2274..a27c13da3d 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -197,15 +197,14 @@ const char *strip_namespace(const char *namespaced_ref)\n \treturn NULL;\n }\n \n-const char *get_log_output_encoding(void)\n+const char *get_log_output_encoding(struct repository *r)\n {\n-\treturn git_log_output_encoding ? git_log_output_encoding\n-\t\t: get_commit_output_encoding();\n+\treturn r->log_output_encoding ? r->log_output_encoding : get_commit_output_encoding(r);\n }\n \n-const char *get_commit_output_encoding(void)\n+const char *get_commit_output_encoding(struct repository *r)\n {\n-\treturn git_commit_encoding ? git_commit_encoding : \"UTF-8\";\n+\treturn r->commit_encoding ? r->commit_encoding : \"UTF-8\";\n }\n \n int use_optional_locks(void)\n@@ -569,16 +568,14 @@ static int git_default_sparse_config(const char *var, const char *value)\n static int git_default_i18n_config(const char *var, const char *value)\n {\n \tif (!strcmp(var, \"i18n.commitencoding\")) {\n-\t\tFREE_AND_NULL(git_commit_encoding);\n-\t\treturn git_config_string(&git_commit_encoding, var, value);\n+\t\tFREE_AND_NULL(the_repository->commit_encoding);\n+\t\treturn git_config_string(&the_repository->commit_encoding, var, value);\n \t}\n-\n \tif (!strcmp(var, \"i18n.logoutputencoding\")) {\n-\t\tFREE_AND_NULL(git_log_output_encoding);\n-\t\treturn git_config_string(&git_log_output_encoding, var, value);\n+\t\tFREE_AND_NULL(the_repository->log_output_encoding);\n+\t\treturn git_config_string(&the_repository->log_output_encoding, var, value);\n \t}\n \n-\t/* Add other config variables here and to Documentation/config.adoc. */\n \treturn 0;\n }\n \ndiff --git a/environment.h b/environment.h\nindex 27f657af04..d1c62a8296 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -193,11 +193,8 @@ extern enum object_creation_mode object_creation_mode;\n \n extern int grafts_keep_true_parents;\n \n-const char *get_log_output_encoding(void);\n-const char *get_commit_output_encoding(void);\n-\n-extern char *git_commit_encoding;\n-extern char *git_log_output_encoding;\n+const char *get_log_output_encoding(struct repository *r);\n+const char *get_commit_output_encoding(struct repository *r);\n \n extern char *editor_program;\n extern char *askpass_program;\ndiff --git a/log-tree.c b/log-tree.c\nindex fd2fb0bed6..364fd015f5 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -859,7 +859,7 @@ void show_log(struct rev_info *opt)\n \n \t\traw = (opt->commit_format == CMIT_FMT_USERFORMAT);\n \t\tformat_display_notes(&commit->object.oid, &notebuf,\n-\t\t\t\t     get_log_output_encoding(), raw);\n+\t\t\t\t     get_log_output_encoding(opt->repo), raw);\n \t\tctx.notes_message = strbuf_detach(&notebuf, NULL);\n \t}\n \n@@ -879,7 +879,7 @@ void show_log(struct rev_info *opt)\n \tctx.mailmap = opt->mailmap;\n \tctx.color = opt->diffopt.use_color;\n \tctx.expand_tabs_in_log = opt->expand_tabs_in_log;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = get_log_output_encoding(opt->repo);\n \tctx.rev = opt;\n \tif (opt->from_ident.mail_begin && opt->from_ident.name_begin)\n \t\tctx.from_ident = &opt->from_ident;\ndiff --git a/pretty.c b/pretty.c\nindex 51e3480431..6b585e2763 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -2298,7 +2298,7 @@ void pretty_print_commit(struct repository *r, struct pretty_print_context *pp,\n \t\treturn;\n \t}\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = get_log_output_encoding(r);\n \tmsg = reencoded = repo_logmsg_reencode(the_repository, commit, NULL,\n \t\t\t\t\t       encoding);\n \ndiff --git a/remote-curl.c b/remote-curl.c\nindex 92e40bb682..146cb8930d 100644\n--- a/remote-curl.c\n+++ b/remote-curl.c\n@@ -379,7 +379,7 @@ static int show_http_message(struct strbuf *type, struct strbuf *charset,\n \tif (strcmp(type->buf, \"text/plain\"))\n \t\treturn -1;\n \tif (charset->len)\n-\t\tstrbuf_reencode(msg, charset->buf, get_log_output_encoding());\n+\t\tstrbuf_reencode(msg, charset->buf, get_log_output_encoding(the_repository));\n \n \tstrbuf_trim(msg);\n \tif (!msg->len)\ndiff --git a/replay.c b/replay.c\nindex 8704547aa1..0012d3aa18 100644\n--- a/replay.c\n+++ b/replay.c\n@@ -56,7 +56,7 @@ static struct commit *create_commit(struct repository *repo,\n \tchar *sign_commit = NULL; /* FIXME: cli users might want to sign again */\n \tstruct commit_extra_header *extra = NULL;\n \tstruct strbuf msg = STRBUF_INIT;\n-\tconst char *out_enc = get_commit_output_encoding();\n+\tconst char *out_enc = get_commit_output_encoding(repo);\n \tconst char *message = repo_logmsg_reencode(repo, based_on,\n \t\t\t\t\t\t   NULL, out_enc);\n \tconst char *orig_message = NULL;\ndiff --git a/repository.c b/repository.c\nindex 46a7c99930..a2ab093a68 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -370,6 +370,8 @@ void repo_clear(struct repository *repo)\n \tFREE_AND_NULL(repo->index_file);\n \tFREE_AND_NULL(repo->worktree);\n \tFREE_AND_NULL(repo->submodule_prefix);\n+\tFREE_AND_NULL(repo->commit_encoding);\n+\tFREE_AND_NULL(repo->log_output_encoding);\n \n \todb_free(repo->objects);\n \trepo->objects = NULL;\ndiff --git a/repository.h b/repository.h\nindex 7141237f97..4e67b15c36 100644\n--- a/repository.h\n+++ b/repository.h\n@@ -172,6 +172,11 @@ struct repository {\n \n \t/* Should repo_config() check for deprecated settings */\n \tbool check_deprecated_config;\n+\n+\t/* User's preferred encoding for commit messages and log output. */\n+\n+\tchar *commit_encoding;\n+\tchar *log_output_encoding;\n };\n \n #ifdef USE_THE_REPOSITORY_VARIABLE\ndiff --git a/revision.c b/revision.c\nindex 29972c3a19..b85cac9877 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2675,11 +2675,11 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t} else if (!strcmp(arg, \"--invert-grep\")) {\n \t\trevs->grep_filter.no_body_match = 1;\n \t} else if ((argcount = parse_long_opt(\"encoding\", argv, &optarg))) {\n-\t\tfree(git_log_output_encoding);\n+\t\tfree(revs->repo->log_output_encoding);\n \t\tif (strcmp(optarg, \"none\"))\n-\t\t\tgit_log_output_encoding = xstrdup(optarg);\n+\t\t\trevs->repo->log_output_encoding = xstrdup(optarg);\n \t\telse\n-\t\t\tgit_log_output_encoding = xstrdup(\"\");\n+\t\t\trevs->repo->log_output_encoding = xstrdup(\"\");\n \t\treturn argcount;\n \t} else if (!strcmp(arg, \"--reverse\")) {\n \t\trevs->reverse ^= 1;\n@@ -3129,7 +3129,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \n \tdiff_setup_done(&revs->diffopt);\n \n-\tif (!is_encoding_utf8(get_log_output_encoding()))\n+\tif (!is_encoding_utf8(get_log_output_encoding(revs->repo)))\n \t\trevs->grep_filter.ignore_locale = 1;\n \tcompile_grep_patterns(&revs->grep_filter);\n \n@@ -4063,7 +4063,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)\n \t * so we will not end up with a buffer that has two different encodings\n \t * in it.\n \t */\n-\tencoding = get_log_output_encoding();\n+\tencoding = get_log_output_encoding(opt->repo);\n \tmessage = repo_logmsg_reencode(the_repository, commit, NULL, encoding);\n \n \t/* Copy the commit to temporary if we are using \"fake\" headers */\ndiff --git a/sequencer.c b/sequencer.c\nindex e6b3e05fce..62717910d2 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -480,13 +480,13 @@ static const char *short_commit_name(struct repository *r, struct commit *commit\n \treturn repo_find_unique_abbrev(r, &commit->object.oid, DEFAULT_ABBREV);\n }\n \n-static int get_message(struct commit *commit, struct commit_message *out)\n+static int get_message(struct repository *r, struct commit *commit, struct commit_message *out)\n {\n \tconst char *abbrev, *subject;\n \tint subject_len;\n \n \tout->message = repo_logmsg_reencode(the_repository, commit, NULL,\n-\t\t\t\t\t    get_commit_output_encoding());\n+\t\t\t\t\t    get_commit_output_encoding(r));\n \tabbrev = short_commit_name(the_repository, commit);\n \n \tsubject_len = find_commit_subject(out->message, &subject);\n@@ -1539,7 +1539,7 @@ static int try_to_commit(struct repository *r,\n \n \tif (flags & AMEND_MSG) {\n \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", \"gpgsig-sha256\", NULL };\n-\t\tconst char *out_enc = get_commit_output_encoding();\n+\t\tconst char *out_enc = get_commit_output_encoding(r);\n \t\tconst char *message = repo_logmsg_reencode(r, current_head,\n \t\t\t\t\t\t\t   NULL, out_enc);\n \n@@ -2054,7 +2054,7 @@ static int update_squash_messages(struct repository *r,\n \tstruct strbuf buf = STRBUF_INIT;\n \tint res = 0;\n \tconst char *message, *body;\n-\tconst char *encoding = get_commit_output_encoding();\n+\tconst char *encoding = get_commit_output_encoding(r);\n \n \tif (!is_fixup(command))\n \t\tBUG(\"not a FIXUP or SQUASH %d\", command);\n@@ -2324,7 +2324,7 @@ static int do_pick_commit(struct repository *r,\n \telse\n \t\tparent = commit->parents->item;\n \n-\tif (get_message(commit, &msg) != 0)\n+\tif (get_message(r, commit, &msg) != 0)\n \t\treturn error(_(\"cannot get commit message for %s\"),\n \t\t\toid_to_hex(&commit->object.oid));\n \n@@ -3344,7 +3344,7 @@ static int walk_revs_populate_todo(struct todo_list *todo_list,\n \tif (prepare_revs(opts))\n \t\treturn -1;\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = get_log_output_encoding(the_repository);\n \n \twhile ((commit = get_revision(opts->revs))) {\n \t\tstruct todo_item *item = append_new_todo(todo_list);\n@@ -3730,7 +3730,7 @@ static int make_patch(struct repository *r,\n \t}\n \n \tif (!file_exists(rebase_path_message())) {\n-\t\tconst char *encoding = get_commit_output_encoding();\n+\t\tconst char *encoding = get_commit_output_encoding(r);\n \t\tconst char *commit_buffer = repo_logmsg_reencode(r,\n \t\t\t\t\t\t\t\t commit, NULL,\n \t\t\t\t\t\t\t\t encoding);\n@@ -4187,7 +4187,7 @@ static int do_merge(struct repository *r,\n \t}\n \n \tif (commit) {\n-\t\tconst char *encoding = get_commit_output_encoding();\n+\t\tconst char *encoding = get_commit_output_encoding(r);\n \t\tconst char *message = repo_logmsg_reencode(r, commit, NULL,\n \t\t\t\t\t\t\t   encoding);\n \t\tconst char *body;\n@@ -4831,7 +4831,7 @@ static int stopped_at_head(struct repository *r)\n \n \tif (repo_get_oid(r, \"HEAD\", &head) ||\n \t    !(commit = lookup_commit(r, &head)) ||\n-\t    repo_parse_commit(r, commit) || get_message(commit, &message))\n+\t    repo_parse_commit(r, commit) || get_message(r, commit, &message))\n \t\tfprintf(stderr, _(\"Stopped at HEAD\\n\"));\n \telse {\n \t\tfprintf(stderr, _(\"Stopped at %s\\n\"), message.label);\n@@ -5311,7 +5311,7 @@ static int commit_staged_changes(struct repository *r,\n \t\t\t\tstruct commit *commit;\n \t\t\t\tconst char *msg;\n \t\t\t\tconst char *path = rebase_path_squash_msg();\n-\t\t\t\tconst char *encoding = get_commit_output_encoding();\n+\t\t\t\tconst char *encoding = get_commit_output_encoding(r);\n \n \t\t\t\tif (parse_head(r, &commit)) {\n \t\t\t\t\tret = error(_(\"could not parse HEAD\"));\n@@ -6092,7 +6092,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out,\n \tget_commit_format(format, &revs);\n \tfree(format);\n \tpp.fmt = revs.commit_format;\n-\tpp.output_encoding = get_log_output_encoding();\n+\tpp.output_encoding = get_log_output_encoding(r);\n \n \tsetup_revisions_from_strvec(argv, &revs, NULL);\n \tif (argv->nr > 1) {\ndiff --git a/submodule.c b/submodule.c\nindex 508938e4da..a58ed3652c 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -479,7 +479,7 @@ static void print_submodule_diff_summary(struct repository *r, struct rev_info *\n \twhile ((commit = get_revision(rev))) {\n \t\tstruct pretty_print_context ctx = {0};\n \t\tctx.date_mode = rev->date_mode;\n-\t\tctx.output_encoding = get_log_output_encoding();\n+\t\tctx.output_encoding = get_log_output_encoding(r);\n \t\tstrbuf_setlen(&sb, 0);\n \t\trepo_format_commit_message(r, commit, format, &sb,\n \t\t\t\t      &ctx);\n-- \n2.43.0\n\n"},{"id":"537498","messageId":"20260302085738.2510514-1-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260228040727.2057192-1-a3205153416@gmail.com","subject":"[PATCH v4 0/3] move encoding configs to repo_config_values()","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-02T08:57:34Z","receivedAt":"2026-03-02T08:58:10Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"This is v4 of the series aimed at reducing the global state associated with \n`git_commit_encoding` and `git_log_output_encoding`.\n\nThis v4 series is built on top of Olamide Caleb Bello's recent patch:\n\"[Outreachy PATCH v7 1/3] environment: stop storing `core.attributesFile` globally\"\n(Message-ID: <48821a3848bef25c13038be8377ad73e7c17a924.1771258573.git.belkid98@gmail.com>)\n\nIt adopts the 'struct repo_config_values' introduced in that patch\nto safely encapsulate repository-specific parsed configurations.\n\nI would like to express my gratitude to Phillip Wood for help\nand guidance.\n\nTian Yuchen (3):\n  commit: plumb 'struct repository' into commit creation APIs\n  pretty: plumb 'struct repository' into pretty-print APIs\n  environment: migrate encoding configs to repo_config_values()\n\n builtin/am.c          |  6 +++---\n builtin/blame.c       |  2 +-\n builtin/checkout.c    |  4 ++--\n builtin/commit-tree.c |  2 +-\n builtin/commit.c      |  8 ++++----\n builtin/history.c     |  2 +-\n builtin/log.c         |  4 ++--\n builtin/mailinfo.c    |  6 +++---\n builtin/merge.c       |  6 +++---\n builtin/rebase.c      |  2 +-\n builtin/reset.c       |  2 +-\n builtin/rev-list.c    |  4 ++--\n builtin/shortlog.c    |  4 ++--\n builtin/show-branch.c |  2 +-\n builtin/stash.c       | 12 ++++++------\n bundle.c              |  4 ++--\n commit.c              | 20 ++++++++++----------\n commit.h              |  4 ++--\n environment.c         | 33 ++++++++++++++++++++-------------\n environment.h         | 10 +++++-----\n log-tree.c            |  6 +++---\n notes-cache.c         |  2 +-\n notes-utils.c         |  2 +-\n pretty.c              |  8 ++++----\n pretty.h              |  4 ++--\n range-diff.c          |  2 +-\n remote-curl.c         |  2 +-\n replay.c              |  4 ++--\n repository.c          |  2 ++\n revision.c            | 12 +++++++-----\n sequencer.c           | 32 ++++++++++++++++----------------\n submodule.c           |  2 +-\n 32 files changed, 113 insertions(+), 102 deletions(-)\n\n-- \n2.43.0\n\n"},{"id":"537499","messageId":"20260302085738.2510514-2-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260302085738.2510514-1-a3205153416@gmail.com","subject":"[PATCH v4 1/3] commit: plumb 'struct repository' into commit creation APIs","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-02T08:57:35Z","receivedAt":"2026-03-02T08:58:12Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"To pave the way for reducing the global state tied to commit encoding\nin a subsequent patch, functions like 'commit_tree()' and\n'commit_tree_extended()' must be able to access a repository instance.\n\nPlumb the 'struct repository' pointer down the call chain for these\nAPIs. For built-ins or subsystems already dependent on global state\n(e.g., 'notes_cache_write()'), fallback to 'the_repository'.\n\nNo functional changes are introduced in this preparatory step.\n\nSigned-off-by: Tian Yuchen <a3205153416@gmail.com>\n---\n builtin/am.c          |  2 +-\n builtin/commit-tree.c |  2 +-\n builtin/commit.c      |  2 +-\n builtin/history.c     |  2 +-\n builtin/merge.c       |  4 ++--\n builtin/rebase.c      |  2 +-\n builtin/stash.c       | 10 +++++-----\n commit.c              |  7 +++----\n commit.h              |  4 ++--\n notes-cache.c         |  2 +-\n notes-utils.c         |  2 +-\n replay.c              |  2 +-\n sequencer.c           |  4 ++--\n 13 files changed, 22 insertions(+), 23 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex e0c767e223..5296124f84 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1699,7 +1699,7 @@ static void do_commit(const struct am_state *state)\n \t\t\t\t\t\t\t : state->author_date,\n \t\t\t\t      IDENT_STRICT);\n \n-\tif (commit_tree_extended(state->msg, state->msg_len, &tree, parents,\n+\tif (commit_tree_extended(the_repository, state->msg, state->msg_len, &tree, parents,\n \t\t\t\t &commit, author, committer, state->sign_commit,\n \t\t\t\t NULL))\n \t\tdie(_(\"failed to write commit object\"));\ndiff --git a/builtin/commit-tree.c b/builtin/commit-tree.c\nindex 30535db131..c489749588 100644\n--- a/builtin/commit-tree.c\n+++ b/builtin/commit-tree.c\n@@ -144,7 +144,7 @@ int cmd_commit_tree(int argc,\n \t\t\tdie_errno(_(\"git commit-tree: failed to read\"));\n \t}\n \n-\tif (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,\n+\tif (commit_tree(the_repository, buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,\n \t\t\tNULL, sign_commit)) {\n \t\tret = 1;\n \t\tgoto out;\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex 9e3a09d532..d619fd2ace 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -1931,7 +1931,7 @@ int cmd_commit(int argc,\n \t\tappend_merge_tag_headers(parents, &tail);\n \t}\n \n-\tif (commit_tree_extended(sb.buf, sb.len, &the_repository->index->cache_tree->oid,\n+\tif (commit_tree_extended(the_repository, sb.buf, sb.len, &the_repository->index->cache_tree->oid,\n \t\t\t\t parents, &oid, author_ident.buf, NULL,\n \t\t\t\t sign_commit, extra)) {\n \t\trollback_index_files();\ndiff --git a/builtin/history.c b/builtin/history.c\nindex 8dcb9a6046..3d83ac021b 100644\n--- a/builtin/history.c\n+++ b/builtin/history.c\n@@ -136,7 +136,7 @@ static int commit_tree_with_edited_message(struct repository *repo,\n \n \toriginal_extra_headers = read_commit_extra_headers(original, exclude_gpgsig);\n \n-\tret = commit_tree_extended(commit_message.buf, commit_message.len, &original_tree_oid,\n+\tret = commit_tree_extended(repo, commit_message.buf, commit_message.len, &original_tree_oid,\n \t\t\t\t   original->parents, &rewritten_commit_oid, original_author,\n \t\t\t\t   NULL, NULL, original_extra_headers);\n \tif (ret < 0)\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 4e456a381c..7c944fe179 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -1000,7 +1000,7 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)\n \tpptr = commit_list_append(head, pptr);\n \tpptr = commit_list_append(remoteheads->item, pptr);\n \tprepare_to_commit(remoteheads);\n-\tif (commit_tree(merge_msg.buf, merge_msg.len, &result_tree, parents,\n+\tif (commit_tree(the_repository, merge_msg.buf, merge_msg.len, &result_tree, parents,\n \t\t\t&result_commit, NULL, sign_commit))\n \t\tdie(_(\"failed to write commit object\"));\n \tfinish(head, remoteheads, &result_commit, \"In-index merge\");\n@@ -1027,7 +1027,7 @@ static int finish_automerge(struct commit *head,\n \tif (!head_subsumed || fast_forward == FF_NO)\n \t\tcommit_list_insert(head, &parents);\n \tprepare_to_commit(remoteheads);\n-\tif (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents,\n+\tif (commit_tree(the_repository, merge_msg.buf, merge_msg.len, result_tree, parents,\n \t\t\t&result_commit, NULL, sign_commit))\n \t\tdie(_(\"failed to write commit object\"));\n \tstrbuf_addf(&buf, \"Merge made by the '%s' strategy.\", wt_strategy);\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex c487e10907..7b9ab85cc0 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1647,7 +1647,7 @@ int cmd_rebase(int argc,\n \t\toptions.upstream_arg = options.upstream_name;\n \t} else {\n \t\tif (!options.onto_name) {\n-\t\t\tif (commit_tree(\"\", 0, the_hash_algo->empty_tree, NULL,\n+\t\t\tif (commit_tree(the_repository, \"\", 0, the_hash_algo->empty_tree, NULL,\n \t\t\t\t\t&squash_onto, NULL, NULL) < 0)\n \t\t\t\tdie(_(\"Could not create new root commit\"));\n \t\t\toptions.squash_onto = &squash_onto;\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex f06cfa7989..785c1f9e5d 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -1258,7 +1258,7 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg,\n \t\tgoto done;\n \t}\n \n-\tif (commit_tree(untracked_msg.buf, untracked_msg.len,\n+\tif (commit_tree(the_repository, untracked_msg.buf, untracked_msg.len,\n \t\t\t&info->u_tree, NULL, &info->u_commit, NULL, NULL)) {\n \t\tret = -1;\n \t\tgoto done;\n@@ -1486,7 +1486,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \tcommit_list_insert(head_commit, &parents);\n \tif (write_index_as_tree(&info->i_tree, the_repository->index,\n \t\t\t\trepo_get_index_file(the_repository), 0, NULL) ||\n-\t    commit_tree(commit_tree_label.buf, commit_tree_label.len,\n+\t    commit_tree(the_repository, commit_tree_label.buf, commit_tree_label.len,\n \t\t\t&info->i_tree, parents, &info->i_commit, NULL, NULL)) {\n \t\tif (!quiet)\n \t\t\tfprintf_ln(stderr, _(\"Cannot save the current \"\n@@ -1551,7 +1551,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \t\t\t   &parents);\n \tcommit_list_insert(head_commit, &parents);\n \n-\tif (commit_tree(stash_msg_buf->buf, stash_msg_buf->len, &info->w_tree,\n+\tif (commit_tree(the_repository, stash_msg_buf->buf, stash_msg_buf->len, &info->w_tree,\n \t\t\tparents, &info->w_commit, NULL, NULL)) {\n \t\tif (!quiet)\n \t\t\tfprintf_ln(stderr, _(\"Cannot record \"\n@@ -2035,7 +2035,7 @@ static int write_commit_with_parents(struct repository *r,\n \tauthor = xmemdupz(orig_author, author_len);\n \tcommitter = xmemdupz(orig_committer, committer_len);\n \n-\tif (commit_tree_extended(msg.buf, msg.len,\n+\tif (commit_tree_extended(r, msg.buf, msg.len,\n \t\t\t\t r->hash_algo->empty_tree, parents,\n \t\t\t\t out, author, committer,\n \t\t\t\t NULL, NULL)) {\n@@ -2258,7 +2258,7 @@ static int do_export_stash(struct repository *r,\n \t\t\t      \"2001-09-17T00:00:00Z\", 0);\n \n \t/* First, we create a single empty commit. */\n-\tif (commit_tree_extended(\"\", 0, r->hash_algo->empty_tree, NULL,\n+\tif (commit_tree_extended(the_repository, \"\", 0, r->hash_algo->empty_tree, NULL,\n \t\t\t\t &base, author, committer, NULL, NULL))\n \t\treturn error(_(\"unable to write base commit\"));\n \ndiff --git a/commit.c b/commit.c\nindex d16ae73345..71a2b7bbe5 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1534,7 +1534,7 @@ void free_commit_extra_headers(struct commit_extra_header *extra)\n \t}\n }\n \n-int commit_tree(const char *msg, size_t msg_len, const struct object_id *tree,\n+int commit_tree(struct repository *r, const char *msg, size_t msg_len, const struct object_id *tree,\n \t\tconst struct commit_list *parents, struct object_id *ret,\n \t\tconst char *author, const char *sign_commit)\n {\n@@ -1542,7 +1542,7 @@ int commit_tree(const char *msg, size_t msg_len, const struct object_id *tree,\n \tint result;\n \n \tappend_merge_tag_headers(parents, &tail);\n-\tresult = commit_tree_extended(msg, msg_len, tree, parents, ret, author,\n+\tresult = commit_tree_extended(r, msg, msg_len, tree, parents, ret, author,\n \t\t\t\t      NULL, sign_commit, extra);\n \tfree_commit_extra_headers(extra);\n \treturn result;\n@@ -1706,14 +1706,13 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \tstrbuf_add(buffer, msg, msg_len);\n }\n \n-int commit_tree_extended(const char *msg, size_t msg_len,\n+int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len,\n \t\t\t const struct object_id *tree,\n \t\t\t const struct commit_list *parents, struct object_id *ret,\n \t\t\t const char *author, const char *committer,\n \t\t\t const char *sign_commit,\n \t\t\t const struct commit_extra_header *extra)\n {\n-\tstruct repository *r = the_repository;\n \tint result = 0;\n \tint encoding_is_utf8;\n \tstruct strbuf buffer = STRBUF_INIT, compat_buffer = STRBUF_INIT;\ndiff --git a/commit.h b/commit.h\nindex 1635de418b..d3d664d0ff 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -289,12 +289,12 @@ struct commit_extra_header {\n void append_merge_tag_headers(const struct commit_list *parents,\n \t\t\t      struct commit_extra_header ***tail);\n \n-int commit_tree(const char *msg, size_t msg_len,\n+int commit_tree(struct repository *r, const char *msg, size_t msg_len,\n \t\tconst struct object_id *tree,\n \t\tconst struct commit_list *parents, struct object_id *ret,\n \t\tconst char *author, const char *sign_commit);\n \n-int commit_tree_extended(const char *msg, size_t msg_len,\n+int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len,\n \t\t\t const struct object_id *tree,\n \t\t\t const struct commit_list *parents, struct object_id *ret,\n \t\t\t const char *author, const char *committer,\ndiff --git a/notes-cache.c b/notes-cache.c\nindex bf5bb1f6c1..5dbbd94ea3 100644\n--- a/notes-cache.c\n+++ b/notes-cache.c\n@@ -66,7 +66,7 @@ int notes_cache_write(struct notes_cache *c)\n \n \tif (write_notes_tree(&c->tree, &tree_oid))\n \t\treturn -1;\n-\tif (commit_tree(c->validity, strlen(c->validity), &tree_oid, NULL,\n+\tif (commit_tree(the_repository, c->validity, strlen(c->validity), &tree_oid, NULL,\n \t\t\t&commit_oid, NULL, NULL) < 0)\n \t\treturn -1;\n \tif (refs_update_ref(get_main_ref_store(the_repository), \"update notes cache\", c->tree.update_ref, &commit_oid,\ndiff --git a/notes-utils.c b/notes-utils.c\nindex 5c1c75d5b8..4671a11993 100644\n--- a/notes-utils.c\n+++ b/notes-utils.c\n@@ -36,7 +36,7 @@ void create_notes_commit(struct repository *r,\n \t\t/* else: t->ref points to nothing, assume root/orphan commit */\n \t}\n \n-\tif (commit_tree(msg, msg_len, &tree_oid, parents, result_oid, NULL,\n+\tif (commit_tree(r, msg, msg_len, &tree_oid, parents, result_oid, NULL,\n \t\t\tNULL))\n \t\tdie(\"Failed to commit notes tree to database\");\n \ndiff --git a/replay.c b/replay.c\nindex f97d652f33..8704547aa1 100644\n--- a/replay.c\n+++ b/replay.c\n@@ -68,7 +68,7 @@ static struct commit *create_commit(struct repository *repo,\n \tstrbuf_addstr(&msg, orig_message);\n \tauthor = get_author(message);\n \treset_ident_date();\n-\tif (commit_tree_extended(msg.buf, msg.len, &tree->object.oid, parents,\n+\tif (commit_tree_extended(repo, msg.buf, msg.len, &tree->object.oid, parents,\n \t\t\t\t &ret, author, NULL, sign_commit, extra)) {\n \t\terror(_(\"failed to write commit object\"));\n \t\tgoto out;\ndiff --git a/sequencer.c b/sequencer.c\nindex a3eb39bb25..627020d65b 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -1672,7 +1672,7 @@ static int try_to_commit(struct repository *r,\n \t\tfree(email);\n \t}\n \n-\tif (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid,\n+\tif (commit_tree_extended(r, msg->buf, msg->len, &tree, parents, oid,\n \t\t\t\t author, committer, opts->gpg_sign, extra)) {\n \t\tres = error(_(\"failed to write commit object\"));\n \t\tgoto out;\n@@ -3989,7 +3989,7 @@ static int do_reset(struct repository *r,\n \tif (len == 10 && !strncmp(\"[new root]\", name, len)) {\n \t\tif (!opts->have_squash_onto) {\n \t\t\tconst char *hex;\n-\t\t\tif (commit_tree(\"\", 0, the_hash_algo->empty_tree,\n+\t\t\tif (commit_tree(r, \"\", 0, the_hash_algo->empty_tree,\n \t\t\t\t\tNULL, &opts->squash_onto,\n \t\t\t\t\tNULL, NULL))\n \t\t\t\treturn error(_(\"writing fake root commit\"));\n-- \n2.43.0\n\n"},{"id":"537500","messageId":"20260302085738.2510514-3-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260302085738.2510514-1-a3205153416@gmail.com","subject":"[PATCH v4 2/3] pretty: plumb 'struct repository' into pretty-print APIs","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-02T08:57:36Z","receivedAt":"2026-03-02T08:58:27Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"To prepare for the elimination of the global state associated with\n'log_output_encoding', functions responsible for formatting commit\nmessages, such as 'pretty_print_commit()' and 'pp_commit_easy()',\nmust be able to access a repository instance.\n\nPlumb the 'struct repository' pointer down the call chain for these\nAPIs. Where no such context is readily available in built-ins or\nhigh-level functions, fallback to 'the_repository'.\n\nSigned-off-by: Tian Yuchen <a3205153416@gmail.com>\n---\n builtin/checkout.c    | 4 ++--\n builtin/log.c         | 2 +-\n builtin/merge.c       | 2 +-\n builtin/reset.c       | 2 +-\n builtin/rev-list.c    | 2 +-\n builtin/shortlog.c    | 2 +-\n builtin/show-branch.c | 2 +-\n builtin/stash.c       | 2 +-\n bundle.c              | 2 +-\n log-tree.c            | 2 +-\n pretty.c              | 6 +++---\n pretty.h              | 4 ++--\n range-diff.c          | 2 +-\n sequencer.c           | 6 +++---\n 14 files changed, 20 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex 2d816de583..3b9e3e45f9 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -689,7 +689,7 @@ static void describe_detached_head(const char *msg, struct commit *commit)\n \tstruct strbuf sb = STRBUF_INIT;\n \n \tif (!repo_parse_commit(the_repository, commit))\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &sb);\n \tif (print_sha1_ellipsis()) {\n \t\tfprintf(stderr, \"%s %s... %s\\n\", msg,\n \t\t\trepo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV),\n@@ -1077,7 +1077,7 @@ static void describe_one_orphan(struct strbuf *sb, struct commit *commit)\n \tstrbuf_add_unique_abbrev(sb, &commit->object.oid, DEFAULT_ABBREV);\n \tstrbuf_addch(sb, ' ');\n \tif (!repo_parse_commit(the_repository, commit))\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, sb);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, sb);\n \tstrbuf_addch(sb, '\\n');\n }\n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 8ab6d3a943..0758aed580 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -2521,7 +2521,7 @@ static void print_commit(char sign, struct commit *commit, int verbose,\n \t\t       repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev));\n \t} else {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &buf);\n \t\tfprintf(file, \"%c %s %s\\n\", sign,\n \t\t       repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev),\n \t\t       buf.buf);\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 7c944fe179..dff8185776 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -470,7 +470,7 @@ static void squash_message(struct commit *commit, struct commit_list *remotehead\n \t\tstrbuf_addch(&out, '\\n');\n \t\tstrbuf_addf(&out, \"commit %s\\n\",\n \t\t\toid_to_hex(&commit->object.oid));\n-\t\tpretty_print_commit(&ctx, commit, &out);\n+\t\tpretty_print_commit(the_repository, &ctx, commit, &out);\n \t}\n \twrite_file_buf(git_path_squash_msg(the_repository), out.buf, out.len);\n \tstrbuf_release(&out);\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex c48d9845f8..733f3fa905 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -141,7 +141,7 @@ static void print_new_head_line(struct commit *commit)\n \tprintf(_(\"HEAD is now at %s\"),\n \t\trepo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV));\n \n-\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);\n+\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &buf);\n \tif (buf.len > 0)\n \t\tprintf(\" %s\", buf.buf);\n \tputchar('\\n');\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex ddea8aa251..57c7b8d3ff 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -307,7 +307,7 @@ static void show_commit(struct commit *commit, void *data)\n \t\tctx.output_encoding = get_log_output_encoding();\n \t\tctx.color = revs->diffopt.use_color;\n \t\tctx.rev = revs;\n-\t\tpretty_print_commit(&ctx, commit, &buf);\n+\t\tpretty_print_commit(the_repository, &ctx, commit, &buf);\n \t\tif (buf.len) {\n \t\t\tif (revs->commit_format != CMIT_FMT_ONELINE)\n \t\t\t\tgraph_show_oneline(revs->graph);\ndiff --git a/builtin/shortlog.c b/builtin/shortlog.c\nindex d80bf1a7d0..109785fd00 100644\n--- a/builtin/shortlog.c\n+++ b/builtin/shortlog.c\n@@ -252,7 +252,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)\n \n \tif (!log->summary) {\n \t\tif (log->user_format)\n-\t\t\tpretty_print_commit(&ctx, commit, &oneline);\n+\t\t\tpretty_print_commit(the_repository, &ctx, commit, &oneline);\n \t\telse\n \t\t\trepo_format_commit_message(the_repository, commit,\n \t\t\t\t\t\t   \"%s\", &oneline, &ctx);\ndiff --git a/builtin/show-branch.c b/builtin/show-branch.c\nindex f02831b085..6bfe9e2e96 100644\n--- a/builtin/show-branch.c\n+++ b/builtin/show-branch.c\n@@ -310,7 +310,7 @@ static void show_one_commit(struct commit *commit, int no_name)\n \tstruct commit_name *name = commit_to_name(commit);\n \n \tif (commit->object.parsed) {\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty);\n+\t\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &pretty);\n \t\tpretty_str = pretty.buf;\n \t}\n \tskip_prefix(pretty_str, \"[PATCH] \", &pretty_str);\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex 785c1f9e5d..a522bb6de5 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -1480,7 +1480,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b\n \t\t\t\t\t\t  &head_commit->object.oid,\n \t\t\t\t\t\t  DEFAULT_ABBREV);\n \tstrbuf_addf(&msg, \"%s: %s \", branch_name, head_short_sha1);\n-\tpp_commit_easy(CMIT_FMT_ONELINE, head_commit, &msg);\n+\tpp_commit_easy(the_repository, CMIT_FMT_ONELINE, head_commit, &msg);\n \n \tstrbuf_addf(&commit_tree_label, \"index on %s\\n\", msg.buf);\n \tcommit_list_insert(head_commit, &parents);\ndiff --git a/bundle.c b/bundle.c\nindex 42327f9739..3bc2ed9ee9 100644\n--- a/bundle.c\n+++ b/bundle.c\n@@ -463,7 +463,7 @@ static void write_bundle_prerequisites(struct commit *commit, void *data)\n \tctx.fmt = CMIT_FMT_ONELINE;\n \tctx.output_encoding = get_log_output_encoding();\n \tstrbuf_reset(&buf);\n-\tpretty_print_commit(&ctx, commit, &buf);\n+\tpretty_print_commit(the_repository, &ctx, commit, &buf);\n \tstrbuf_trim(&buf);\n \n \tobject = (struct object *)commit;\ndiff --git a/log-tree.c b/log-tree.c\nindex 7e048701d0..fd2fb0bed6 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -885,7 +885,7 @@ void show_log(struct rev_info *opt)\n \t\tctx.from_ident = &opt->from_ident;\n \tif (opt->graph)\n \t\tctx.graph_width = graph_width(opt->graph);\n-\tpretty_print_commit(&ctx, commit, &msgbuf);\n+\tpretty_print_commit(opt->repo, &ctx, commit, &msgbuf);\n \n \tif (opt->add_signoff)\n \t\tappend_signoff(&msgbuf, 0, APPEND_SIGNOFF_DEDUP);\ndiff --git a/pretty.c b/pretty.c\nindex e0646bbc5d..51e3480431 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -2281,7 +2281,7 @@ void pp_remainder(struct pretty_print_context *pp,\n \t}\n }\n \n-void pretty_print_commit(struct pretty_print_context *pp,\n+void pretty_print_commit(struct repository *r, struct pretty_print_context *pp,\n \t\t\t const struct commit *commit,\n \t\t\t struct strbuf *sb)\n {\n@@ -2363,10 +2363,10 @@ void pretty_print_commit(struct pretty_print_context *pp,\n \trepo_unuse_commit_buffer(the_repository, commit, reencoded);\n }\n \n-void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,\n+void pp_commit_easy(struct repository *r, enum cmit_fmt fmt, const struct commit *commit,\n \t\t    struct strbuf *sb)\n {\n \tstruct pretty_print_context pp = {0};\n \tpp.fmt = fmt;\n-\tpretty_print_commit(&pp, commit, sb);\n+\tpretty_print_commit(r, &pp, commit, sb);\n }\ndiff --git a/pretty.h b/pretty.h\nindex fac699033e..13eb0189bd 100644\n--- a/pretty.h\n+++ b/pretty.h\n@@ -82,7 +82,7 @@ void userformat_find_requirements(const char *fmt, struct userformat_want *w);\n  * Shortcut for invoking pretty_print_commit if we do not have any context.\n  * Context would be set empty except \"fmt\".\n  */\n-void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,\n+void pp_commit_easy(struct repository *r, enum cmit_fmt fmt, const struct commit *commit,\n \t\t\tstruct strbuf *sb);\n \n /*\n@@ -132,7 +132,7 @@ void get_commit_format(const char *arg, struct rev_info *);\n  * and put it into \"sb\".\n  * Please use this function if you have a context (candidate for \"pp\").\n  */\n-void pretty_print_commit(struct pretty_print_context *pp,\n+void pretty_print_commit(struct repository *r, struct pretty_print_context *pp,\n \t\t\tconst struct commit *commit,\n \t\t\tstruct strbuf *sb);\n \ndiff --git a/range-diff.c b/range-diff.c\nindex 57edff40a8..31d38c2318 100644\n--- a/range-diff.c\n+++ b/range-diff.c\n@@ -460,7 +460,7 @@ static void output_pair_header(struct diff_options *diffopt,\n \t\t\tstrbuf_addf(buf, \"%s%s\", color_reset, color);\n \n \t\tstrbuf_addch(buf, ' ');\n-\t\tpp_commit_easy(CMIT_FMT_ONELINE, commit, buf);\n+\t\tpp_commit_easy(diffopt->repo, CMIT_FMT_ONELINE, commit, buf);\n \t}\n \tstrbuf_addf(buf, \"%s\\n\", color_reset);\n \ndiff --git a/sequencer.c b/sequencer.c\nindex 627020d65b..e6b3e05fce 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -5870,7 +5870,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,\n \t\t\tcontinue;\n \n \t\tstrbuf_reset(&oneline);\n-\t\tpretty_print_commit(pp, commit, &oneline);\n+\t\tpretty_print_commit(revs->repo, pp, commit, &oneline);\n \n \t\tto_merge = commit->parents ? commit->parents->next : NULL;\n \t\tif (!to_merge) {\n@@ -6012,7 +6012,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,\n \t\t\t\tstrbuf_addf(out, \"%s onto\\n\", cmd_reset);\n \t\t\telse {\n \t\t\t\tstrbuf_reset(&oneline);\n-\t\t\t\tpretty_print_commit(pp, commit, &oneline);\n+\t\t\t\tpretty_print_commit(revs->repo, pp, commit, &oneline);\n \t\t\t\tstrbuf_addf(out, \"%s %s %s\\n\",\n \t\t\t\t\t    cmd_reset, to, oneline.buf);\n \t\t\t}\n@@ -6124,7 +6124,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out,\n \t\t\tcontinue;\n \t\tstrbuf_addf(out, \"%s %s \", insn,\n \t\t\t    oid_to_hex(&commit->object.oid));\n-\t\tpretty_print_commit(&pp, commit, out);\n+\t\tpretty_print_commit(r, &pp, commit, out);\n \t\tif (is_empty)\n \t\t\tstrbuf_addf(out, \" %s empty\", comment_line_str);\n \t\tstrbuf_addch(out, '\\n');\n-- \n2.43.0\n\n"},{"id":"537501","messageId":"20260302085738.2510514-4-a3205153416@gmail.com","threadId":"65095","inReplyTo":"20260302085738.2510514-1-a3205153416@gmail.com","subject":"[PATCH v4 3/3] environment: migrate encoding configs to repo_config_values()","fromName":"Tian Yuchen","fromEmail":"a3205153416@gmail.com","sentAt":"2026-03-02T08:57:37Z","receivedAt":"2026-03-02T08:58:31Z","isPatch":true,"sender":{"key":"cat@malon.dev","avatar":"https://avatars.githubusercontent.com/u/232002048?v=4"},"body":"The global variables 'git_commit_encoding' and 'git_log_output_encoding'\nprevent libification.\n\nMigrate these variables into the 'struct repo_config_values'. This ensures\nthat they are safely accessed via the 'repo_config_values()' accessor which\nprevents uninitialized or cross-repository access.\n\nNote that these variables are not migrated to 'repo_settings'. As eagerly\nparsed user preferences, deferring them to lazy evaluation would break\nearly validation.\n\nCurrently, during the config parsing phase in 'git_default_i18n_config()',\nthe values are still parsed into the 'the_repository' instance of\n'repo_config_values', Since safely plumbing a repository pointer through\nthe 'git_default_config' callback machinery remains highly invasive due\nto custom contexts being passed via the 'void *cb' parameter.\nHowever, the read-paths (commit APIs and log formatters) updated in\nprevious patches are now fully plumbed to accept any repository\ninstance.\n\nSigned-off-by: Tian Yuchen <a3205153416@gmail.com>\n---\n builtin/am.c       |  4 ++--\n builtin/blame.c    |  2 +-\n builtin/commit.c   |  6 +++---\n builtin/log.c      |  2 +-\n builtin/mailinfo.c |  6 +++---\n builtin/rev-list.c |  2 +-\n builtin/shortlog.c |  2 +-\n bundle.c           |  2 +-\n commit.c           | 13 +++++++------\n environment.c      | 33 ++++++++++++++++++++-------------\n environment.h      | 10 +++++-----\n log-tree.c         |  4 ++--\n pretty.c           |  2 +-\n remote-curl.c      |  2 +-\n replay.c           |  2 +-\n repository.c       |  2 ++\n revision.c         | 12 +++++++-----\n sequencer.c        | 22 +++++++++++-----------\n submodule.c        |  2 +-\n 19 files changed, 71 insertions(+), 59 deletions(-)\n\ndiff --git a/builtin/am.c b/builtin/am.c\nindex 5296124f84..990b6c54e7 100644\n--- a/builtin/am.c\n+++ b/builtin/am.c\n@@ -1216,7 +1216,7 @@ static int parse_mail(struct am_state *state, const char *mail)\n \tsetup_mailinfo(the_repository, &mi);\n \n \tif (state->utf8)\n-\t\tmi.metainfo_charset = get_commit_output_encoding();\n+\t\tmi.metainfo_charset = get_commit_output_encoding(the_repository);\n \telse\n \t\tmi.metainfo_charset = NULL;\n \n@@ -1355,7 +1355,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit)\n \tstruct ident_split id;\n \n \tbuffer = repo_logmsg_reencode(the_repository, commit, NULL,\n-\t\t\t\t      get_commit_output_encoding());\n+\t\t\t\t      get_commit_output_encoding(the_repository));\n \n \tident_line = find_commit_header(buffer, \"author\", &ident_len);\n \tif (!ident_line)\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex eac2fe7320..0ad9f2c9f7 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -202,7 +202,7 @@ static void get_commit_info(struct commit *commit, struct commit_info *ret)\n \tconst char *subject, *encoding;\n \tconst char *message;\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = get_log_output_encoding(the_repository);\n \tmessage = repo_logmsg_reencode(the_repository, commit, NULL, encoding);\n \tget_ac_line(message, \"\\nauthor \",\n \t\t    &ret->author, &ret->author_mail,\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex d619fd2ace..caf5896d97 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -794,7 +794,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\t\tc = lookup_commit_reference_by_name(squash_message);\n \t\t\tif (!c)\n \t\t\t\tdie(_(\"could not lookup commit '%s'\"), squash_message);\n-\t\t\tctx.output_encoding = get_commit_output_encoding();\n+\t\t\tctx.output_encoding = get_commit_output_encoding(the_repository);\n \t\t\trepo_format_commit_message(the_repository, c,\n \t\t\t\t\t\t   \"squash! %s\\n\\n\", &sb,\n \t\t\t\t\t\t   &ctx);\n@@ -829,7 +829,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\tcommit = lookup_commit_reference_by_name(fixup_commit);\n \t\tif (!commit)\n \t\t\tdie(_(\"could not lookup commit '%s'\"), fixup_commit);\n-\t\tctx.output_encoding = get_commit_output_encoding();\n+\t\tctx.output_encoding = get_commit_output_encoding(the_repository);\n \t\tfmt = xstrfmt(\"%s! %%s\\n\\n\", fixup_prefix);\n \t\trepo_format_commit_message(the_repository, commit, fmt, &sb,\n \t\t\t\t\t   &ctx);\n@@ -1235,7 +1235,7 @@ static const char *read_commit_message(const char *name)\n \tcommit = lookup_commit_reference_by_name(name);\n \tif (!commit)\n \t\tdie(_(\"could not lookup commit '%s'\"), name);\n-\tout_enc = get_commit_output_encoding();\n+\tout_enc = get_commit_output_encoding(the_repository);\n \treturn repo_logmsg_reencode(the_repository, commit, NULL, out_enc);\n }\n \ndiff --git a/builtin/log.c b/builtin/log.c\nindex 0758aed580..8edb3c54e7 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -568,7 +568,7 @@ static void show_tagger(const char *buf, struct rev_info *rev)\n \n \tpp.fmt = rev->commit_format;\n \tpp.date_mode = rev->date_mode;\n-\tpp_user_info(&pp, \"Tagger\", &out, buf, get_log_output_encoding());\n+\tpp_user_info(&pp, \"Tagger\", &out, buf, get_log_output_encoding(the_repository));\n \tfprintf(rev->diffopt.file, \"%s\", out.buf);\n \tstrbuf_release(&out);\n }\ndiff --git a/builtin/mailinfo.c b/builtin/mailinfo.c\nindex 8de7ba7de1..4f17cf1598 100644\n--- a/builtin/mailinfo.c\n+++ b/builtin/mailinfo.c\n@@ -52,7 +52,7 @@ static int parse_opt_quoted_cr(const struct option *opt, const char *arg, int un\n int cmd_mailinfo(int argc,\n \t\t const char **argv,\n \t\t const char *prefix,\n-\t\t struct repository *repo UNUSED)\n+\t\t struct repository *repo)\n {\n \tstruct metainfo_charset meta_charset;\n \tstruct mailinfo mi;\n@@ -83,7 +83,7 @@ int cmd_mailinfo(int argc,\n \t\tOPT_END()\n \t};\n \n-\tsetup_mailinfo(the_repository, &mi);\n+\tsetup_mailinfo(repo, &mi);\n \tmeta_charset.policy = CHARSET_DEFAULT;\n \n \targc = parse_options(argc, argv, prefix, options, mailinfo_usage, 0);\n@@ -93,7 +93,7 @@ int cmd_mailinfo(int argc,\n \n \tswitch (meta_charset.policy) {\n \tcase CHARSET_DEFAULT:\n-\t\tmi.metainfo_charset = get_commit_output_encoding();\n+\t\tmi.metainfo_charset = get_commit_output_encoding(repo);\n \t\tbreak;\n \tcase CHARSET_NO_REENCODE:\n \t\tmi.metainfo_charset = NULL;\ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex 57c7b8d3ff..3732edae8b 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -304,7 +304,7 @@ static void show_commit(struct commit *commit, void *data)\n \t\tctx.date_mode = revs->date_mode;\n \t\tctx.date_mode_explicit = revs->date_mode_explicit;\n \t\tctx.fmt = revs->commit_format;\n-\t\tctx.output_encoding = get_log_output_encoding();\n+\t\tctx.output_encoding = get_log_output_encoding(the_repository);\n \t\tctx.color = revs->diffopt.use_color;\n \t\tctx.rev = revs;\n \t\tpretty_print_commit(the_repository, &ctx, commit, &buf);\ndiff --git a/builtin/shortlog.c b/builtin/shortlog.c\nindex 109785fd00..79606e57be 100644\n--- a/builtin/shortlog.c\n+++ b/builtin/shortlog.c\n@@ -248,7 +248,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)\n \tctx.fmt = CMIT_FMT_USERFORMAT;\n \tctx.abbrev = log->abbrev;\n \tctx.date_mode = log->date_mode;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = get_log_output_encoding(the_repository);\n \n \tif (!log->summary) {\n \t\tif (log->user_format)\ndiff --git a/bundle.c b/bundle.c\nindex 3bc2ed9ee9..3b98cdd6fd 100644\n--- a/bundle.c\n+++ b/bundle.c\n@@ -461,7 +461,7 @@ static void write_bundle_prerequisites(struct commit *commit, void *data)\n \twrite_or_die(bpi->fd, buf.buf, buf.len);\n \n \tctx.fmt = CMIT_FMT_ONELINE;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = get_log_output_encoding(the_repository);\n \tstrbuf_reset(&buf);\n \tpretty_print_commit(the_repository, &ctx, commit, &buf);\n \tstrbuf_trim(&buf);\ndiff --git a/commit.c b/commit.c\nindex 71a2b7bbe5..cb8ec675d1 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1663,7 +1663,8 @@ N_(\"Warning: commit message did not conform to UTF-8.\\n\"\n    \"You may want to amend it after fixing the message, or set the config\\n\"\n    \"variable i18n.commitEncoding to the encoding your project uses.\\n\");\n \n-static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg_len,\n+static void write_commit_tree(struct repository *r, struct strbuf *buffer,\n+\t\t\t      const char *msg, size_t msg_len,\n \t\t\t      const struct object_id *tree,\n \t\t\t      const struct object_id *parents, size_t parents_len,\n \t\t\t      const char *author, const char *committer,\n@@ -1673,7 +1674,7 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \tsize_t i;\n \n \t/* Not having i18n.commitencoding is the same as having utf-8 */\n-\tencoding_is_utf8 = is_encoding_utf8(git_commit_encoding);\n+\tencoding_is_utf8 = is_encoding_utf8(get_commit_output_encoding(r));\n \n \tstrbuf_grow(buffer, 8192); /* should avoid reallocs for the headers */\n \tstrbuf_addf(buffer, \"tree %s\\n\", oid_to_hex(tree));\n@@ -1694,7 +1695,7 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg\n \t\tcommitter = git_committer_info(IDENT_STRICT);\n \tstrbuf_addf(buffer, \"committer %s\\n\", committer);\n \tif (!encoding_is_utf8)\n-\t\tstrbuf_addf(buffer, \"encoding %s\\n\", git_commit_encoding);\n+\t\tstrbuf_addf(buffer, \"encoding %s\\n\", get_commit_output_encoding(r));\n \n \twhile (extra) {\n \t\tadd_extra_header(buffer, extra);\n@@ -1722,7 +1723,7 @@ int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len,\n \tsize_t i, nparents;\n \n \t/* Not having i18n.commitencoding is the same as having utf-8 */\n-\tencoding_is_utf8 = is_encoding_utf8(git_commit_encoding);\n+\tencoding_is_utf8 = is_encoding_utf8(get_commit_output_encoding(r));\n \n \todb_assert_oid_type(the_repository->objects, tree, OBJ_TREE);\n \n@@ -1735,7 +1736,7 @@ int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len,\n \tfor (const struct commit_list *p = parents; p; p = p->next)\n \t\toidcpy(&parent_buf[i++], &p->item->object.oid);\n \n-\twrite_commit_tree(&buffer, msg, msg_len, tree, parent_buf, nparents, author, committer, extra);\n+\twrite_commit_tree(r, &buffer, msg, msg_len, tree, parent_buf, nparents, author, committer, extra);\n \tif (sign_commit && sign_commit_to_strbuf(&sig, &buffer, sign_commit)) {\n \t\tresult = -1;\n \t\tgoto out;\n@@ -1763,7 +1764,7 @@ int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len,\n \t\t\tfree(mapped_parents);\n \t\t\tgoto out;\n \t\t}\n-\t\twrite_commit_tree(&compat_buffer, msg, msg_len, &mapped_tree,\n+\t\twrite_commit_tree(r, &compat_buffer, msg, msg_len, &mapped_tree,\n \t\t\t\t  mapped_parents, nparents, author, committer, compat_extra);\n \t\tfree_commit_extra_headers(compat_extra);\n \t\tfree(mapped_parents);\ndiff --git a/environment.c b/environment.c\nindex 3ee88e20ff..948e22ec26 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -50,8 +50,6 @@ int ignore_case;\n int assume_unchanged;\n int is_bare_repository_cfg = -1; /* unspecified */\n int warn_on_object_refname_ambiguity = 1;\n-char *git_commit_encoding;\n-char *git_log_output_encoding;\n char *apply_default_whitespace;\n char *apply_default_ignorewhitespace;\n int zlib_compression_level = Z_BEST_SPEED;\n@@ -194,15 +192,22 @@ const char *strip_namespace(const char *namespaced_ref)\n \treturn NULL;\n }\n \n-const char *get_log_output_encoding(void)\n+const char *get_log_output_encoding(struct repository *r)\n {\n-\treturn git_log_output_encoding ? git_log_output_encoding\n-\t\t: get_commit_output_encoding();\n+\tstruct repo_config_values *cfg;\n+\tif (r != the_repository)\n+\t\treturn get_commit_output_encoding(r);\n+\tcfg = repo_config_values(r);\n+\treturn cfg->log_output_encoding ? cfg->log_output_encoding : get_commit_output_encoding(r);\n }\n \n-const char *get_commit_output_encoding(void)\n+const char *get_commit_output_encoding(struct repository *r)\n {\n-\treturn git_commit_encoding ? git_commit_encoding : \"UTF-8\";\n+\tstruct repo_config_values *cfg;\n+\tif (r != the_repository)\t\n+\t\treturn \"UTF-8\";\n+\tcfg= repo_config_values(r);\n+\treturn cfg->commit_encoding ? cfg->commit_encoding : \"UTF-8\";\n }\n \n int use_optional_locks(void)\n@@ -567,17 +572,17 @@ static int git_default_sparse_config(const char *var, const char *value)\n \n static int git_default_i18n_config(const char *var, const char *value)\n {\n+\tstruct repo_config_values *cfg = repo_config_values(the_repository);\n+\n \tif (!strcmp(var, \"i18n.commitencoding\")) {\n-\t\tFREE_AND_NULL(git_commit_encoding);\n-\t\treturn git_config_string(&git_commit_encoding, var, value);\n+\t\tFREE_AND_NULL(cfg->commit_encoding);\n+\t\treturn git_config_string(&cfg->commit_encoding, var, value);\n \t}\n-\n \tif (!strcmp(var, \"i18n.logoutputencoding\")) {\n-\t\tFREE_AND_NULL(git_log_output_encoding);\n-\t\treturn git_config_string(&git_log_output_encoding, var, value);\n+\t\tFREE_AND_NULL(cfg->log_output_encoding);\n+\t\treturn git_config_string(&cfg->log_output_encoding, var, value);\n \t}\n \n-\t/* Add other config variables here and to Documentation/config.adoc. */\n \treturn 0;\n }\n \n@@ -738,6 +743,8 @@ int git_default_config(const char *var, const char *value,\n void repo_config_values_init(struct repo_config_values *cfg)\n {\n \tcfg->attributes_file = NULL;\n+\tcfg->commit_encoding = NULL;\n+\tcfg->log_output_encoding = NULL;\n \tcfg->apply_sparse_checkout = 0;\n \tcfg->branch_track = BRANCH_TRACK_REMOTE;\n }\ndiff --git a/environment.h b/environment.h\nindex 8c221b567b..358c7d05e0 100644\n--- a/environment.h\n+++ b/environment.h\n@@ -93,6 +93,9 @@ struct repo_config_values {\n \n \t/* section \"branch\" config values */\n \tenum branch_track branch_track;\n+\n+\tchar *commit_encoding;\n+\tchar *log_output_encoding;\n };\n \n struct repo_config_values *repo_config_values(struct repository *repo);\n@@ -206,11 +209,8 @@ extern enum object_creation_mode object_creation_mode;\n \n extern int grafts_keep_true_parents;\n \n-const char *get_log_output_encoding(void);\n-const char *get_commit_output_encoding(void);\n-\n-extern char *git_commit_encoding;\n-extern char *git_log_output_encoding;\n+const char *get_log_output_encoding(struct repository *r);\n+const char *get_commit_output_encoding(struct repository *r);\n \n extern char *editor_program;\n extern char *askpass_program;\ndiff --git a/log-tree.c b/log-tree.c\nindex fd2fb0bed6..364fd015f5 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -859,7 +859,7 @@ void show_log(struct rev_info *opt)\n \n \t\traw = (opt->commit_format == CMIT_FMT_USERFORMAT);\n \t\tformat_display_notes(&commit->object.oid, &notebuf,\n-\t\t\t\t     get_log_output_encoding(), raw);\n+\t\t\t\t     get_log_output_encoding(opt->repo), raw);\n \t\tctx.notes_message = strbuf_detach(&notebuf, NULL);\n \t}\n \n@@ -879,7 +879,7 @@ void show_log(struct rev_info *opt)\n \tctx.mailmap = opt->mailmap;\n \tctx.color = opt->diffopt.use_color;\n \tctx.expand_tabs_in_log = opt->expand_tabs_in_log;\n-\tctx.output_encoding = get_log_output_encoding();\n+\tctx.output_encoding = get_log_output_encoding(opt->repo);\n \tctx.rev = opt;\n \tif (opt->from_ident.mail_begin && opt->from_ident.name_begin)\n \t\tctx.from_ident = &opt->from_ident;\ndiff --git a/pretty.c b/pretty.c\nindex 51e3480431..6b585e2763 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -2298,7 +2298,7 @@ void pretty_print_commit(struct repository *r, struct pretty_print_context *pp,\n \t\treturn;\n \t}\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = get_log_output_encoding(r);\n \tmsg = reencoded = repo_logmsg_reencode(the_repository, commit, NULL,\n \t\t\t\t\t       encoding);\n \ndiff --git a/remote-curl.c b/remote-curl.c\nindex 92e40bb682..146cb8930d 100644\n--- a/remote-curl.c\n+++ b/remote-curl.c\n@@ -379,7 +379,7 @@ static int show_http_message(struct strbuf *type, struct strbuf *charset,\n \tif (strcmp(type->buf, \"text/plain\"))\n \t\treturn -1;\n \tif (charset->len)\n-\t\tstrbuf_reencode(msg, charset->buf, get_log_output_encoding());\n+\t\tstrbuf_reencode(msg, charset->buf, get_log_output_encoding(the_repository));\n \n \tstrbuf_trim(msg);\n \tif (!msg->len)\ndiff --git a/replay.c b/replay.c\nindex 8704547aa1..0012d3aa18 100644\n--- a/replay.c\n+++ b/replay.c\n@@ -56,7 +56,7 @@ static struct commit *create_commit(struct repository *repo,\n \tchar *sign_commit = NULL; /* FIXME: cli users might want to sign again */\n \tstruct commit_extra_header *extra = NULL;\n \tstruct strbuf msg = STRBUF_INIT;\n-\tconst char *out_enc = get_commit_output_encoding();\n+\tconst char *out_enc = get_commit_output_encoding(repo);\n \tconst char *message = repo_logmsg_reencode(repo, based_on,\n \t\t\t\t\t\t   NULL, out_enc);\n \tconst char *orig_message = NULL;\ndiff --git a/repository.c b/repository.c\nindex 0207bcb299..3202d67bf0 100644\n--- a/repository.c\n+++ b/repository.c\n@@ -384,6 +384,8 @@ void repo_clear(struct repository *repo)\n \tFREE_AND_NULL(repo->index_file);\n \tFREE_AND_NULL(repo->worktree);\n \tFREE_AND_NULL(repo->submodule_prefix);\n+\tFREE_AND_NULL(repo->config_values_private_.commit_encoding);\n+\tFREE_AND_NULL(repo->config_values_private_.log_output_encoding);\n \n \todb_free(repo->objects);\n \trepo->objects = NULL;\ndiff --git a/revision.c b/revision.c\nindex 29972c3a19..5fb85c0f13 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -2675,11 +2675,13 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t} else if (!strcmp(arg, \"--invert-grep\")) {\n \t\trevs->grep_filter.no_body_match = 1;\n \t} else if ((argcount = parse_long_opt(\"encoding\", argv, &optarg))) {\n-\t\tfree(git_log_output_encoding);\n+\t\tstruct repo_config_values *cfg = repo_config_values(revs->repo);\n+\n+\t\tfree(cfg->log_output_encoding);\n \t\tif (strcmp(optarg, \"none\"))\n-\t\t\tgit_log_output_encoding = xstrdup(optarg);\n+\t\t\tcfg->log_output_encoding = xstrdup(optarg);\n \t\telse\n-\t\t\tgit_log_output_encoding = xstrdup(\"\");\n+\t\t\tcfg->log_output_encoding = xstrdup(\"\");\n \t\treturn argcount;\n \t} else if (!strcmp(arg, \"--reverse\")) {\n \t\trevs->reverse ^= 1;\n@@ -3129,7 +3131,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \n \tdiff_setup_done(&revs->diffopt);\n \n-\tif (!is_encoding_utf8(get_log_output_encoding()))\n+\tif (!is_encoding_utf8(get_log_output_encoding(revs->repo)))\n \t\trevs->grep_filter.ignore_locale = 1;\n \tcompile_grep_patterns(&revs->grep_filter);\n \n@@ -4063,7 +4065,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)\n \t * so we will not end up with a buffer that has two different encodings\n \t * in it.\n \t */\n-\tencoding = get_log_output_encoding();\n+\tencoding = get_log_output_encoding(opt->repo);\n \tmessage = repo_logmsg_reencode(the_repository, commit, NULL, encoding);\n \n \t/* Copy the commit to temporary if we are using \"fake\" headers */\ndiff --git a/sequencer.c b/sequencer.c\nindex e6b3e05fce..62717910d2 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -480,13 +480,13 @@ static const char *short_commit_name(struct repository *r, struct commit *commit\n \treturn repo_find_unique_abbrev(r, &commit->object.oid, DEFAULT_ABBREV);\n }\n \n-static int get_message(struct commit *commit, struct commit_message *out)\n+static int get_message(struct repository *r, struct commit *commit, struct commit_message *out)\n {\n \tconst char *abbrev, *subject;\n \tint subject_len;\n \n \tout->message = repo_logmsg_reencode(the_repository, commit, NULL,\n-\t\t\t\t\t    get_commit_output_encoding());\n+\t\t\t\t\t    get_commit_output_encoding(r));\n \tabbrev = short_commit_name(the_repository, commit);\n \n \tsubject_len = find_commit_subject(out->message, &subject);\n@@ -1539,7 +1539,7 @@ static int try_to_commit(struct repository *r,\n \n \tif (flags & AMEND_MSG) {\n \t\tconst char *exclude_gpgsig[] = { \"gpgsig\", \"gpgsig-sha256\", NULL };\n-\t\tconst char *out_enc = get_commit_output_encoding();\n+\t\tconst char *out_enc = get_commit_output_encoding(r);\n \t\tconst char *message = repo_logmsg_reencode(r, current_head,\n \t\t\t\t\t\t\t   NULL, out_enc);\n \n@@ -2054,7 +2054,7 @@ static int update_squash_messages(struct repository *r,\n \tstruct strbuf buf = STRBUF_INIT;\n \tint res = 0;\n \tconst char *message, *body;\n-\tconst char *encoding = get_commit_output_encoding();\n+\tconst char *encoding = get_commit_output_encoding(r);\n \n \tif (!is_fixup(command))\n \t\tBUG(\"not a FIXUP or SQUASH %d\", command);\n@@ -2324,7 +2324,7 @@ static int do_pick_commit(struct repository *r,\n \telse\n \t\tparent = commit->parents->item;\n \n-\tif (get_message(commit, &msg) != 0)\n+\tif (get_message(r, commit, &msg) != 0)\n \t\treturn error(_(\"cannot get commit message for %s\"),\n \t\t\toid_to_hex(&commit->object.oid));\n \n@@ -3344,7 +3344,7 @@ static int walk_revs_populate_todo(struct todo_list *todo_list,\n \tif (prepare_revs(opts))\n \t\treturn -1;\n \n-\tencoding = get_log_output_encoding();\n+\tencoding = get_log_output_encoding(the_repository);\n \n \twhile ((commit = get_revision(opts->revs))) {\n \t\tstruct todo_item *item = append_new_todo(todo_list);\n@@ -3730,7 +3730,7 @@ static int make_patch(struct repository *r,\n \t}\n \n \tif (!file_exists(rebase_path_message())) {\n-\t\tconst char *encoding = get_commit_output_encoding();\n+\t\tconst char *encoding = get_commit_output_encoding(r);\n \t\tconst char *commit_buffer = repo_logmsg_reencode(r,\n \t\t\t\t\t\t\t\t commit, NULL,\n \t\t\t\t\t\t\t\t encoding);\n@@ -4187,7 +4187,7 @@ static int do_merge(struct repository *r,\n \t}\n \n \tif (commit) {\n-\t\tconst char *encoding = get_commit_output_encoding();\n+\t\tconst char *encoding = get_commit_output_encoding(r);\n \t\tconst char *message = repo_logmsg_reencode(r, commit, NULL,\n \t\t\t\t\t\t\t   encoding);\n \t\tconst char *body;\n@@ -4831,7 +4831,7 @@ static int stopped_at_head(struct repository *r)\n \n \tif (repo_get_oid(r, \"HEAD\", &head) ||\n \t    !(commit = lookup_commit(r, &head)) ||\n-\t    repo_parse_commit(r, commit) || get_message(commit, &message))\n+\t    repo_parse_commit(r, commit) || get_message(r, commit, &message))\n \t\tfprintf(stderr, _(\"Stopped at HEAD\\n\"));\n \telse {\n \t\tfprintf(stderr, _(\"Stopped at %s\\n\"), message.label);\n@@ -5311,7 +5311,7 @@ static int commit_staged_changes(struct repository *r,\n \t\t\t\tstruct commit *commit;\n \t\t\t\tconst char *msg;\n \t\t\t\tconst char *path = rebase_path_squash_msg();\n-\t\t\t\tconst char *encoding = get_commit_output_encoding();\n+\t\t\t\tconst char *encoding = get_commit_output_encoding(r);\n \n \t\t\t\tif (parse_head(r, &commit)) {\n \t\t\t\t\tret = error(_(\"could not parse HEAD\"));\n@@ -6092,7 +6092,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out,\n \tget_commit_format(format, &revs);\n \tfree(format);\n \tpp.fmt = revs.commit_format;\n-\tpp.output_encoding = get_log_output_encoding();\n+\tpp.output_encoding = get_log_output_encoding(r);\n \n \tsetup_revisions_from_strvec(argv, &revs, NULL);\n \tif (argv->nr > 1) {\ndiff --git a/submodule.c b/submodule.c\nindex 508938e4da..a58ed3652c 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -479,7 +479,7 @@ static void print_submodule_diff_summary(struct repository *r, struct rev_info *\n \twhile ((commit = get_revision(rev))) {\n \t\tstruct pretty_print_context ctx = {0};\n \t\tctx.date_mode = rev->date_mode;\n-\t\tctx.output_encoding = get_log_output_encoding();\n+\t\tctx.output_encoding = get_log_output_encoding(r);\n \t\tstrbuf_setlen(&sb, 0);\n \t\trepo_format_commit_message(r, commit, format, &sb,\n \t\t\t\t      &ctx);\n-- \n2.43.0\n\n"}]}