2222#include "repository.h"
2323#include "alias.h"
2424#include "utf8.h"
25+ #include "autocorrect.h"
2526
2627#ifndef NO_CURL
2728#include "git-curl-compat.h" /* For LIBCURL_VERSION only */
@@ -536,77 +537,30 @@ int is_in_cmdlist(struct cmdnames *c, const char *s)
536537 return 0 ;
537538}
538539
539- struct help_unknown_cmd_config {
540- int autocorrect ;
541- struct cmdnames aliases ;
542- };
543-
544- #define AUTOCORRECT_SHOW (-4)
545- #define AUTOCORRECT_PROMPT (-3)
546- #define AUTOCORRECT_NEVER (-2)
547- #define AUTOCORRECT_IMMEDIATELY (-1)
548-
549- static int parse_autocorrect (const char * value )
550- {
551- switch (git_parse_maybe_bool_text (value )) {
552- case 1 :
553- return AUTOCORRECT_IMMEDIATELY ;
554- case 0 :
555- return AUTOCORRECT_SHOW ;
556- default : /* other random text */
557- break ;
558- }
559-
560- if (!strcmp (value , "prompt" ))
561- return AUTOCORRECT_PROMPT ;
562- if (!strcmp (value , "never" ))
563- return AUTOCORRECT_NEVER ;
564- if (!strcmp (value , "immediate" ))
565- return AUTOCORRECT_IMMEDIATELY ;
566- if (!strcmp (value , "show" ))
567- return AUTOCORRECT_SHOW ;
568-
569- return 0 ;
570- }
571-
572- static int git_unknown_cmd_config (const char * var , const char * value ,
573- const struct config_context * ctx ,
574- void * cb )
540+ static int resolve_aliases (const char * var , const char * value UNUSED ,
541+ const struct config_context * ctx UNUSED , void * data )
575542{
576- struct help_unknown_cmd_config * cfg = cb ;
543+ struct cmdnames * aliases = data ;
577544 const char * subsection , * key ;
578545 size_t subsection_len ;
579546
580- if (!strcmp (var , "help.autocorrect" )) {
581- int v = parse_autocorrect (value );
582-
583- if (!v ) {
584- v = git_config_int (var , value , ctx -> kvi );
585- if (v < 0 || v == 1 )
586- v = AUTOCORRECT_IMMEDIATELY ;
587- }
588-
589- cfg -> autocorrect = v ;
590- }
591-
592- /* Also use aliases for command lookup */
593547 if (!parse_config_key (var , "alias" , & subsection , & subsection_len ,
594548 & key )) {
595549 size_t key_len = strlen (key );
596550
597551 if (subsection ) {
598552 /* [alias "name"] command = value */
599553 if (!strcmp (key , "command" ))
600- add_cmdname (& cfg -> aliases , subsection ,
554+ add_cmdname (aliases , subsection ,
601555 subsection_len );
602556 else {
603557 key = var + strlen ("alias." );
604558 key_len = strlen (key );
605- add_cmdname (& cfg -> aliases , key , key_len );
559+ add_cmdname (aliases , key , key_len );
606560 }
607561 } else {
608562 /* alias.name = value */
609- add_cmdname (& cfg -> aliases , key , key_len );
563+ add_cmdname (aliases , key , key_len );
610564 }
611565 }
612566
@@ -633,38 +587,32 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
633587 old -> cnt = 0 ;
634588}
635589
636- /* An empirically derived magic number */
637- #define SIMILARITY_FLOOR 7
638- #define SIMILAR_ENOUGH (x ) ((x) < SIMILARITY_FLOOR)
639-
640590static const char bad_interpreter_advice [] =
641591 N_ ("'%s' appears to be a git command, but we were not\n"
642592 "able to execute it. Maybe git-%s is broken?" );
643593
644594char * help_unknown_cmd (const char * cmd )
645595{
646- struct help_unknown_cmd_config cfg = { 0 };
596+ struct cmdnames aliases = { 0 };
597+ struct autocorrect autocorrect = { 0 };
647598 int i , n , best_similarity = 0 ;
648599 struct cmdnames main_cmds = { 0 };
649600 struct cmdnames other_cmds = { 0 };
650601 struct cmdname_help * common_cmds ;
651602
652- read_early_config (the_repository , git_unknown_cmd_config , & cfg );
653-
654- /*
655- * Disable autocorrection prompt in a non-interactive session
656- */
657- if ((cfg .autocorrect == AUTOCORRECT_PROMPT ) && (!isatty (0 ) || !isatty (2 )))
658- cfg .autocorrect = AUTOCORRECT_NEVER ;
603+ autocorrect_resolve (& autocorrect );
659604
660- if (cfg . autocorrect == AUTOCORRECT_NEVER ) {
605+ if (autocorrect . mode == AUTOCORRECT_NEVER ) {
661606 fprintf_ln (stderr , _ ("git: '%s' is not a git command. See 'git --help'." ), cmd );
662607 exit (1 );
663608 }
664609
665610 load_command_list ("git-" , & main_cmds , & other_cmds );
666611
667- add_cmd_list (& main_cmds , & cfg .aliases );
612+ /* Also use aliases for command lookup */
613+ read_early_config (the_repository , resolve_aliases , & aliases );
614+
615+ add_cmd_list (& main_cmds , & aliases );
668616 add_cmd_list (& main_cmds , & other_cmds );
669617 QSORT (main_cmds .names , main_cmds .cnt , cmdname_compare );
670618 uniq (& main_cmds );
@@ -714,7 +662,7 @@ char *help_unknown_cmd(const char *cmd)
714662
715663 if (main_cmds .cnt <= n ) {
716664 /* prefix matches with everything? that is too ambiguous */
717- best_similarity = SIMILARITY_FLOOR + 1 ;
665+ best_similarity = AUTOCORRECT_SIMILARITY_FLOOR + 1 ;
718666 } else {
719667 /* count all the most similar ones */
720668 for (best_similarity = main_cmds .names [n ++ ]-> len ;
@@ -723,49 +671,29 @@ char *help_unknown_cmd(const char *cmd)
723671 n ++ )
724672 ; /* still counting */
725673 }
726- if (cfg .autocorrect && cfg .autocorrect != AUTOCORRECT_SHOW && n == 1 &&
727- SIMILAR_ENOUGH (best_similarity )) {
674+
675+ if (autocorrect .mode != AUTOCORRECT_HINT && n == 1 &&
676+ AUTOCORRECT_SIMILAR_ENOUGH (best_similarity )) {
728677 char * assumed = xstrdup (main_cmds .names [0 ]-> name );
729678
730679 fprintf_ln (stderr ,
731- _ ("WARNING: You called a Git command named '%s', "
732- "which does not exist." ),
680+ _ ("WARNING: You called a Git command named '%s', which does not exist." ),
733681 cmd );
734- if (cfg .autocorrect == AUTOCORRECT_IMMEDIATELY )
735- fprintf_ln (stderr ,
736- _ ("Continuing under the assumption that "
737- "you meant '%s'." ),
738- assumed );
739- else if (cfg .autocorrect == AUTOCORRECT_PROMPT ) {
740- char * answer ;
741- struct strbuf msg = STRBUF_INIT ;
742- strbuf_addf (& msg , _ ("Run '%s' instead [y/N]? " ), assumed );
743- answer = git_prompt (msg .buf , PROMPT_ECHO );
744- strbuf_release (& msg );
745- if (!(starts_with (answer , "y" ) ||
746- starts_with (answer , "Y" )))
747- exit (1 );
748- } else {
749- fprintf_ln (stderr ,
750- _ ("Continuing in %0.1f seconds, "
751- "assuming that you meant '%s'." ),
752- (float )cfg .autocorrect /10.0 , assumed );
753- sleep_millisec (cfg .autocorrect * 100 );
754- }
755682
756- cmdnames_release (& cfg .aliases );
683+ autocorrect_confirm (& autocorrect , assumed );
684+
685+ cmdnames_release (& aliases );
757686 cmdnames_release (& main_cmds );
758687 cmdnames_release (& other_cmds );
759688 return assumed ;
760689 }
761690
762691 fprintf_ln (stderr , _ ("git: '%s' is not a git command. See 'git --help'." ), cmd );
763692
764- if (SIMILAR_ENOUGH (best_similarity )) {
693+ if (AUTOCORRECT_SIMILAR_ENOUGH (best_similarity )) {
765694 fprintf_ln (stderr ,
766695 Q_ ("\nThe most similar command is" ,
767- "\nThe most similar commands are" ,
768- n ));
696+ "\nThe most similar commands are" , n ));
769697
770698 for (i = 0 ; i < n ; i ++ )
771699 fprintf (stderr , "\t%s\n" , main_cmds .names [i ]-> name );
0 commit comments