33#include "config.h"
44#include "environment.h"
55#include "parse-options.h"
6+ #include "strbuf.h"
7+ #include "string-list.h"
68
79static const char * const builtin_config_batch_usage [] = {
810 N_ ("git config-batch <options>" ),
911 NULL
1012};
1113
14+ #define UNKNOWN_COMMAND "unknown_command"
15+
16+ static int emit_response (const char * response , ...)
17+ {
18+ va_list params ;
19+ const char * token ;
20+
21+ printf ("%s" , response );
22+
23+ va_start (params , response );
24+ while ((token = va_arg (params , const char * )))
25+ printf (" %s" , token );
26+ va_end (params );
27+
28+ printf ("\n" );
29+ fflush (stdout );
30+ return 0 ;
31+ }
32+
33+ /**
34+ * A function pointer type for defining a command. The function is
35+ * responsible for handling different versions of the command name.
36+ *
37+ * These functions should only return a negative value if they result
38+ * in such a catastrophic failure that the process should end.
39+ *
40+ * Return 0 on success.
41+ */
42+ typedef int (* command_fn )(struct repository * repo , int version ,
43+ int argc , const char * * argv );
44+
45+ static int unknown_commmand (struct repository * repo UNUSED , int version UNUSED ,
46+ int argc UNUSED , const char * * argv UNUSED )
47+ {
48+ return emit_response (UNKNOWN_COMMAND , NULL );
49+ }
50+
51+ struct command {
52+ const char * name ;
53+ command_fn fn ;
54+ };
55+
56+ static struct command commands [] = {
57+ /* unknown_command must be last. */
58+ {
59+ .name = "" ,
60+ .fn = unknown_commmand ,
61+ },
62+ };
63+
64+ #define COMMAND_COUNT ((size_t)(sizeof(commands) / sizeof(*commands)))
65+
66+ /**
67+ * Process a single line from stdin and process the command.
68+ *
69+ * Returns 0 on successful processing of command, including the
70+ * unknown_command output.
71+ *
72+ * Returns 1 on natural exit due to exist signal of empty line.
73+ *
74+ * Returns negative value on other catastrophic error.
75+ */
76+ static int process_command (struct repository * repo )
77+ {
78+ static struct strbuf line = STRBUF_INIT ;
79+ struct string_list tokens = STRING_LIST_INIT_NODUP ;
80+ const char * command ;
81+ int version ;
82+ int argc = 0 ;
83+ const char * * argv = NULL ;
84+ int res = 0 ;
85+
86+ strbuf_getline (& line , stdin );
87+
88+ if (!line .len )
89+ return 1 ;
90+
91+ string_list_split_in_place (& tokens , line .buf , " " , -1 );
92+
93+ if (tokens .nr < 2 ) {
94+ res = error (_ ("expected at least 2 tokens, got %" PRIuMAX ), tokens .nr );
95+ goto cleanup ;
96+ }
97+
98+ command = tokens .items [0 ].string ;
99+
100+ if (!git_parse_int (tokens .items [1 ].string , & version )) {
101+ res = error (_ ("unable to parse '%s' to integer" ),
102+ tokens .items [1 ].string );
103+ goto cleanup ;
104+ }
105+
106+ argc = tokens .nr - 2 ;
107+ CALLOC_ARRAY (argv , argc + 1 );
108+
109+ for (size_t i = 2 ; i < tokens .nr ; i ++ )
110+ argv [i - 2 ] = tokens .items [i ].string ;
111+
112+ for (size_t i = 0 ; i < COMMAND_COUNT ; i ++ ) {
113+ if (!commands [i ].name [0 ] || /* unknown command */
114+ !strcmp (command , commands [i ].name )) {
115+ res = commands [i ].fn (repo , version , argc , argv );
116+ goto cleanup ;
117+ }
118+ }
119+
120+ BUG (_ ("scanned to end of command list, including 'unknown_command'" ));
121+
122+ cleanup :
123+ free (argv );
124+ strbuf_reset (& line );
125+ string_list_clear (& tokens , 0 );
126+ return res ;
127+ }
128+
12129int cmd_config_batch (int argc ,
13130 const char * * argv ,
14131 const char * prefix ,
15132 struct repository * repo )
16133{
134+ int res = 0 ;
17135 struct option options [] = {
18136 OPT_END (),
19137 };
@@ -26,5 +144,9 @@ int cmd_config_batch(int argc,
26144
27145 repo_config (repo , git_default_config , NULL );
28146
29- return 0 ;
147+ while (!(res = process_command (repo )));
148+
149+ if (res == 1 )
150+ return 0 ;
151+ die (_ ("an unrecoverable error occurred during command execution" ));
30152}
0 commit comments