Skip to content

Commit fdeef53

Browse files
committed
config-batch: add 'set' v1 command
This new command is intended for single-value assignments to a specific chosen scope. More complicated versions of the 'git config set' command will be incorporated into future commands. Signed-off-by: Derrick Stolee <stolee@gmail.com>
1 parent 60443c5 commit fdeef53

File tree

5 files changed

+217
-2
lines changed

5 files changed

+217
-2
lines changed

Documentation/git-config-batch.adoc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,30 @@ get 1 missing <key> [<value-pattern>|<value>]
111111
where `<value-pattern>` or `<value>` is only supplied if provided in
112112
the command.
113113

114+
`set` version 1::
115+
The `set` command writes a single key-value pair to a config
116+
file. It specifies which file by a `<scope>` parameter from
117+
among `system`, `global`, `local`, and `worktree`. The `<key>`
118+
is the next positional argument. The remaining data in the line
119+
is provided as the `<value>` to assign the config.
120+
+
121+
------------
122+
set 1 <scope> <key> <value>
123+
------------
124+
+
125+
These uses will match the behavior of `git config --set --<scope> <key>
126+
<value>`. Note that replacing all values with the `--all` option or
127+
matching specific value patterns are not supported by this command.
128+
+
129+
The response of these commands will include a `success` message if the
130+
value is written as expected or `failed` if an unexpected failure
131+
occurs:
132+
+
133+
------------
134+
set 1 success <scope> <key> <value>
135+
set 1 failed <scope> <key> <value>
136+
------------
137+
114138
NUL-Terminated Format
115139
~~~~~~~~~~~~~~~~~~~~~
116140

builtin/config-batch.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ static int zformat = 0;
1616
#define UNKNOWN_COMMAND "unknown_command"
1717
#define HELP_COMMAND "help"
1818
#define GET_COMMAND "get"
19+
#define SET_COMMAND "set"
1920
#define COMMAND_PARSE_ERROR "command_parse_error"
2021

2122
static void print_word(const char *word, int start)
@@ -379,6 +380,71 @@ static int get_command_1(struct repository *repo,
379380
return res;
380381
}
381382

