Skip to content

Commit 00bb99c

Browse files
committed
Merge branch 'tb/config-default'
"git config --get" learned the "--default" option, to help the calling script. Building on top of the tb/config-type topic, the "git config" learns "--type=color" type. Taken together, you can do things like "git config --get foo.color --default blue" and get the ANSI color sequence for the color given to foo.color variable, or "blue" if the variable does not exist. * tb/config-default: builtin/config: introduce `color` type specifier config.c: introduce 'git_config_color' to parse ANSI colors builtin/config: introduce `--default`
2 parents e3e042b + 63e2a0f commit 00bb99c

File tree

6 files changed

+127
-0
lines changed

6 files changed

+127
-0
lines changed

Documentation/git-config.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ Valid `<type>`'s include:
177177
~/` from the command line to let your shell do the expansion.)
178178
- 'expiry-date': canonicalize by converting from a fixed or relative date-string
179179
to a timestamp. This specifier has no effect when setting the value.
180+
- 'color': When getting a value, canonicalize by converting to an ANSI color
181+
escape sequence. When setting a value, a sanity-check is performed to ensure
182+
that the given value is canonicalize-able as an ANSI color, but it is written
183+
as-is.
180184
+
181185

182186
--bool::
@@ -228,6 +232,8 @@ Valid `<type>`'s include:
228232
output it as the ANSI color escape sequence to the standard
229233
output. The optional `default` parameter is used instead, if
230234
there is no color configured for `name`.
235+
+
236+
`--type=color [--default=<default>]` is preferred over `--get-color`.
231237

232238
-e::
233239
--edit::
@@ -240,6 +246,10 @@ Valid `<type>`'s include:
240246
using `--file`, `--global`, etc) and `on` when searching all
241247
config files.
242248

249+
--default <value>::
250+
When using `--get`, and the requested variable is not found, behave as if
251+
<value> were the value assigned to the that variable.
252+
243253
CONFIGURATION
244254
-------------
245255
`pager.config` is only respected when listing configuration, i.e., when

builtin/config.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ static char term = '\n';
2626
static int use_global_config, use_system_config, use_local_config;
2727
static struct git_config_source given_config_source;
2828
static int actions, type;
29+
static char *default_value;
2930
static int end_null;
3031
static int respect_includes_opt = -1;
3132
static struct config_options config_options;
@@ -60,6 +61,7 @@ static int show_origin;
6061
#define TYPE_BOOL_OR_INT 3
6162
#define TYPE_PATH 4
6263
#define TYPE_EXPIRY_DATE 5
64+
#define TYPE_COLOR 6
6365

6466
#define OPT_CALLBACK_VALUE(s, l, v, h, i) \
6567
{ OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
@@ -93,6 +95,8 @@ static int option_parse_type(const struct option *opt, const char *arg,
9395
new_type = TYPE_PATH;
9496
else if (!strcmp(arg, "expiry-date"))
9597
new_type = TYPE_EXPIRY_DATE;
98+
else if (!strcmp(arg, "color"))
99+
new_type = TYPE_COLOR;
96100
else
97101
die(_("unrecognized --type argument, %s"), arg);
98102
}
@@ -149,6 +153,7 @@ static struct option builtin_config_options[] = {
149153
OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
150154
OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
151155
OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
156+
OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
152157
OPT_END(),
153158
};
154159

@@ -228,6 +233,11 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value
228233
if (git_config_expiry_date(&t, key_, value_) < 0)
229234
return -1;
230235
strbuf_addf(buf, "%"PRItime, t);
236+
} else if (type == TYPE_COLOR) {
237+
char v[COLOR_MAXLEN];
238+
if (git_config_color(v, key_, value_) < 0)
239+
return -1;
240+
strbuf_addstr(buf, v);
231241
} else if (value_) {
232242
strbuf_addstr(buf, value_);
233243
} else {
@@ -313,6 +323,16 @@ static int get_value(const char *key_, const char *regex_)
313323
config_with_options(collect_config, &values,
314324
&given_config_source, &config_options);
315325

326+
if (!values.nr && default_value) {
327+
struct strbuf *item;
328+
ALLOC_GROW(values.items, values.nr + 1, values.alloc);
329+
item = &values.items[values.nr++];
330+
strbuf_init(item, 0);
331+
if (format_config(item, key_, default_value) < 0)
332+
die(_("failed to format default config value: %s"),
333+
default_value);
334+
}
335+
316336
ret = !values.nr;
317337

318338
for (i = 0; i < values.nr; i++) {
@@ -363,6 +383,20 @@ static char *normalize_value(const char *key, const char *value)
363383
else
364384
return xstrdup(v ? "true" : "false");
365385
}
386+
if (type == TYPE_COLOR) {
387+
char v[COLOR_MAXLEN];
388+
if (git_config_color(v, key, value))
389+
die("cannot parse color '%s'", value);
390+
391+
/*
392+
* The contents of `v` now contain an ANSI escape
393+
* sequence, not suitable for including within a
394+
* configuration file. Treat the above as a
395+
* "sanity-check", and return the given value, which we
396+
* know is representable as valid color code.
397+
*/
398+
return xstrdup(value);
399+
}
366400

367401
die("BUG: cannot normalize type %d", type);
368402
}
@@ -651,6 +685,12 @@ int cmd_config(int argc, const char **argv, const char *prefix)
651685
usage_with_options(builtin_config_usage, builtin_config_options);
652686
}
653687

688+
if (default_value && !(actions & ACTION_GET)) {
689+
error("--default is only applicable to --get");
690+
usage_with_options(builtin_config_usage,
691+
builtin_config_options);
692+
}
693+
654694
if (actions & PAGING_ACTIONS)
655695
setup_auto_pager("config", 1);
656696

config.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "string-list.h"
1717
#include "utf8.h"
1818
#include "dir.h"
19+
#include "color.h"
1920

2021
struct config_source {
2122
struct config_source *prev;
@@ -1067,6 +1068,15 @@ int git_config_expiry_date(timestamp_t *timestamp, const char *var, const char *
10671068
return 0;
10681069
}
10691070

1071+
int git_config_color(char *dest, const char *var, const char *value)
1072+
{
1073+
if (!value)
1074+
return config_error_nonbool(var);
1075+
if (color_parse(value, dest) < 0)
1076+
return -1;
1077+
return 0;
1078+
}
1079+
10701080
static int git_default_core_config(const char *var, const char *value)
10711081
{
10721082
/* This needs a better name */

config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ extern int git_config_bool(const char *, const char *);
8484
extern int git_config_string(const char **, const char *, const char *);
8585
extern int git_config_pathname(const char **, const char *, const char *);
8686
extern int git_config_expiry_date(timestamp_t *, const char *, const char *);
87+
extern int git_config_color(char *, const char *, const char *);
8788
extern int git_config_set_in_file_gently(const char *, const char *, const char *);
8889
extern void git_config_set_in_file(const char *, const char *, const char *);
8990
extern int git_config_set_gently(const char *, const char *);

t/t1300-config.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,36 @@ test_expect_success 'get --expiry-date' '
933933
test_must_fail git config --expiry-date date.invalid1
934934
'
935935

936+
test_expect_success 'get --type=color' '
937+
rm .git/config &&
938+
git config foo.color "red" &&
939+
git config --get --type=color foo.color >actual.raw &&
940+
test_decode_color <actual.raw >actual &&
941+
echo "<RED>" >expect &&
942+
test_cmp expect actual
943+
'
944+
945+
cat >expect << EOF
946+
[foo]
947+
color = red
948+
EOF
949+
950+
test_expect_success 'set --type=color' '
951+
rm .git/config &&
952+
git config --type=color foo.color "red" &&
953+
test_cmp expect .git/config
954+
'
955+
956+
test_expect_success 'get --type=color barfs on non-color' '
957+
echo "[foo]bar=not-a-color" >.git/config &&
958+
test_must_fail git config --get --type=color foo.bar
959+
'
960+
961+
test_expect_success 'set --type=color barfs on non-color' '
962+
test_must_fail git config --type=color foo.color "not-a-color" 2>error &&
963+
test_i18ngrep "cannot parse color" error
964+
'
965+
936966
cat > expect << EOF
937967
[quote]
938968
leading = " test"

t/t1310-config-default.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/sh
2+
3+
test_description='Test git config in different settings (with --default)'
4+
5+
. ./test-lib.sh
6+
7+
test_expect_success 'uses --default when entry missing' '
8+
echo quux >expect &&
9+
git config -f config --default=quux core.foo >actual &&
10+
test_cmp expect actual
11+
'
12+
13+
test_expect_success 'does not use --default when entry present' '
14+
echo bar >expect &&
15+
git -c core.foo=bar config --default=baz core.foo >actual &&
16+
test_cmp expect actual
17+
'
18+
19+
test_expect_success 'canonicalizes --default with appropriate type' '
20+
echo true >expect &&
21+
git config -f config --default=yes --bool core.foo >actual &&
22+
test_cmp expect actual
23+
'
24+
25+
test_expect_success 'dies when --default cannot be parsed' '
26+
test_must_fail git config -f config --type=expiry-date --default=x --get \
27+
not.a.section 2>error &&
28+
test_i18ngrep "failed to format default config value" error
29+
'
30+
31+
test_expect_success 'does not allow --default without --get' '
32+
test_must_fail git config --default=quux --unset a.section >output 2>&1 &&
33+
test_i18ngrep "\-\-default is only applicable to" output
34+
'
35+
36+
test_done

0 commit comments

Comments
 (0)