From d7c4f751c745fa800e3c5b006af7a4b6ffb56ec0 Mon Sep 17 00:00:00 2001 From: Tian Yuchen Date: Mon, 2 Mar 2026 02:35:36 +0800 Subject: [PATCH 1/3] commit: plumb 'struct repository' into commit creation APIs To pave the way for reducing the global state tied to commit encoding in a subsequent patch, functions like 'commit_tree()' and 'commit_tree_extended()' must be able to access a repository instance. Plumb the 'struct repository' pointer down the call chain for these APIs. For built-ins or subsystems already dependent on global state (e.g., 'notes_cache_write()'), fallback to 'the_repository'. No functional changes are introduced in this preparatory step. Signed-off-by: Tian Yuchen --- builtin/am.c | 2 +- builtin/commit-tree.c | 2 +- builtin/commit.c | 2 +- builtin/history.c | 2 +- builtin/merge.c | 4 ++-- builtin/rebase.c | 2 +- builtin/stash.c | 10 +++++----- commit.c | 7 +++---- commit.h | 4 ++-- notes-cache.c | 2 +- notes-utils.c | 2 +- replay.c | 2 +- sequencer.c | 4 ++-- 13 files changed, 22 insertions(+), 23 deletions(-) diff --git a/builtin/am.c b/builtin/am.c index e0c767e223dbce..5296124f84cfb1 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -1699,7 +1699,7 @@ static void do_commit(const struct am_state *state) : state->author_date, IDENT_STRICT); - if (commit_tree_extended(state->msg, state->msg_len, &tree, parents, + if (commit_tree_extended(the_repository, state->msg, state->msg_len, &tree, parents, &commit, author, committer, state->sign_commit, NULL)) die(_("failed to write commit object")); diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index 30535db131eaa6..c489749588407c 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -144,7 +144,7 @@ int cmd_commit_tree(int argc, die_errno(_("git commit-tree: failed to read")); } - if (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid, + if (commit_tree(the_repository, buffer.buf, buffer.len, &tree_oid, parents, &commit_oid, NULL, sign_commit)) { ret = 1; goto out; diff --git a/builtin/commit.c b/builtin/commit.c index 9e3a09d532bfce..d619fd2acedc17 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1931,7 +1931,7 @@ int cmd_commit(int argc, append_merge_tag_headers(parents, &tail); } - if (commit_tree_extended(sb.buf, sb.len, &the_repository->index->cache_tree->oid, + if (commit_tree_extended(the_repository, sb.buf, sb.len, &the_repository->index->cache_tree->oid, parents, &oid, author_ident.buf, NULL, sign_commit, extra)) { rollback_index_files(); diff --git a/builtin/history.c b/builtin/history.c index 8dcb9a604665f8..3d83ac021b5493 100644 --- a/builtin/history.c +++ b/builtin/history.c @@ -136,7 +136,7 @@ static int commit_tree_with_edited_message(struct repository *repo, original_extra_headers = read_commit_extra_headers(original, exclude_gpgsig); - ret = commit_tree_extended(commit_message.buf, commit_message.len, &original_tree_oid, + ret = commit_tree_extended(repo, commit_message.buf, commit_message.len, &original_tree_oid, original->parents, &rewritten_commit_oid, original_author, NULL, NULL, original_extra_headers); if (ret < 0) diff --git a/builtin/merge.c b/builtin/merge.c index 4e456a381c192d..7c944fe179df86 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -1000,7 +1000,7 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads) pptr = commit_list_append(head, pptr); pptr = commit_list_append(remoteheads->item, pptr); prepare_to_commit(remoteheads); - if (commit_tree(merge_msg.buf, merge_msg.len, &result_tree, parents, + if (commit_tree(the_repository, merge_msg.buf, merge_msg.len, &result_tree, parents, &result_commit, NULL, sign_commit)) die(_("failed to write commit object")); finish(head, remoteheads, &result_commit, "In-index merge"); @@ -1027,7 +1027,7 @@ static int finish_automerge(struct commit *head, if (!head_subsumed || fast_forward == FF_NO) commit_list_insert(head, &parents); prepare_to_commit(remoteheads); - if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents, + if (commit_tree(the_repository, merge_msg.buf, merge_msg.len, result_tree, parents, &result_commit, NULL, sign_commit)) die(_("failed to write commit object")); strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy); diff --git a/builtin/rebase.c b/builtin/rebase.c index c487e1090779c2..7b9ab85cc059ca 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -1647,7 +1647,7 @@ int cmd_rebase(int argc, options.upstream_arg = options.upstream_name; } else { if (!options.onto_name) { - if (commit_tree("", 0, the_hash_algo->empty_tree, NULL, + if (commit_tree(the_repository, "", 0, the_hash_algo->empty_tree, NULL, &squash_onto, NULL, NULL) < 0) die(_("Could not create new root commit")); options.squash_onto = &squash_onto; diff --git a/builtin/stash.c b/builtin/stash.c index f06cfa79894cae..785c1f9e5d5f38 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -1258,7 +1258,7 @@ static int save_untracked_files(struct stash_info *info, struct strbuf *msg, goto done; } - if (commit_tree(untracked_msg.buf, untracked_msg.len, + if (commit_tree(the_repository, untracked_msg.buf, untracked_msg.len, &info->u_tree, NULL, &info->u_commit, NULL, NULL)) { ret = -1; goto done; @@ -1486,7 +1486,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b commit_list_insert(head_commit, &parents); if (write_index_as_tree(&info->i_tree, the_repository->index, repo_get_index_file(the_repository), 0, NULL) || - commit_tree(commit_tree_label.buf, commit_tree_label.len, + commit_tree(the_repository, commit_tree_label.buf, commit_tree_label.len, &info->i_tree, parents, &info->i_commit, NULL, NULL)) { if (!quiet) fprintf_ln(stderr, _("Cannot save the current " @@ -1551,7 +1551,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b &parents); commit_list_insert(head_commit, &parents); - if (commit_tree(stash_msg_buf->buf, stash_msg_buf->len, &info->w_tree, + if (commit_tree(the_repository, stash_msg_buf->buf, stash_msg_buf->len, &info->w_tree, parents, &info->w_commit, NULL, NULL)) { if (!quiet) fprintf_ln(stderr, _("Cannot record " @@ -2035,7 +2035,7 @@ static int write_commit_with_parents(struct repository *r, author = xmemdupz(orig_author, author_len); committer = xmemdupz(orig_committer, committer_len); - if (commit_tree_extended(msg.buf, msg.len, + if (commit_tree_extended(r, msg.buf, msg.len, r->hash_algo->empty_tree, parents, out, author, committer, NULL, NULL)) { @@ -2258,7 +2258,7 @@ static int do_export_stash(struct repository *r, "2001-09-17T00:00:00Z", 0); /* First, we create a single empty commit. */ - if (commit_tree_extended("", 0, r->hash_algo->empty_tree, NULL, + if (commit_tree_extended(the_repository, "", 0, r->hash_algo->empty_tree, NULL, &base, author, committer, NULL, NULL)) return error(_("unable to write base commit")); diff --git a/commit.c b/commit.c index d16ae7334510e0..71a2b7bbe5f6b7 100644 --- a/commit.c +++ b/commit.c @@ -1534,7 +1534,7 @@ void free_commit_extra_headers(struct commit_extra_header *extra) } } -int commit_tree(const char *msg, size_t msg_len, const struct object_id *tree, +int commit_tree(struct repository *r, const char *msg, size_t msg_len, const struct object_id *tree, const struct commit_list *parents, struct object_id *ret, const char *author, const char *sign_commit) { @@ -1542,7 +1542,7 @@ int commit_tree(const char *msg, size_t msg_len, const struct object_id *tree, int result; append_merge_tag_headers(parents, &tail); - result = commit_tree_extended(msg, msg_len, tree, parents, ret, author, + result = commit_tree_extended(r, msg, msg_len, tree, parents, ret, author, NULL, sign_commit, extra); free_commit_extra_headers(extra); return result; @@ -1706,14 +1706,13 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg strbuf_add(buffer, msg, msg_len); } -int commit_tree_extended(const char *msg, size_t msg_len, +int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len, const struct object_id *tree, const struct commit_list *parents, struct object_id *ret, const char *author, const char *committer, const char *sign_commit, const struct commit_extra_header *extra) { - struct repository *r = the_repository; int result = 0; int encoding_is_utf8; struct strbuf buffer = STRBUF_INIT, compat_buffer = STRBUF_INIT; diff --git a/commit.h b/commit.h index 1635de418b59e0..d3d664d0ffdc14 100644 --- a/commit.h +++ b/commit.h @@ -289,12 +289,12 @@ struct commit_extra_header { void append_merge_tag_headers(const struct commit_list *parents, struct commit_extra_header ***tail); -int commit_tree(const char *msg, size_t msg_len, +int commit_tree(struct repository *r, const char *msg, size_t msg_len, const struct object_id *tree, const struct commit_list *parents, struct object_id *ret, const char *author, const char *sign_commit); -int commit_tree_extended(const char *msg, size_t msg_len, +int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len, const struct object_id *tree, const struct commit_list *parents, struct object_id *ret, const char *author, const char *committer, diff --git a/notes-cache.c b/notes-cache.c index bf5bb1f6c13a13..5dbbd94ea31223 100644 --- a/notes-cache.c +++ b/notes-cache.c @@ -66,7 +66,7 @@ int notes_cache_write(struct notes_cache *c) if (write_notes_tree(&c->tree, &tree_oid)) return -1; - if (commit_tree(c->validity, strlen(c->validity), &tree_oid, NULL, + if (commit_tree(the_repository, c->validity, strlen(c->validity), &tree_oid, NULL, &commit_oid, NULL, NULL) < 0) return -1; if (refs_update_ref(get_main_ref_store(the_repository), "update notes cache", c->tree.update_ref, &commit_oid, diff --git a/notes-utils.c b/notes-utils.c index 5c1c75d5b8099a..4671a119939eb3 100644 --- a/notes-utils.c +++ b/notes-utils.c @@ -36,7 +36,7 @@ void create_notes_commit(struct repository *r, /* else: t->ref points to nothing, assume root/orphan commit */ } - if (commit_tree(msg, msg_len, &tree_oid, parents, result_oid, NULL, + if (commit_tree(r, msg, msg_len, &tree_oid, parents, result_oid, NULL, NULL)) die("Failed to commit notes tree to database"); diff --git a/replay.c b/replay.c index f97d652f338f1d..8704547aa1d0aa 100644 --- a/replay.c +++ b/replay.c @@ -68,7 +68,7 @@ static struct commit *create_commit(struct repository *repo, strbuf_addstr(&msg, orig_message); author = get_author(message); reset_ident_date(); - if (commit_tree_extended(msg.buf, msg.len, &tree->object.oid, parents, + if (commit_tree_extended(repo, msg.buf, msg.len, &tree->object.oid, parents, &ret, author, NULL, sign_commit, extra)) { error(_("failed to write commit object")); goto out; diff --git a/sequencer.c b/sequencer.c index a3eb39bb25248a..627020d65bb48f 100644 --- a/sequencer.c +++ b/sequencer.c @@ -1672,7 +1672,7 @@ static int try_to_commit(struct repository *r, free(email); } - if (commit_tree_extended(msg->buf, msg->len, &tree, parents, oid, + if (commit_tree_extended(r, msg->buf, msg->len, &tree, parents, oid, author, committer, opts->gpg_sign, extra)) { res = error(_("failed to write commit object")); goto out; @@ -3989,7 +3989,7 @@ static int do_reset(struct repository *r, if (len == 10 && !strncmp("[new root]", name, len)) { if (!opts->have_squash_onto) { const char *hex; - if (commit_tree("", 0, the_hash_algo->empty_tree, + if (commit_tree(r, "", 0, the_hash_algo->empty_tree, NULL, &opts->squash_onto, NULL, NULL)) return error(_("writing fake root commit")); From b5f033574b08748a0957d0eb76592c30d5f67ca1 Mon Sep 17 00:00:00 2001 From: Tian Yuchen Date: Mon, 2 Mar 2026 02:52:45 +0800 Subject: [PATCH 2/3] pretty: plumb 'struct repository' into pretty-print APIs To prepare for the elimination of the global state associated with 'log_output_encoding', functions responsible for formatting commit messages, such as 'pretty_print_commit()' and 'pp_commit_easy()', must be able to access a repository instance. Plumb the 'struct repository' pointer down the call chain for these APIs. Where no such context is readily available in built-ins or high-level functions, fallback to 'the_repository'. Signed-off-by: Tian Yuchen --- builtin/checkout.c | 4 ++-- builtin/log.c | 2 +- builtin/merge.c | 2 +- builtin/reset.c | 2 +- builtin/rev-list.c | 2 +- builtin/shortlog.c | 2 +- builtin/show-branch.c | 2 +- builtin/stash.c | 2 +- bundle.c | 2 +- log-tree.c | 2 +- pretty.c | 6 +++--- pretty.h | 4 ++-- range-diff.c | 2 +- sequencer.c | 6 +++--- 14 files changed, 20 insertions(+), 20 deletions(-) diff --git a/builtin/checkout.c b/builtin/checkout.c index f7b313816e7708..64c5c9ed1a979a 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -689,7 +689,7 @@ static void describe_detached_head(const char *msg, struct commit *commit) struct strbuf sb = STRBUF_INIT; if (!repo_parse_commit(the_repository, commit)) - pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb); + pp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &sb); if (print_sha1_ellipsis()) { fprintf(stderr, "%s %s... %s\n", msg, repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV), @@ -1077,7 +1077,7 @@ static void describe_one_orphan(struct strbuf *sb, struct commit *commit) strbuf_add_unique_abbrev(sb, &commit->object.oid, DEFAULT_ABBREV); strbuf_addch(sb, ' '); if (!repo_parse_commit(the_repository, commit)) - pp_commit_easy(CMIT_FMT_ONELINE, commit, sb); + pp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, sb); strbuf_addch(sb, '\n'); } diff --git a/builtin/log.c b/builtin/log.c index 8ab6d3a9439afd..0758aed5808c56 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -2521,7 +2521,7 @@ static void print_commit(char sign, struct commit *commit, int verbose, repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev)); } else { struct strbuf buf = STRBUF_INIT; - pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf); + pp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &buf); fprintf(file, "%c %s %s\n", sign, repo_find_unique_abbrev(the_repository, &commit->object.oid, abbrev), buf.buf); diff --git a/builtin/merge.c b/builtin/merge.c index 7c944fe179df86..dff8185776b303 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -470,7 +470,7 @@ static void squash_message(struct commit *commit, struct commit_list *remotehead strbuf_addch(&out, '\n'); strbuf_addf(&out, "commit %s\n", oid_to_hex(&commit->object.oid)); - pretty_print_commit(&ctx, commit, &out); + pretty_print_commit(the_repository, &ctx, commit, &out); } write_file_buf(git_path_squash_msg(the_repository), out.buf, out.len); strbuf_release(&out); diff --git a/builtin/reset.c b/builtin/reset.c index c48d9845f8425e..733f3fa90513ac 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -141,7 +141,7 @@ static void print_new_head_line(struct commit *commit) printf(_("HEAD is now at %s"), repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV)); - pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf); + pp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &buf); if (buf.len > 0) printf(" %s", buf.buf); putchar('\n'); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index ddea8aa251a361..57c7b8d3ffa50e 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -307,7 +307,7 @@ static void show_commit(struct commit *commit, void *data) ctx.output_encoding = get_log_output_encoding(); ctx.color = revs->diffopt.use_color; ctx.rev = revs; - pretty_print_commit(&ctx, commit, &buf); + pretty_print_commit(the_repository, &ctx, commit, &buf); if (buf.len) { if (revs->commit_format != CMIT_FMT_ONELINE) graph_show_oneline(revs->graph); diff --git a/builtin/shortlog.c b/builtin/shortlog.c index d80bf1a7d055fc..109785fd0036a8 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -252,7 +252,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit) if (!log->summary) { if (log->user_format) - pretty_print_commit(&ctx, commit, &oneline); + pretty_print_commit(the_repository, &ctx, commit, &oneline); else repo_format_commit_message(the_repository, commit, "%s", &oneline, &ctx); diff --git a/builtin/show-branch.c b/builtin/show-branch.c index f02831b08500c4..6bfe9e2e96d656 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -310,7 +310,7 @@ static void show_one_commit(struct commit *commit, int no_name) struct commit_name *name = commit_to_name(commit); if (commit->object.parsed) { - pp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty); + pp_commit_easy(the_repository, CMIT_FMT_ONELINE, commit, &pretty); pretty_str = pretty.buf; } skip_prefix(pretty_str, "[PATCH] ", &pretty_str); diff --git a/builtin/stash.c b/builtin/stash.c index 785c1f9e5d5f38..a522bb6de56732 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -1480,7 +1480,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b &head_commit->object.oid, DEFAULT_ABBREV); strbuf_addf(&msg, "%s: %s ", branch_name, head_short_sha1); - pp_commit_easy(CMIT_FMT_ONELINE, head_commit, &msg); + pp_commit_easy(the_repository, CMIT_FMT_ONELINE, head_commit, &msg); strbuf_addf(&commit_tree_label, "index on %s\n", msg.buf); commit_list_insert(head_commit, &parents); diff --git a/bundle.c b/bundle.c index 42327f9739cc54..3bc2ed9ee9aea3 100644 --- a/bundle.c +++ b/bundle.c @@ -463,7 +463,7 @@ static void write_bundle_prerequisites(struct commit *commit, void *data) ctx.fmt = CMIT_FMT_ONELINE; ctx.output_encoding = get_log_output_encoding(); strbuf_reset(&buf); - pretty_print_commit(&ctx, commit, &buf); + pretty_print_commit(the_repository, &ctx, commit, &buf); strbuf_trim(&buf); object = (struct object *)commit; diff --git a/log-tree.c b/log-tree.c index 7e048701d0c5b4..fd2fb0bed68a7f 100644 --- a/log-tree.c +++ b/log-tree.c @@ -885,7 +885,7 @@ void show_log(struct rev_info *opt) ctx.from_ident = &opt->from_ident; if (opt->graph) ctx.graph_width = graph_width(opt->graph); - pretty_print_commit(&ctx, commit, &msgbuf); + pretty_print_commit(opt->repo, &ctx, commit, &msgbuf); if (opt->add_signoff) append_signoff(&msgbuf, 0, APPEND_SIGNOFF_DEDUP); diff --git a/pretty.c b/pretty.c index e0646bbc5d49cc..51e34804312480 100644 --- a/pretty.c +++ b/pretty.c @@ -2281,7 +2281,7 @@ void pp_remainder(struct pretty_print_context *pp, } } -void pretty_print_commit(struct pretty_print_context *pp, +void pretty_print_commit(struct repository *r, struct pretty_print_context *pp, const struct commit *commit, struct strbuf *sb) { @@ -2363,10 +2363,10 @@ void pretty_print_commit(struct pretty_print_context *pp, repo_unuse_commit_buffer(the_repository, commit, reencoded); } -void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit, +void pp_commit_easy(struct repository *r, enum cmit_fmt fmt, const struct commit *commit, struct strbuf *sb) { struct pretty_print_context pp = {0}; pp.fmt = fmt; - pretty_print_commit(&pp, commit, sb); + pretty_print_commit(r, &pp, commit, sb); } diff --git a/pretty.h b/pretty.h index fac699033e943c..13eb0189bdce43 100644 --- a/pretty.h +++ b/pretty.h @@ -82,7 +82,7 @@ void userformat_find_requirements(const char *fmt, struct userformat_want *w); * Shortcut for invoking pretty_print_commit if we do not have any context. * Context would be set empty except "fmt". */ -void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit, +void pp_commit_easy(struct repository *r, enum cmit_fmt fmt, const struct commit *commit, struct strbuf *sb); /* @@ -132,7 +132,7 @@ void get_commit_format(const char *arg, struct rev_info *); * and put it into "sb". * Please use this function if you have a context (candidate for "pp"). */ -void pretty_print_commit(struct pretty_print_context *pp, +void pretty_print_commit(struct repository *r, struct pretty_print_context *pp, const struct commit *commit, struct strbuf *sb); diff --git a/range-diff.c b/range-diff.c index 57edff40a85f24..31d38c2318c876 100644 --- a/range-diff.c +++ b/range-diff.c @@ -460,7 +460,7 @@ static void output_pair_header(struct diff_options *diffopt, strbuf_addf(buf, "%s%s", color_reset, color); strbuf_addch(buf, ' '); - pp_commit_easy(CMIT_FMT_ONELINE, commit, buf); + pp_commit_easy(diffopt->repo, CMIT_FMT_ONELINE, commit, buf); } strbuf_addf(buf, "%s\n", color_reset); diff --git a/sequencer.c b/sequencer.c index 627020d65bb48f..e6b3e05fce2378 100644 --- a/sequencer.c +++ b/sequencer.c @@ -5870,7 +5870,7 @@ static int make_script_with_merges(struct pretty_print_context *pp, continue; strbuf_reset(&oneline); - pretty_print_commit(pp, commit, &oneline); + pretty_print_commit(revs->repo, pp, commit, &oneline); to_merge = commit->parents ? commit->parents->next : NULL; if (!to_merge) { @@ -6012,7 +6012,7 @@ static int make_script_with_merges(struct pretty_print_context *pp, strbuf_addf(out, "%s onto\n", cmd_reset); else { strbuf_reset(&oneline); - pretty_print_commit(pp, commit, &oneline); + pretty_print_commit(revs->repo, pp, commit, &oneline); strbuf_addf(out, "%s %s %s\n", cmd_reset, to, oneline.buf); } @@ -6124,7 +6124,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, continue; strbuf_addf(out, "%s %s ", insn, oid_to_hex(&commit->object.oid)); - pretty_print_commit(&pp, commit, out); + pretty_print_commit(r, &pp, commit, out); if (is_empty) strbuf_addf(out, " %s empty", comment_line_str); strbuf_addch(out, '\n'); From 196b272c881caa06ec8432c45b30a9c130ae2d7b Mon Sep 17 00:00:00 2001 From: Tian Yuchen Date: Mon, 2 Mar 2026 03:50:17 +0800 Subject: [PATCH 3/3] environment: migrate encoding configs to struct repository The global variables 'git_commit_encoding' and 'git_log_output_encoding' prevent libification. Migrate these variables into 'struct repository'. Note that these variables are not migrated to 'repo_settings'. As user preferences, they must be parsed eagerly to maintain immediate UX feedback. While the core read and write APIs (updated in previous patches) now utilize the 'struct repository' pointer, the config parsing step ('git_default_i18n_config') currently parses these values into 'the_repository', since safely plumbing a repository pointer through the 'git_default_config' callback machinery is highly invasive due to the diverse and custom structures currently passed via the 'void *cb' parameter. Signed-off-by: Tian Yuchen --- builtin/am.c | 4 ++-- builtin/blame.c | 2 +- builtin/commit.c | 6 +++--- builtin/log.c | 2 +- builtin/mailinfo.c | 6 +++--- builtin/rev-list.c | 2 +- builtin/shortlog.c | 2 +- bundle.c | 2 +- commit.c | 13 +++++++------ environment.c | 19 ++++++++----------- environment.h | 7 ++----- log-tree.c | 4 ++-- pretty.c | 2 +- remote-curl.c | 2 +- replay.c | 2 +- repository.c | 2 ++ repository.h | 5 +++++ revision.c | 10 +++++----- sequencer.c | 22 +++++++++++----------- submodule.c | 2 +- 20 files changed, 59 insertions(+), 57 deletions(-) diff --git a/builtin/am.c b/builtin/am.c index 5296124f84cfb1..990b6c54e70b30 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -1216,7 +1216,7 @@ static int parse_mail(struct am_state *state, const char *mail) setup_mailinfo(the_repository, &mi); if (state->utf8) - mi.metainfo_charset = get_commit_output_encoding(); + mi.metainfo_charset = get_commit_output_encoding(the_repository); else mi.metainfo_charset = NULL; @@ -1355,7 +1355,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit) struct ident_split id; buffer = repo_logmsg_reencode(the_repository, commit, NULL, - get_commit_output_encoding()); + get_commit_output_encoding(the_repository)); ident_line = find_commit_header(buffer, "author", &ident_len); if (!ident_line) diff --git a/builtin/blame.c b/builtin/blame.c index eac2fe73201ca2..0ad9f2c9f7e398 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -202,7 +202,7 @@ static void get_commit_info(struct commit *commit, struct commit_info *ret) const char *subject, *encoding; const char *message; - encoding = get_log_output_encoding(); + encoding = get_log_output_encoding(the_repository); message = repo_logmsg_reencode(the_repository, commit, NULL, encoding); get_ac_line(message, "\nauthor ", &ret->author, &ret->author_mail, diff --git a/builtin/commit.c b/builtin/commit.c index d619fd2acedc17..caf5896d97e116 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -794,7 +794,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, c = lookup_commit_reference_by_name(squash_message); if (!c) die(_("could not lookup commit '%s'"), squash_message); - ctx.output_encoding = get_commit_output_encoding(); + ctx.output_encoding = get_commit_output_encoding(the_repository); repo_format_commit_message(the_repository, c, "squash! %s\n\n", &sb, &ctx); @@ -829,7 +829,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, commit = lookup_commit_reference_by_name(fixup_commit); if (!commit) die(_("could not lookup commit '%s'"), fixup_commit); - ctx.output_encoding = get_commit_output_encoding(); + ctx.output_encoding = get_commit_output_encoding(the_repository); fmt = xstrfmt("%s! %%s\n\n", fixup_prefix); repo_format_commit_message(the_repository, commit, fmt, &sb, &ctx); @@ -1235,7 +1235,7 @@ static const char *read_commit_message(const char *name) commit = lookup_commit_reference_by_name(name); if (!commit) die(_("could not lookup commit '%s'"), name); - out_enc = get_commit_output_encoding(); + out_enc = get_commit_output_encoding(the_repository); return repo_logmsg_reencode(the_repository, commit, NULL, out_enc); } diff --git a/builtin/log.c b/builtin/log.c index 0758aed5808c56..8edb3c54e7089f 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -568,7 +568,7 @@ static void show_tagger(const char *buf, struct rev_info *rev) pp.fmt = rev->commit_format; pp.date_mode = rev->date_mode; - pp_user_info(&pp, "Tagger", &out, buf, get_log_output_encoding()); + pp_user_info(&pp, "Tagger", &out, buf, get_log_output_encoding(the_repository)); fprintf(rev->diffopt.file, "%s", out.buf); strbuf_release(&out); } diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c index 8de7ba7de1d6aa..4f17cf1598ca41 100644 --- a/builtin/mailinfo.c +++ b/builtin/mailinfo.c @@ -52,7 +52,7 @@ static int parse_opt_quoted_cr(const struct option *opt, const char *arg, int un int cmd_mailinfo(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct metainfo_charset meta_charset; struct mailinfo mi; @@ -83,7 +83,7 @@ int cmd_mailinfo(int argc, OPT_END() }; - setup_mailinfo(the_repository, &mi); + setup_mailinfo(repo, &mi); meta_charset.policy = CHARSET_DEFAULT; argc = parse_options(argc, argv, prefix, options, mailinfo_usage, 0); @@ -93,7 +93,7 @@ int cmd_mailinfo(int argc, switch (meta_charset.policy) { case CHARSET_DEFAULT: - mi.metainfo_charset = get_commit_output_encoding(); + mi.metainfo_charset = get_commit_output_encoding(repo); break; case CHARSET_NO_REENCODE: mi.metainfo_charset = NULL; diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 57c7b8d3ffa50e..3732edae8be713 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -304,7 +304,7 @@ static void show_commit(struct commit *commit, void *data) ctx.date_mode = revs->date_mode; ctx.date_mode_explicit = revs->date_mode_explicit; ctx.fmt = revs->commit_format; - ctx.output_encoding = get_log_output_encoding(); + ctx.output_encoding = get_log_output_encoding(the_repository); ctx.color = revs->diffopt.use_color; ctx.rev = revs; pretty_print_commit(the_repository, &ctx, commit, &buf); diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 109785fd0036a8..79606e57be8ccf 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -248,7 +248,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit) ctx.fmt = CMIT_FMT_USERFORMAT; ctx.abbrev = log->abbrev; ctx.date_mode = log->date_mode; - ctx.output_encoding = get_log_output_encoding(); + ctx.output_encoding = get_log_output_encoding(the_repository); if (!log->summary) { if (log->user_format) diff --git a/bundle.c b/bundle.c index 3bc2ed9ee9aea3..3b98cdd6fd4dda 100644 --- a/bundle.c +++ b/bundle.c @@ -461,7 +461,7 @@ static void write_bundle_prerequisites(struct commit *commit, void *data) write_or_die(bpi->fd, buf.buf, buf.len); ctx.fmt = CMIT_FMT_ONELINE; - ctx.output_encoding = get_log_output_encoding(); + ctx.output_encoding = get_log_output_encoding(the_repository); strbuf_reset(&buf); pretty_print_commit(the_repository, &ctx, commit, &buf); strbuf_trim(&buf); diff --git a/commit.c b/commit.c index 71a2b7bbe5f6b7..cb8ec675d1fe85 100644 --- a/commit.c +++ b/commit.c @@ -1663,7 +1663,8 @@ N_("Warning: commit message did not conform to UTF-8.\n" "You may want to amend it after fixing the message, or set the config\n" "variable i18n.commitEncoding to the encoding your project uses.\n"); -static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg_len, +static void write_commit_tree(struct repository *r, struct strbuf *buffer, + const char *msg, size_t msg_len, const struct object_id *tree, const struct object_id *parents, size_t parents_len, const char *author, const char *committer, @@ -1673,7 +1674,7 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg size_t i; /* Not having i18n.commitencoding is the same as having utf-8 */ - encoding_is_utf8 = is_encoding_utf8(git_commit_encoding); + encoding_is_utf8 = is_encoding_utf8(get_commit_output_encoding(r)); strbuf_grow(buffer, 8192); /* should avoid reallocs for the headers */ strbuf_addf(buffer, "tree %s\n", oid_to_hex(tree)); @@ -1694,7 +1695,7 @@ static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg committer = git_committer_info(IDENT_STRICT); strbuf_addf(buffer, "committer %s\n", committer); if (!encoding_is_utf8) - strbuf_addf(buffer, "encoding %s\n", git_commit_encoding); + strbuf_addf(buffer, "encoding %s\n", get_commit_output_encoding(r)); while (extra) { add_extra_header(buffer, extra); @@ -1722,7 +1723,7 @@ int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len, size_t i, nparents; /* Not having i18n.commitencoding is the same as having utf-8 */ - encoding_is_utf8 = is_encoding_utf8(git_commit_encoding); + encoding_is_utf8 = is_encoding_utf8(get_commit_output_encoding(r)); odb_assert_oid_type(the_repository->objects, tree, OBJ_TREE); @@ -1735,7 +1736,7 @@ int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len, for (const struct commit_list *p = parents; p; p = p->next) oidcpy(&parent_buf[i++], &p->item->object.oid); - write_commit_tree(&buffer, msg, msg_len, tree, parent_buf, nparents, author, committer, extra); + write_commit_tree(r, &buffer, msg, msg_len, tree, parent_buf, nparents, author, committer, extra); if (sign_commit && sign_commit_to_strbuf(&sig, &buffer, sign_commit)) { result = -1; goto out; @@ -1763,7 +1764,7 @@ int commit_tree_extended(struct repository *r, const char *msg, size_t msg_len, free(mapped_parents); goto out; } - write_commit_tree(&compat_buffer, msg, msg_len, &mapped_tree, + write_commit_tree(r, &compat_buffer, msg, msg_len, &mapped_tree, mapped_parents, nparents, author, committer, compat_extra); free_commit_extra_headers(compat_extra); free(mapped_parents); diff --git a/environment.c b/environment.c index 0026eb227487dd..a27c13da3d3e98 100644 --- a/environment.c +++ b/environment.c @@ -197,15 +197,14 @@ const char *strip_namespace(const char *namespaced_ref) return NULL; } -const char *get_log_output_encoding(void) +const char *get_log_output_encoding(struct repository *r) { - return git_log_output_encoding ? git_log_output_encoding - : get_commit_output_encoding(); + return r->log_output_encoding ? r->log_output_encoding : get_commit_output_encoding(r); } -const char *get_commit_output_encoding(void) +const char *get_commit_output_encoding(struct repository *r) { - return git_commit_encoding ? git_commit_encoding : "UTF-8"; + return r->commit_encoding ? r->commit_encoding : "UTF-8"; } int use_optional_locks(void) @@ -569,16 +568,14 @@ static int git_default_sparse_config(const char *var, const char *value) static int git_default_i18n_config(const char *var, const char *value) { if (!strcmp(var, "i18n.commitencoding")) { - FREE_AND_NULL(git_commit_encoding); - return git_config_string(&git_commit_encoding, var, value); + FREE_AND_NULL(the_repository->commit_encoding); + return git_config_string(&the_repository->commit_encoding, var, value); } - if (!strcmp(var, "i18n.logoutputencoding")) { - FREE_AND_NULL(git_log_output_encoding); - return git_config_string(&git_log_output_encoding, var, value); + FREE_AND_NULL(the_repository->log_output_encoding); + return git_config_string(&the_repository->log_output_encoding, var, value); } - /* Add other config variables here and to Documentation/config.adoc. */ return 0; } diff --git a/environment.h b/environment.h index 27f657af046a51..d1c62a8296444c 100644 --- a/environment.h +++ b/environment.h @@ -193,11 +193,8 @@ extern enum object_creation_mode object_creation_mode; extern int grafts_keep_true_parents; -const char *get_log_output_encoding(void); -const char *get_commit_output_encoding(void); - -extern char *git_commit_encoding; -extern char *git_log_output_encoding; +const char *get_log_output_encoding(struct repository *r); +const char *get_commit_output_encoding(struct repository *r); extern char *editor_program; extern char *askpass_program; diff --git a/log-tree.c b/log-tree.c index fd2fb0bed68a7f..364fd015f50705 100644 --- a/log-tree.c +++ b/log-tree.c @@ -859,7 +859,7 @@ void show_log(struct rev_info *opt) raw = (opt->commit_format == CMIT_FMT_USERFORMAT); format_display_notes(&commit->object.oid, ¬ebuf, - get_log_output_encoding(), raw); + get_log_output_encoding(opt->repo), raw); ctx.notes_message = strbuf_detach(¬ebuf, NULL); } @@ -879,7 +879,7 @@ void show_log(struct rev_info *opt) ctx.mailmap = opt->mailmap; ctx.color = opt->diffopt.use_color; ctx.expand_tabs_in_log = opt->expand_tabs_in_log; - ctx.output_encoding = get_log_output_encoding(); + ctx.output_encoding = get_log_output_encoding(opt->repo); ctx.rev = opt; if (opt->from_ident.mail_begin && opt->from_ident.name_begin) ctx.from_ident = &opt->from_ident; diff --git a/pretty.c b/pretty.c index 51e34804312480..6b585e27638ad7 100644 --- a/pretty.c +++ b/pretty.c @@ -2298,7 +2298,7 @@ void pretty_print_commit(struct repository *r, struct pretty_print_context *pp, return; } - encoding = get_log_output_encoding(); + encoding = get_log_output_encoding(r); msg = reencoded = repo_logmsg_reencode(the_repository, commit, NULL, encoding); diff --git a/remote-curl.c b/remote-curl.c index 92e40bb682d34d..146cb8930df7c9 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -379,7 +379,7 @@ static int show_http_message(struct strbuf *type, struct strbuf *charset, if (strcmp(type->buf, "text/plain")) return -1; if (charset->len) - strbuf_reencode(msg, charset->buf, get_log_output_encoding()); + strbuf_reencode(msg, charset->buf, get_log_output_encoding(the_repository)); strbuf_trim(msg); if (!msg->len) diff --git a/replay.c b/replay.c index 8704547aa1d0aa..0012d3aa1818f3 100644 --- a/replay.c +++ b/replay.c @@ -56,7 +56,7 @@ static struct commit *create_commit(struct repository *repo, char *sign_commit = NULL; /* FIXME: cli users might want to sign again */ struct commit_extra_header *extra = NULL; struct strbuf msg = STRBUF_INIT; - const char *out_enc = get_commit_output_encoding(); + const char *out_enc = get_commit_output_encoding(repo); const char *message = repo_logmsg_reencode(repo, based_on, NULL, out_enc); const char *orig_message = NULL; diff --git a/repository.c b/repository.c index 46a7c999302a4c..a2ab093a6851d1 100644 --- a/repository.c +++ b/repository.c @@ -370,6 +370,8 @@ void repo_clear(struct repository *repo) FREE_AND_NULL(repo->index_file); FREE_AND_NULL(repo->worktree); FREE_AND_NULL(repo->submodule_prefix); + FREE_AND_NULL(repo->commit_encoding); + FREE_AND_NULL(repo->log_output_encoding); odb_free(repo->objects); repo->objects = NULL; diff --git a/repository.h b/repository.h index 7141237f97d87d..4e67b15c36c199 100644 --- a/repository.h +++ b/repository.h @@ -172,6 +172,11 @@ struct repository { /* Should repo_config() check for deprecated settings */ bool check_deprecated_config; + + /* User's preferred encoding for commit messages and log output. */ + + char *commit_encoding; + char *log_output_encoding; }; #ifdef USE_THE_REPOSITORY_VARIABLE diff --git a/revision.c b/revision.c index 29972c3a19887a..b85cac9877e419 100644 --- a/revision.c +++ b/revision.c @@ -2675,11 +2675,11 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg } else if (!strcmp(arg, "--invert-grep")) { revs->grep_filter.no_body_match = 1; } else if ((argcount = parse_long_opt("encoding", argv, &optarg))) { - free(git_log_output_encoding); + free(revs->repo->log_output_encoding); if (strcmp(optarg, "none")) - git_log_output_encoding = xstrdup(optarg); + revs->repo->log_output_encoding = xstrdup(optarg); else - git_log_output_encoding = xstrdup(""); + revs->repo->log_output_encoding = xstrdup(""); return argcount; } else if (!strcmp(arg, "--reverse")) { revs->reverse ^= 1; @@ -3129,7 +3129,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s diff_setup_done(&revs->diffopt); - if (!is_encoding_utf8(get_log_output_encoding())) + if (!is_encoding_utf8(get_log_output_encoding(revs->repo))) revs->grep_filter.ignore_locale = 1; compile_grep_patterns(&revs->grep_filter); @@ -4063,7 +4063,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt) * so we will not end up with a buffer that has two different encodings * in it. */ - encoding = get_log_output_encoding(); + encoding = get_log_output_encoding(opt->repo); message = repo_logmsg_reencode(the_repository, commit, NULL, encoding); /* Copy the commit to temporary if we are using "fake" headers */ diff --git a/sequencer.c b/sequencer.c index e6b3e05fce2378..62717910d25ba2 100644 --- a/sequencer.c +++ b/sequencer.c @@ -480,13 +480,13 @@ static const char *short_commit_name(struct repository *r, struct commit *commit return repo_find_unique_abbrev(r, &commit->object.oid, DEFAULT_ABBREV); } -static int get_message(struct commit *commit, struct commit_message *out) +static int get_message(struct repository *r, struct commit *commit, struct commit_message *out) { const char *abbrev, *subject; int subject_len; out->message = repo_logmsg_reencode(the_repository, commit, NULL, - get_commit_output_encoding()); + get_commit_output_encoding(r)); abbrev = short_commit_name(the_repository, commit); subject_len = find_commit_subject(out->message, &subject); @@ -1539,7 +1539,7 @@ static int try_to_commit(struct repository *r, if (flags & AMEND_MSG) { const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL }; - const char *out_enc = get_commit_output_encoding(); + const char *out_enc = get_commit_output_encoding(r); const char *message = repo_logmsg_reencode(r, current_head, NULL, out_enc); @@ -2054,7 +2054,7 @@ static int update_squash_messages(struct repository *r, struct strbuf buf = STRBUF_INIT; int res = 0; const char *message, *body; - const char *encoding = get_commit_output_encoding(); + const char *encoding = get_commit_output_encoding(r); if (!is_fixup(command)) BUG("not a FIXUP or SQUASH %d", command); @@ -2324,7 +2324,7 @@ static int do_pick_commit(struct repository *r, else parent = commit->parents->item; - if (get_message(commit, &msg) != 0) + if (get_message(r, commit, &msg) != 0) return error(_("cannot get commit message for %s"), oid_to_hex(&commit->object.oid)); @@ -3344,7 +3344,7 @@ static int walk_revs_populate_todo(struct todo_list *todo_list, if (prepare_revs(opts)) return -1; - encoding = get_log_output_encoding(); + encoding = get_log_output_encoding(the_repository); while ((commit = get_revision(opts->revs))) { struct todo_item *item = append_new_todo(todo_list); @@ -3730,7 +3730,7 @@ static int make_patch(struct repository *r, } if (!file_exists(rebase_path_message())) { - const char *encoding = get_commit_output_encoding(); + const char *encoding = get_commit_output_encoding(r); const char *commit_buffer = repo_logmsg_reencode(r, commit, NULL, encoding); @@ -4187,7 +4187,7 @@ static int do_merge(struct repository *r, } if (commit) { - const char *encoding = get_commit_output_encoding(); + const char *encoding = get_commit_output_encoding(r); const char *message = repo_logmsg_reencode(r, commit, NULL, encoding); const char *body; @@ -4831,7 +4831,7 @@ static int stopped_at_head(struct repository *r) if (repo_get_oid(r, "HEAD", &head) || !(commit = lookup_commit(r, &head)) || - repo_parse_commit(r, commit) || get_message(commit, &message)) + repo_parse_commit(r, commit) || get_message(r, commit, &message)) fprintf(stderr, _("Stopped at HEAD\n")); else { fprintf(stderr, _("Stopped at %s\n"), message.label); @@ -5311,7 +5311,7 @@ static int commit_staged_changes(struct repository *r, struct commit *commit; const char *msg; const char *path = rebase_path_squash_msg(); - const char *encoding = get_commit_output_encoding(); + const char *encoding = get_commit_output_encoding(r); if (parse_head(r, &commit)) { ret = error(_("could not parse HEAD")); @@ -6092,7 +6092,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, get_commit_format(format, &revs); free(format); pp.fmt = revs.commit_format; - pp.output_encoding = get_log_output_encoding(); + pp.output_encoding = get_log_output_encoding(r); setup_revisions_from_strvec(argv, &revs, NULL); if (argv->nr > 1) { diff --git a/submodule.c b/submodule.c index 508938e4da5058..a58ed3652c6efc 100644 --- a/submodule.c +++ b/submodule.c @@ -479,7 +479,7 @@ static void print_submodule_diff_summary(struct repository *r, struct rev_info * while ((commit = get_revision(rev))) { struct pretty_print_context ctx = {0}; ctx.date_mode = rev->date_mode; - ctx.output_encoding = get_log_output_encoding(); + ctx.output_encoding = get_log_output_encoding(r); strbuf_setlen(&sb, 0); repo_format_commit_message(r, commit, format, &sb, &ctx);