383+
384+
/**
385+
* 'set' command, version 1.
386+
*
387+
* Positional arguments should be of the form:
388+
*
389+
* [0] scope ("system", "global", "local", or "worktree")
390+
* [1] config key
391+
* [2] config value
392+
*/
393+
static int set_command_1(struct repository *repo,
394+
const char *prefix,
395+
char *data,
396+
size_t data_len)
397+
{
398+
int res = 0, err = 0;
399+
enum config_scope scope = CONFIG_SCOPE_UNKNOWN;
400+
char *token = NULL, *key = NULL, *value = NULL;
401+
struct config_location_options locopts = CONFIG_LOCATION_OPTIONS_INIT;
402+
403+
if (!parse_token(&data, &data_len, &token, &err) || err)
404+
goto parse_error;
405+
406+
if (parse_scope(token, &scope) ||
407+
scope == CONFIG_SCOPE_UNKNOWN ||
408+
scope == CONFIG_SCOPE_SUBMODULE ||
409+
scope == CONFIG_SCOPE_COMMAND)
410+
goto parse_error;
411+
412+
if (!parse_token(&data, &data_len, &key, &err) || err)
413+
goto parse_error;
414+
415+
/* Use the remaining data as the value string. */
416+
if (!zformat)
417+
value = data;
418+
else {
419+
parse_token(&data, &data_len, &value, &err);
420+
if (err)
421+
goto parse_error;
422+
}
423+
424+
if (location_options_set_scope(&locopts, scope))
425+
goto parse_error;
426+
location_options_init(repo, &locopts, prefix);
427+
428+
res = repo_config_set_in_file_gently(repo, locopts.source.file,
429+
key, NULL, value);
430+
431+
if (res)
432+
res = emit_response(SET_COMMAND, "1", "failure",
433+
scope_str(scope), key, value, NULL);
434+
else
435+
res = emit_response(SET_COMMAND, "1", "success",
436+
scope_str(scope), key, value, NULL);
437+
438+
goto cleanup;
439+
440+
parse_error:
441+
res = command_parse_error(SET_COMMAND);
442+
443+
cleanup:
444+
location_options_release(&locopts);
445+
return res;
446+
}
447+
382448
struct command {
383449
const char *name;
384450
command_fn fn;
@@ -396,6 +462,11 @@ static struct command commands[] = {
396462
.fn = get_command_1,
397463
.version = 1,
398464
},
465+
{
466+
.name = SET_COMMAND,
467+
.fn = set_command_1,
468+
.version = 1,
469+
},
399470
/* unknown_command must be last. */
400471
{
401472
.name = "",

config.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3594,6 +3594,33 @@ int lookup_config(const char **mapping, int nr_mapping, const char *var)
35943594
return -1;
35953595
}
35963596

3597+
int location_options_set_scope(struct config_location_options *opts,
3598+
enum config_scope scope)
3599+
{
3600+
switch (scope) {
3601+
case CONFIG_SCOPE_SYSTEM:
3602+
opts->use_system_config = 1;
3603+
break;
3604+
3605+
case CONFIG_SCOPE_GLOBAL:
3606+
opts->use_global_config = 1;
3607+
break;
3608+
3609+
case CONFIG_SCOPE_LOCAL:
3610+
opts->use_local_config = 1;
3611+
break;
3612+
3613+
case CONFIG_SCOPE_WORKTREE:
3614+
opts->use_worktree_config = 1;
3615+
break;
3616+
3617+
default:
3618+
return -1;
3619+
}
3620+
3621+
return 0;
3622+
}
3623+
35973624
void location_options_init(struct repository *repo,
35983625
struct config_location_options *opts,
35993626
const char *prefix)

config.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@ struct config_location_options {
180180
.respect_includes_opt = -1, \
181181
}
182182

183+
int location_options_set_scope(struct config_location_options *opts,
184+
enum config_scope scope);
185+
183186
void location_options_init(struct repository *repo,
184187
struct config_location_options *opts,
185188
const char *prefix);

t/t1312-config-batch.sh

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ test_expect_success 'help command' '
4747
echo "help 1" >in &&
4848
4949
cat >expect <<-\EOF &&
50-
help 1 count 2
50+
help 1 count 3
5151
help 1 help 1
5252
help 1 get 1
53+
help 1 set 1
5354
EOF
5455
5556
git config-batch >out <in &&
@@ -63,9 +64,10 @@ test_expect_success 'help -z' '
6364
EOF
6465
6566
cat >expect <<-\EOF &&
66-
4:help 1:1 5:count 1:2
67+
4:help 1:1 5:count 1:3
6768
4:help 1:1 4:help 1:1
6869
4:help 1:1 3:get 1:1
70+
4:help 1:1 3:set 1:1
6971
15:unknown_command
7072
EOF
7173
@@ -205,4 +207,92 @@ test_expect_success 'get config with -z' '
205207
test_cmp expect out
206208
'
207209

210+
test_expect_success 'set config by scope' '
211+
test_when_finished git config remove-section test.set &&
212+
GIT_CONFIG_SYSTEM=system-config-file &&
213+
GIT_CONFIG_NOSYSTEM=0 &&
214+
GIT_CONFIG_GLOBAL=global-config-file &&
215+
export GIT_CONFIG_SYSTEM &&
216+
export GIT_CONFIG_NOSYSTEM &&
217+
export GIT_CONFIG_GLOBAL &&
218+
219+
cat >in <<-\EOF &&
220+
set 1 system test.set.system system
221+
set 1 global test.set.global global
222+
set 1 local test.set.local local with spaces
223+
set 1 worktree test.set.worktree worktree
224+
set 1 submodule test.set.submodule submodule
225+
set 1 command test.set.command command
226+
set 1 inherited test.set.inherited inherited
227+
EOF
228+
229+
cat >expect <<-\EOF &&
230+
set 1 success system test.set.system system
231+
set 1 success global test.set.global global
232+
set 1 success local test.set.local local with spaces
233+
set 1 success worktree test.set.worktree worktree
234+
command_parse_error set
235+
command_parse_error set
236+
command_parse_error set
237+
EOF
238+
239+
git config-batch <in >out 2>err &&
240+
241+
test_must_be_empty err &&
242+
test_cmp expect out &&
243+
244+
cat >expect-values <<-EOF &&
245+
file:system-config-file system
246+
file:global-config-file global
247+
file:.git/config local with spaces
248+
file:.git/config.worktree worktree
249+
EOF
250+
251+
git config get --show-origin --regexp --all test.set.* >values &&
252+
test_cmp expect-values values
253+
'
254+
255+
test_expect_success 'set config by scope with -z' '
256+
test_when_finished git config remove-section test.set &&
257+
GIT_CONFIG_SYSTEM=system-config-file &&
258+
GIT_CONFIG_NOSYSTEM=0 &&
259+
GIT_CONFIG_GLOBAL=global-config-file &&
260+
export GIT_CONFIG_SYSTEM &&
261+
export GIT_CONFIG_NOSYSTEM &&
262+
export GIT_CONFIG_GLOBAL &&
263+
264+
cat >in <<-\EOF &&
265+
3:set NUL 1:1 NUL 6:system NUL 15:test.set.system NUL 6:system NUL NUL
266+
3:set NUL 1:1 NUL 6:global NUL 15:test.set.global NUL 6:global NUL NUL
267+
3:set NUL 1:1 NUL 5:local NUL 14:test.set.local NUL 17:local with spaces NUL NUL
268+
3:set NUL 1:1 NUL 8:worktree NUL 17:test.set.worktree NUL 8:worktree NUL NUL
269+
3:set NUL 1:1 NUL 9:submodule NUL 18:test.set.submodule NUL 9:submodule NUL NUL
270+
3:set NUL 1:1 NUL 7:command NUL 16:test.set.command NUL 7:command NUL NUL
271+
3:set NUL 1:1 NUL 9:inherited NUL 18:test.set.inherited NUL 9:inherited NUL NUL
272+
EOF
273+
274+
cat >expect <<-\EOF &&
275+
3:set 1:1 7:success 6:system 15:test.set.system 6:system
276+
3:set 1:1 7:success 6:global 15:test.set.global 6:global
277+
3:set 1:1 7:success 5:local 14:test.set.local 17:local with spaces
278+
3:set 1:1 7:success 8:worktree 17:test.set.worktree 8:worktree
279+
19:command_parse_error 3:set
280+
19:command_parse_error 3:set
281+
19:command_parse_error 3:set
282+
EOF
283+
284+
test_zformat git config-batch -z >out <in &&
285+
test_cmp expect out &&
286+
287+
cat >expect-values <<-EOF &&
288+
file:system-config-file system
289+
file:global-config-file global
290+
file:.git/config local with spaces
291+
file:.git/config.worktree worktree
292+
EOF
293+
294+
git config get --show-origin --regexp --all test.set.* >values &&
295+
test_cmp expect-values values
296+
'
297+
208298
test_done

0 commit comments

Comments
 (0)