environment: move editor_program into repo_config_values

The global variable 'editor_program' holds the path to the user's preferred editor. Move 'editor_program' into 'struct repo_config_values' to continue the libification effort. There have been discussions on whether external programs like editors truly need to be configured on a per-repository basis within the same process. While a single process might rarely invoke different editors, this migration is necessary for two reasons: 1. Developers frequently use different toolchains for different projects. Per-repo configuration respects this. 2. Moving this string into 'repo_config_values' eliminates mutable global state. As the codebase moves toward becoming a long-running processes, managing multiple repositories concurrently must not overwrite each other's program configurations. No standalone getter function is introduced. Callers directly access the field via 'repo_config_values()'. Heap memory is safely reclaimed in 'repo_config_values_clear()'. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Ayush Chandekar <ayu.chandekar@gmail.com> Mentored-by: Olamide Caleb Bello <belkid98@gmail.com> Signed-off-by: Tian Yuchen <cat@malon.dev> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Tian Yuchen committed Jul 14, 2026 at 11:25 UTC 469e95c2573e938c0963ba52e8d06dd6aa7ba262
3 files changed +7 -6
editor.c
+2 -2
@@ -29,8 +29,8 @@ const char *git_editor(void)
29 const char *editor = getenv("GIT_EDITOR");
30 int terminal_is_dumb = is_terminal_dumb();
31
32 - if (!editor && editor_program)
33 - editor = editor_program;
32 + if (!editor)
33 + editor = repo_config_values(the_repository)->editor_program;
34 if (!editor && !terminal_is_dumb)
35 editor = getenv("VISUAL");
36 if (!editor)
environment.c
+4 -3
@@ -55,7 +55,6 @@ int fsync_object_files = -1;
55 int use_fsync = -1;
56 enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT;
57 enum fsync_component fsync_components = FSYNC_COMPONENTS_DEFAULT;
58 -char *editor_program;
58 char *askpass_program;
59 enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
60 enum eol core_eol = EOL_UNSET;
@@ -437,8 +436,8 @@ int git_default_core_config(const char *var, const char *value,
436 }
437
438 if (!strcmp(var, "core.editor")) {
440 - FREE_AND_NULL(editor_program);
441 - return git_config_string(&editor_program, var, value);
439 + FREE_AND_NULL(cfg->editor_program);
440 + return git_config_string(&cfg->editor_program, var, value);
441 }
442
443 if (!strcmp(var, "core.commentchar") ||
@@ -725,6 +724,7 @@ void repo_config_values_init(struct repo_config_values *cfg)
724 {
725 cfg->attributes_file = NULL;
726 cfg->excludes_file = NULL;
727 + cfg->editor_program = NULL;
728 cfg->apply_sparse_checkout = 0;
729 cfg->branch_track = BRANCH_TRACK_REMOTE;
730 cfg->trust_ctime = 1;
@@ -741,4 +741,5 @@ void repo_config_values_clear(struct repo_config_values *cfg)
741 {
742 FREE_AND_NULL(cfg->attributes_file);
743 FREE_AND_NULL(cfg->excludes_file);
744 + FREE_AND_NULL(cfg->editor_program);
745 }
environment.h
+1 -1
@@ -91,6 +91,7 @@ struct repo_config_values {
91 /* section "core" config values */
92 char *attributes_file;
93 char *excludes_file;
94 + char *editor_program;
95 int apply_sparse_checkout;
96 int trust_ctime;
97 int check_stat;
@@ -218,7 +219,6 @@ const char *get_commit_output_encoding(void);
219 extern char *git_commit_encoding;
220 extern char *git_log_output_encoding;
221
221 -extern char *editor_program;
222 extern char *askpass_program;
223
224 /*