From 46483152a40c803dd0cddcbf9ce2248f9cc23fc6 Mon Sep 17 00:00:00 2001 From: Jiamu Sun <39@barroit.sh> Date: Tue, 10 Mar 2026 20:41:04 +0900 Subject: [PATCH] autocorrect: provide config resolution API Add autocorr_resolve(). This resolves and populates the correct values for autocorrect config. Make autocorrect config callback internal. The API is meant to provide a high-level way to retrieve the config. Allowing access to the config callback from outside violates that intent. Additionally, in some cases, without access to the config callback, two config iterations cannot be merged into one, which can hurt performance. This is fine, as the code path that calls autocorr_resolve() is cold. Signed-off-by: Jiamu Sun <39@barroit.sh> Signed-off-by: Junio C Hamano --- autocorrect.c | 15 ++++++++++++--- autocorrect.h | 5 +---- help.c | 37 +++++++++++++++---------------------- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/autocorrect.c b/autocorrect.c index 9c4b691fb0..63fa331ef5 100644 --- a/autocorrect.c +++ b/autocorrect.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "autocorrect.h" #include "config.h" @@ -29,13 +31,13 @@ static enum autocorr_mode parse_autocorrect(const char *value) return AUTOCORRECT_DELAY; } -void autocorr_resolve_config(const char *var, const char *value, - const struct config_context *ctx, void *data) +static int resolve_autocorr(const char *var, const char *value, + const struct config_context *ctx, void *data) { struct autocorr *conf = data; if (strcmp(var, "help.autocorrect")) - return; + return 0; conf->mode = parse_autocorrect(value); @@ -53,6 +55,13 @@ void autocorr_resolve_config(const char *var, const char *value, else if (conf->delay <= 1) conf->mode = AUTOCORRECT_IMMEDIATELY; } + + return 0; +} + +void autocorr_resolve(struct autocorr *conf) +{ + read_early_config(the_repository, resolve_autocorr, conf); } void autocorr_confirm(struct autocorr *conf, const char *assumed) diff --git a/autocorrect.h b/autocorrect.h index be4e3e8b20..5d82c49903 100644 --- a/autocorrect.h +++ b/autocorrect.h @@ -1,8 +1,6 @@ #ifndef AUTOCORRECT_H #define AUTOCORRECT_H -struct config_context; - enum autocorr_mode { AUTOCORRECT_HINTONLY, AUTOCORRECT_NEVER, @@ -16,8 +14,7 @@ struct autocorr { int delay; }; -void autocorr_resolve_config(const char *var, const char *value, - const struct config_context *ctx, void *data); +void autocorr_resolve(struct autocorr *conf); void autocorr_confirm(struct autocorr *conf, const char *assumed); diff --git a/help.c b/help.c index 6158545e48..4adb1fcf07 100644 --- a/help.c +++ b/help.c @@ -537,32 +537,24 @@ int is_in_cmdlist(struct cmdnames *c, const char *s) return 0; } -struct help_unknown_cmd_config { - struct autocorr autocorr; - struct cmdnames aliases; -}; - -static int git_unknown_cmd_config(const char *var, const char *value, - const struct config_context *ctx, - void *cb) +static int resolve_aliases(const char *var, const char *value UNUSED, + const struct config_context *ctx UNUSED, void *data) { - struct help_unknown_cmd_config *cfg = cb; + struct cmdnames *aliases = data; const char *subsection, *key; size_t subsection_len; - autocorr_resolve_config(var, value, ctx, &cfg->autocorr); - /* Also use aliases for command lookup */ if (!parse_config_key(var, "alias", &subsection, &subsection_len, &key)) { if (subsection) { /* [alias "name"] command = value */ if (!strcmp(key, "command")) - add_cmdname(&cfg->aliases, subsection, + add_cmdname(aliases, subsection, subsection_len); } else { /* alias.name = value */ - add_cmdname(&cfg->aliases, key, strlen(key)); + add_cmdname(aliases, key, strlen(key)); } } @@ -599,22 +591,24 @@ static const char bad_interpreter_advice[] = char *help_unknown_cmd(const char *cmd) { - struct help_unknown_cmd_config cfg = { 0 }; + struct cmdnames aliases = { 0 }; + struct autocorr autocorr = { 0 }; int i, n, best_similarity = 0; struct cmdnames main_cmds = { 0 }; struct cmdnames other_cmds = { 0 }; struct cmdname_help *common_cmds; - read_early_config(the_repository, git_unknown_cmd_config, &cfg); + autocorr_resolve(&autocorr); - if (cfg.autocorr.mode == AUTOCORRECT_NEVER) { + if (autocorr.mode == AUTOCORRECT_NEVER) { fprintf_ln(stderr, _("git: '%s' is not a git command. See 'git --help'."), cmd); exit(1); } load_command_list("git-", &main_cmds, &other_cmds); + read_early_config(the_repository, resolve_aliases, &aliases); - add_cmd_list(&main_cmds, &cfg.aliases); + add_cmd_list(&main_cmds, &aliases); add_cmd_list(&main_cmds, &other_cmds); QSORT(main_cmds.names, main_cmds.cnt, cmdname_compare); uniq(&main_cmds); @@ -674,18 +668,17 @@ char *help_unknown_cmd(const char *cmd) ; /* still counting */ } - if (cfg.autocorr.mode != AUTOCORRECT_HINTONLY && n == 1 && + if (autocorr.mode != AUTOCORRECT_HINTONLY && n == 1 && SIMILAR_ENOUGH(best_similarity)) { char *assumed = xstrdup(main_cmds.names[0]->name); fprintf_ln(stderr, - _("WARNING: You called a Git command named '%s', " - "which does not exist."), + _("WARNING: You called a Git command named '%s', which does not exist."), cmd); - autocorr_confirm(&cfg.autocorr, assumed); + autocorr_confirm(&autocorr, assumed); - cmdnames_release(&cfg.aliases); + cmdnames_release(&aliases); cmdnames_release(&main_cmds); cmdnames_release(&other_cmds); return assumed;