Skip to content

Commit 7fd96b8

Browse files
committed
config-batch: add unset v1 command
Add a new 'unset' command with version 1 that mimics 'git config --unset' with optional regex pattern or '--fixed-value' arguments. Signed-off-by: Derrick Stolee <stolee@gmail.com>
1 parent 1a63402 commit 7fd96b8

File tree

3 files changed

+181
-7
lines changed

3 files changed

+181
-7
lines changed

Documentation/git-config-batch.adoc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,34 @@ set 1 success <scope> <key> <value>
135135
set 1 failed <scope> <key> <value>
136136
------------
137137

138+
`unset` version 1::
139+
The `unset` command removes a single value from a config file.
140+
It specifies which file by a `<scope>` parameter from among
141+
`system`, `global`, `local`, and `worktree`. The `<key>` is the
142+
next positional argument. There could be two additional
143+
arguments used to match specific config values, where the first
144+
is either `arg:regex` or `arg:fixed-value` to specify the type
145+
of match.
146+
+
147+
------------
148+
unset 1 <scope> <key>
149+
unset 1 <scope> <key> arg:regex <value-pattern>
150+
unset 1 <scope> <key> arg:fixed-value <value>
151+
------------
152+
+
153+
These uses will match the behavior of `git config --unset --<scope> <key>`
154+
with the additional arguments of `<value-pattern>` if `arg:regex` is
155+
given or `--fixed-value <value>` if `arg:fixed-value` is given.
156+
+
157+
The response of these commands will include a `success` message
158+
if matched values are found and removed as expected or `failed` if an
159+
unexpected failure occurs:
160+
+
161+
------------
162+
unset 1 success <scope> <key>
163+
unset 1 failed <scope> <key>
164+
------------
165+
138166
NUL-Terminated Format
139167
~~~~~~~~~~~~~~~~~~~~~
140168

builtin/config-batch.c

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ static int zformat = 0;
1717
#define HELP_COMMAND "help"
1818
#define GET_COMMAND "get"
1919
#define SET_COMMAND "set"
20+
#define UNSET_COMMAND "unset"
2021
#define COMMAND_PARSE_ERROR "command_parse_error"
2122

2223
static void print_word(const char *word, int start)
@@ -445,6 +446,99 @@ static int set_command_1(struct repository *repo,
445446
return res;
446447
}
447448

