builtin/config: introduce `color` type specifier

As of this commit, the canonical way to retreive an ANSI-compatible color escape sequence from a configuration file is with the `--get-color` action. This is to allow Git to "fall back" on a default value for the color should the given section not exist in the specified configuration(s). With the addition of `--default`, this is no longer needed since: $ git config --default red --type=color core.section will be have exactly as: $ git config --get-color core.section red For consistency, let's introduce `--type=color` and encourage its use with `--default` together over `--get-color` alone. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed Apr 9, 2018 at 17:18 UTC 63e2a0f8e9cc3d66137a72e424a8b59f1c4dbd79
3 files changed +58
Documentation/git-config.txt
+6
@@ -177,6 +177,10 @@ Valid `<type>`'s include:
177 ~/` from the command line to let your shell do the expansion.)
178 - 'expiry-date': canonicalize by converting from a fixed or relative date-string
179 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.
184 +
185
186 --bool::
@@ -228,6 +232,8 @@ Valid `<type>`'s include:
232 output it as the ANSI color escape sequence to the standard
233 output. The optional `default` parameter is used instead, if
234 there is no color configured for `name`.
235 ++
236 +`--type=color [--default=<default>]` is preferred over `--get-color`.
237
238 -e::
239 --edit::
builtin/config.c
+22
@@ -61,6 +61,7 @@ static int show_origin;
61 #define TYPE_BOOL_OR_INT 3
62 #define TYPE_PATH 4
63 #define TYPE_EXPIRY_DATE 5
64 +#define TYPE_COLOR 6
65
66 #define OPT_CALLBACK_VALUE(s, l, v, h, i) \
67 { OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
@@ -94,6 +95,8 @@ static int option_parse_type(const struct option *opt, const char *arg,
95 new_type = TYPE_PATH;
96 else if (!strcmp(arg, "expiry-date"))
97 new_type = TYPE_EXPIRY_DATE;
98 + else if (!strcmp(arg, "color"))
99 + new_type = TYPE_COLOR;
100 else
101 die(_("unrecognized --type argument, %s"), arg);
102 }
@@ -230,6 +233,11 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value
233 if (git_config_expiry_date(&t, key_, value_) < 0)
234 return -1;
235 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);
241 } else if (value_) {
242 strbuf_addstr(buf, value_);
243 } else {
@@ -375,6 +383,20 @@ static char *normalize_value(const char *key, const char *value)
383 else
384 return xstrdup(v ? "true" : "false");
385 }
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 + }
400
401 die("BUG: cannot normalize type %d", type);
402 }
t/t1300-repo-config.sh
+30
@@ -931,6 +931,36 @@ test_expect_success 'get --expiry-date' '
931 test_must_fail git config --expiry-date date.invalid1
932 '
933
934 +test_expect_success 'get --type=color' '
935 + rm .git/config &&
936 + git config foo.color "red" &&
937 + git config --get --type=color foo.color >actual.raw &&
938 + test_decode_color <actual.raw >actual &&
939 + echo "<RED>" >expect &&
940 + test_cmp expect actual
941 +'
942 +
943 +cat >expect << EOF
944 +[foo]
945 + color = red
946 +EOF
947 +
948 +test_expect_success 'set --type=color' '
949 + rm .git/config &&
950 + git config --type=color foo.color "red" &&
951 + test_cmp expect .git/config
952 +'
953 +
954 +test_expect_success 'get --type=color barfs on non-color' '
955 + echo "[foo]bar=not-a-color" >.git/config &&
956 + test_must_fail git config --get --type=color foo.bar
957 +'
958 +
959 +test_expect_success 'set --type=color barfs on non-color' '
960 + test_must_fail git config --type=color foo.color "not-a-color" 2>error &&
961 + test_i18ngrep "cannot parse color" error
962 +'
963 +
964 cat > expect << EOF
965 [quote]
966 leading = " test"