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 <gitster@pobox.com>
This commit is contained in:
Jiamu Sun
2026-03-10 20:41:04 +09:00
committed by Junio C Hamano
parent 2a48e5668b
commit 46483152a4
3 changed files with 28 additions and 29 deletions

View File

@@ -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)

View File

@@ -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);

37
help.c
View File

@@ -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;