449+
/**
450+
* 'unset' command, version 1.
451+
*
452+
* Positional arguments should be of the form:
453+
*
454+
* [0] scope ("system", "global", "local", or "worktree")
455+
* [1] config key
456+
* [2] config value
457+
* [3*] match ("regex", "fixed-value")
458+
* [4*] value regex OR value string
459+
*
460+
* [N*] indicates optional parameters that are not needed.
461+
*/
462+
static int unset_command_1(struct repository *repo,
463+
const char *prefix,
464+
char *data,
465+
size_t data_len)
466+
{
467+
int res = 0, err = 0, flags = 0;
468+
enum config_scope scope = CONFIG_SCOPE_UNKNOWN;
469+
char *token = NULL, *key = NULL, *value_pattern = NULL;
470+
size_t token_len;
471+
struct config_location_options locopts = CONFIG_LOCATION_OPTIONS_INIT;
472+
473+
if (!parse_token(&data, &data_len, &token, &err) || err)
474+
goto parse_error;
475+
476+
if (parse_scope(token, &scope) ||
477+
scope == CONFIG_SCOPE_UNKNOWN ||
478+
scope == CONFIG_SCOPE_SUBMODULE ||
479+
scope == CONFIG_SCOPE_COMMAND)
480+
goto parse_error;
481+
482+
if (!parse_token(&data, &data_len, &key, &err) || err)
483+
goto parse_error;
484+
485+
token_len = parse_token(&data, &data_len, &token, &err);
486+
if (err)
487+
goto parse_error;
488+
489+
if (token_len && !strncmp(token, "arg:", 4)) {
490+
if (!strcmp(token + 4, "fixed-value"))
491+
flags |= CONFIG_FLAGS_FIXED_VALUE;
492+
/* no special logic for arg:regex. */
493+
else if (strcmp(token + 4, "regex"))
494+
goto parse_error; /* unknown arg. */
495+
496+
/* Use the remaining data as the value string. */
497+
if (!zformat)
498+
value_pattern = data;
499+
else {
500+
parse_token(&data, &data_len, &value_pattern, &err);
501+
if (err)
502+
goto parse_error;
503+
}
504+
} else if (token_len) {
505+
/*
506+
* If we have remaining tokens not starting in "arg:",
507+
* then we don't understand them.
508+
*/
509+
goto parse_error;
510+
}
511+
512+
if (location_options_set_scope(&locopts, scope))
513+
goto parse_error;
514+
location_options_init(repo, &locopts, prefix);
515+
516+
res = repo_config_set_multivar_in_file_gently(
517+
repo,
518+
locopts.source.file,
519+
key,
520+
/* value */ NULL,
521+
value_pattern,
522+
/* comment */ NULL,
523+
flags);
524+
525+
if (res)
526+
res = emit_response(UNSET_COMMAND, "1", "failure",
527+
scope_str(scope), key, NULL);
528+
else
529+
res = emit_response(UNSET_COMMAND, "1", "success",
530+
scope_str(scope), key, NULL);
531+
532+
goto cleanup;
533+
534+
parse_error:
535+
res = command_parse_error(UNSET_COMMAND);
536+
537+
cleanup:
538+
location_options_release(&locopts);
539+
return res;
540+
}
541+
448542
struct command {
449543
const char *name;
450544
command_fn fn;
@@ -467,6 +561,11 @@ static struct command commands[] = {
467561
.fn = set_command_1,
468562
.version = 1,
469563
},
564+
{
565+
.name = UNSET_COMMAND,
566+
.fn = unset_command_1,
567+
.version = 1,
568+
},
470569
/* unknown_command must be last. */
471570
{
472571
.name = "",

t/t1312-config-batch.sh

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,11 @@ test_expect_success 'help command' '
4747
echo "help 1" >in &&
4848
4949
cat >expect <<-\EOF &&
50-
help 1 count 3
50+
help 1 count 4
5151
help 1 help 1
5252
help 1 get 1
5353
help 1 set 1
54+
help 1 unset 1
5455
EOF
5556
5657
git config-batch >out <in &&
@@ -64,10 +65,11 @@ test_expect_success 'help -z' '
6465
EOF
6566
6667
cat >expect <<-\EOF &&
67-
4:help 1:1 5:count 1:3
68+
4:help 1:1 5:count 1:4
6869
4:help 1:1 4:help 1:1
6970
4:help 1:1 3:get 1:1
7071
4:help 1:1 3:set 1:1
72+
4:help 1:1 5:unset 1:1
7173
15:unknown_command
7274
EOF
7375
@@ -295,15 +297,60 @@ test_expect_success 'set config by scope with -z' '
295297
test_cmp expect-values values
296298
'
297299

298-
test_expect_success 'read/write interactions in sequence' '
299-
test_when_finished git config remove-section test.rw &&
300+
test_expect_success 'unset config by scope and filter' '
301+
GIT_CONFIG_SYSTEM=system-config-file &&
302+
GIT_CONFIG_NOSYSTEM=0 &&
303+
GIT_CONFIG_GLOBAL=global-config-file &&
304+
export GIT_CONFIG_SYSTEM &&
305+
export GIT_CONFIG_NOSYSTEM &&
306+
export GIT_CONFIG_GLOBAL &&
300307
308+
cat >in <<-\EOF &&
309+
set 1 system test.unset.key system
310+
set 1 global test.unset.key global
311+
set 1 local test.unset.key local with spaces
312+
set 1 worktree test.unset.key worktree
313+
unset 1 system test.unset.key
314+
unset 1 global test.unset.key arg:regex g.*
315+
unset 1 local test.unset.key arg:fixed-value local with spaces
316+
unset 1 worktree test.unset.key arg:fixed-value submodule
317+
unset 1 worktree test.unset.key arg:regex l.*
318+
EOF
319+
320+
cat >expect <<-\EOF &&
321+
set 1 success system test.unset.key system
322+
set 1 success global test.unset.key global
323+
set 1 success local test.unset.key local with spaces
324+
set 1 success worktree test.unset.key worktree
325+
unset 1 success system test.unset.key
326+
unset 1 success global test.unset.key
327+
unset 1 success local test.unset.key
328+
unset 1 failure worktree test.unset.key
329+
unset 1 failure worktree test.unset.key
330+
EOF
331+
332+
git config-batch <in >out 2>err &&
333+
334+
test_must_be_empty err &&
335+
test_cmp expect out &&
336+
337+
cat >expect-values <<-EOF &&
338+
file:.git/config.worktree worktree
339+
EOF
340+
341+
git config get --show-origin --regexp --all test.unset.key >values &&
342+
test_cmp expect-values values
343+
'
344+
345+
test_expect_success 'read/write interactions in sequence' '
301346
cat >in <<-\EOF &&
302347
get 1 local test.rw.missing
303348
set 1 local test.rw.found found
304349
get 1 local test.rw.found
305350
set 1 local test.rw.found updated
306351
get 1 local test.rw.found
352+
unset 1 local test.rw.found arg:fixed-value updated
353+
get 1 local test.rw.found
307354
EOF
308355
309356
cat >expect <<-\EOF &&
@@ -312,14 +359,14 @@ test_expect_success 'read/write interactions in sequence' '
312359
get 1 found test.rw.found local found
313360
set 1 success local test.rw.found updated
314361
get 1 found test.rw.found local updated
362+
unset 1 success local test.rw.found
363+
get 1 missing test.rw.found
315364
EOF
316365
317366
git config-batch <in >out 2>err &&
318367
319368
test_must_be_empty err &&
320-
test_cmp expect out &&
321-
322-
test_cmp_config updated test.rw.found
369+
test_cmp expect out
323370
'
324371

325372
test_done

0 commit comments

Comments
 (0)