help: move tty check for autocorrection to autocorrect.c

TTY checking is the autocorrect config parser's responsibility. It must
ensure the parsed value is correct and reliable. Thus, move the check to
autocorr_resolve_config().

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:02 +09:00
committed by Junio C Hamano
parent db8b01619c
commit c8ac3d589a
3 changed files with 49 additions and 38 deletions

View File

@@ -6,7 +6,7 @@
#include "prompt.h"
#include "gettext.h"
static int parse_autocorrect(const char *value)
static enum autocorr_mode parse_autocorrect(const char *value)
{
switch (git_parse_maybe_bool_text(value)) {
case 1:
@@ -19,41 +19,49 @@ static int parse_autocorrect(const char *value)
if (!strcmp(value, "prompt"))
return AUTOCORRECT_PROMPT;
if (!strcmp(value, "never"))
else if (!strcmp(value, "never"))
return AUTOCORRECT_NEVER;
if (!strcmp(value, "immediate"))
else if (!strcmp(value, "immediate"))
return AUTOCORRECT_IMMEDIATELY;
if (!strcmp(value, "show"))
else if (!strcmp(value, "show"))
return AUTOCORRECT_SHOW;
return 0;
else
return AUTOCORRECT_DELAY;
}
void autocorr_resolve_config(const char *var, const char *value,
const struct config_context *ctx, void *data)
{
int *out = data;
struct autocorr *conf = data;
if (!strcmp(var, "help.autocorrect")) {
int v = parse_autocorrect(value);
if (strcmp(var, "help.autocorrect"))
return;
if (!v) {
v = git_config_int(var, value, ctx->kvi);
if (v < 0 || v == 1)
v = AUTOCORRECT_IMMEDIATELY;
}
conf->mode = parse_autocorrect(value);
*out = v;
/*
* Disable autocorrection prompt in a non-interactive session.
*/
if (conf->mode == AUTOCORRECT_PROMPT && (!isatty(0) || !isatty(2)))
conf->mode = AUTOCORRECT_NEVER;
if (conf->mode == AUTOCORRECT_DELAY) {
conf->delay = git_config_int(var, value, ctx->kvi);
if (!conf->delay)
conf->mode = AUTOCORRECT_SHOW;
else if (conf->delay <= 1)
conf->mode = AUTOCORRECT_IMMEDIATELY;
}
}
void autocorr_confirm(int autocorrect, const char *assumed)
void autocorr_confirm(struct autocorr *conf, const char *assumed)
{
if (autocorrect == AUTOCORRECT_IMMEDIATELY) {
if (conf->mode == AUTOCORRECT_IMMEDIATELY) {
fprintf_ln(stderr,
_("Continuing under the assumption that you meant '%s'."),
assumed);
} else if (autocorrect == AUTOCORRECT_PROMPT) {
} else if (conf->mode == AUTOCORRECT_PROMPT) {
char *answer;
struct strbuf msg = STRBUF_INIT;
@@ -63,10 +71,10 @@ void autocorr_confirm(int autocorrect, const char *assumed)
if (!(starts_with(answer, "y") || starts_with(answer, "Y")))
exit(1);
} else {
} else if (conf->mode == AUTOCORRECT_DELAY) {
fprintf_ln(stderr,
_("Continuing in %0.1f seconds, assuming that you meant '%s'."),
(float)autocorrect / 10.0, assumed);
sleep_millisec(autocorrect * 100);
conf->delay / 10.0, assumed);
sleep_millisec(conf->delay * 100);
}
}

View File

@@ -1,16 +1,24 @@
#ifndef AUTOCORRECT_H
#define AUTOCORRECT_H
#define AUTOCORRECT_SHOW (-4)
#define AUTOCORRECT_PROMPT (-3)
#define AUTOCORRECT_NEVER (-2)
#define AUTOCORRECT_IMMEDIATELY (-1)
struct config_context;
enum autocorr_mode {
AUTOCORRECT_SHOW,
AUTOCORRECT_NEVER,
AUTOCORRECT_PROMPT,
AUTOCORRECT_IMMEDIATELY,
AUTOCORRECT_DELAY,
};
struct autocorr {
enum autocorr_mode mode;
int delay;
};
void autocorr_resolve_config(const char *var, const char *value,
const struct config_context *ctx, void *data);
void autocorr_confirm(int autocorr, const char *assumed);
void autocorr_confirm(struct autocorr *conf, const char *assumed);
#endif /* AUTOCORRECT_H */

17
help.c
View File

@@ -538,7 +538,7 @@ int is_in_cmdlist(struct cmdnames *c, const char *s)
}
struct help_unknown_cmd_config {
int autocorrect;
struct autocorr autocorr;
struct cmdnames aliases;
};
@@ -550,7 +550,7 @@ static int git_unknown_cmd_config(const char *var, const char *value,
const char *subsection, *key;
size_t subsection_len;
autocorr_resolve_config(var, value, ctx, &cfg->autocorrect);
autocorr_resolve_config(var, value, ctx, &cfg->autocorr);
/* Also use aliases for command lookup */
if (!parse_config_key(var, "alias", &subsection, &subsection_len,
@@ -607,13 +607,7 @@ char *help_unknown_cmd(const char *cmd)
read_early_config(the_repository, git_unknown_cmd_config, &cfg);
/*
* Disable autocorrection prompt in a non-interactive session
*/
if ((cfg.autocorrect == AUTOCORRECT_PROMPT) && (!isatty(0) || !isatty(2)))
cfg.autocorrect = AUTOCORRECT_NEVER;
if (cfg.autocorrect == AUTOCORRECT_NEVER) {
if (cfg.autocorr.mode == AUTOCORRECT_NEVER) {
fprintf_ln(stderr, _("git: '%s' is not a git command. See 'git --help'."), cmd);
exit(1);
}
@@ -679,7 +673,8 @@ char *help_unknown_cmd(const char *cmd)
n++)
; /* still counting */
}
if (cfg.autocorrect && cfg.autocorrect != AUTOCORRECT_SHOW && n == 1 &&
if (cfg.autocorr.mode != AUTOCORRECT_SHOW && n == 1 &&
SIMILAR_ENOUGH(best_similarity)) {
char *assumed = xstrdup(main_cmds.names[0]->name);
@@ -688,7 +683,7 @@ char *help_unknown_cmd(const char *cmd)
"which does not exist."),
cmd);
autocorr_confirm(cfg.autocorrect, assumed);
autocorr_confirm(&cfg.autocorr, assumed);
cmdnames_release(&cfg.aliases);
cmdnames_release(&main_cmds);