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`
This commit is contained in:
commit
00bb99c424
@ -177,6 +177,10 @@ Valid `<type>`'s include:
|
||||
~/` from the command line to let your shell do the expansion.)
|
||||
- 'expiry-date': canonicalize by converting from a fixed or relative date-string
|
||||
to a timestamp. This specifier has no effect when setting the value.
|
||||
- 'color': When getting a value, canonicalize by converting to an ANSI color
|
||||
escape sequence. When setting a value, a sanity-check is performed to ensure
|
||||
that the given value is canonicalize-able as an ANSI color, but it is written
|
||||
as-is.
|
||||
+
|
||||
|
||||
--bool::
|
||||
@ -228,6 +232,8 @@ Valid `<type>`'s include:
|
||||
output it as the ANSI color escape sequence to the standard
|
||||
output. The optional `default` parameter is used instead, if
|
||||
there is no color configured for `name`.
|
||||
+
|
||||
`--type=color [--default=<default>]` is preferred over `--get-color`.
|
||||
|
||||
-e::
|
||||
--edit::
|
||||
@ -240,6 +246,10 @@ Valid `<type>`'s include:
|
||||
using `--file`, `--global`, etc) and `on` when searching all
|
||||
config files.
|
||||
|
||||
--default <value>::
|
||||
When using `--get`, and the requested variable is not found, behave as if
|
||||
<value> were the value assigned to the that variable.
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
`pager.config` is only respected when listing configuration, i.e., when
|
||||
|
@ -26,6 +26,7 @@ static char term = '\n';
|
||||
static int use_global_config, use_system_config, use_local_config;
|
||||
static struct git_config_source given_config_source;
|
||||
static int actions, type;
|
||||
static char *default_value;
|
||||
static int end_null;
|
||||
static int respect_includes_opt = -1;
|
||||
static struct config_options config_options;
|
||||
@ -60,6 +61,7 @@ static int show_origin;
|
||||
#define TYPE_BOOL_OR_INT 3
|
||||
#define TYPE_PATH 4
|
||||
#define TYPE_EXPIRY_DATE 5
|
||||
#define TYPE_COLOR 6
|
||||
|
||||
#define OPT_CALLBACK_VALUE(s, l, v, h, i) \
|
||||
{ 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,
|
||||
new_type = TYPE_PATH;
|
||||
else if (!strcmp(arg, "expiry-date"))
|
||||
new_type = TYPE_EXPIRY_DATE;
|
||||
else if (!strcmp(arg, "color"))
|
||||
new_type = TYPE_COLOR;
|
||||
else
|
||||
die(_("unrecognized --type argument, %s"), arg);
|
||||
}
|
||||
@ -149,6 +153,7 @@ static struct option builtin_config_options[] = {
|
||||
OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
|
||||
OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
|
||||
OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
|
||||
OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
@ -228,6 +233,11 @@ static int format_config(struct strbuf *buf, const char *key_, const char *value
|
||||
if (git_config_expiry_date(&t, key_, value_) < 0)
|
||||
return -1;
|
||||
strbuf_addf(buf, "%"PRItime, t);
|
||||
} else if (type == TYPE_COLOR) {
|
||||
char v[COLOR_MAXLEN];
|
||||
if (git_config_color(v, key_, value_) < 0)
|
||||
return -1;
|
||||
strbuf_addstr(buf, v);
|
||||
} else if (value_) {
|
||||
strbuf_addstr(buf, value_);
|
||||
} else {
|
||||
@ -313,6 +323,16 @@ static int get_value(const char *key_, const char *regex_)
|
||||
config_with_options(collect_config, &values,
|
||||
&given_config_source, &config_options);
|
||||
|
||||
if (!values.nr && default_value) {
|
||||
struct strbuf *item;
|
||||
ALLOC_GROW(values.items, values.nr + 1, values.alloc);
|
||||
item = &values.items[values.nr++];
|
||||
strbuf_init(item, 0);
|
||||
if (format_config(item, key_, default_value) < 0)
|
||||
die(_("failed to format default config value: %s"),
|
||||
default_value);
|
||||
}
|
||||
|
||||
ret = !values.nr;
|
||||
|
||||
for (i = 0; i < values.nr; i++) {
|
||||
@ -363,6 +383,20 @@ static char *normalize_value(const char *key, const char *value)
|
||||
else
|
||||
return xstrdup(v ? "true" : "false");
|
||||
}
|
||||
if (type == TYPE_COLOR) {
|
||||
char v[COLOR_MAXLEN];
|
||||
if (git_config_color(v, key, value))
|
||||
die("cannot parse color '%s'", value);
|
||||
|
||||
/*
|
||||
* The contents of `v` now contain an ANSI escape
|
||||
* sequence, not suitable for including within a
|
||||
* configuration file. Treat the above as a
|
||||
* "sanity-check", and return the given value, which we
|
||||
* know is representable as valid color code.
|
||||
*/
|
||||
return xstrdup(value);
|
||||
}
|
||||
|
||||
die("BUG: cannot normalize type %d", type);
|
||||
}
|
||||
@ -651,6 +685,12 @@ int cmd_config(int argc, const char **argv, const char *prefix)
|
||||
usage_with_options(builtin_config_usage, builtin_config_options);
|
||||
}
|
||||
|
||||
if (default_value && !(actions & ACTION_GET)) {
|
||||
error("--default is only applicable to --get");
|
||||
usage_with_options(builtin_config_usage,
|
||||
builtin_config_options);
|
||||
}
|
||||
|
||||
if (actions & PAGING_ACTIONS)
|
||||
setup_auto_pager("config", 1);
|
||||
|
||||
|
10
config.c
10
config.c
@ -16,6 +16,7 @@
|
||||
#include "string-list.h"
|
||||
#include "utf8.h"
|
||||
#include "dir.h"
|
||||
#include "color.h"
|
||||
|
||||
struct config_source {
|
||||
struct config_source *prev;
|
||||
@ -1067,6 +1068,15 @@ int git_config_expiry_date(timestamp_t *timestamp, const char *var, const char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_config_color(char *dest, const char *var, const char *value)
|
||||
{
|
||||
if (!value)
|
||||
return config_error_nonbool(var);
|
||||
if (color_parse(value, dest) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int git_default_core_config(const char *var, const char *value)
|
||||
{
|
||||
/* This needs a better name */
|
||||
|
1
config.h
1
config.h
@ -84,6 +84,7 @@ extern int git_config_bool(const char *, const char *);
|
||||
extern int git_config_string(const char **, const char *, const char *);
|
||||
extern int git_config_pathname(const char **, const char *, const char *);
|
||||
extern int git_config_expiry_date(timestamp_t *, const char *, const char *);
|
||||
extern int git_config_color(char *, const char *, const char *);
|
||||
extern int git_config_set_in_file_gently(const char *, const char *, const char *);
|
||||
extern void git_config_set_in_file(const char *, const char *, const char *);
|
||||
extern int git_config_set_gently(const char *, const char *);
|
||||
|
@ -933,6 +933,36 @@ test_expect_success 'get --expiry-date' '
|
||||
test_must_fail git config --expiry-date date.invalid1
|
||||
'
|
||||
|
||||
test_expect_success 'get --type=color' '
|
||||
rm .git/config &&
|
||||
git config foo.color "red" &&
|
||||
git config --get --type=color foo.color >actual.raw &&
|
||||
test_decode_color <actual.raw >actual &&
|
||||
echo "<RED>" >expect &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect << EOF
|
||||
[foo]
|
||||
color = red
|
||||
EOF
|
||||
|
||||
test_expect_success 'set --type=color' '
|
||||
rm .git/config &&
|
||||
git config --type=color foo.color "red" &&
|
||||
test_cmp expect .git/config
|
||||
'
|
||||
|
||||
test_expect_success 'get --type=color barfs on non-color' '
|
||||
echo "[foo]bar=not-a-color" >.git/config &&
|
||||
test_must_fail git config --get --type=color foo.bar
|
||||
'
|
||||
|
||||
test_expect_success 'set --type=color barfs on non-color' '
|
||||
test_must_fail git config --type=color foo.color "not-a-color" 2>error &&
|
||||
test_i18ngrep "cannot parse color" error
|
||||
'
|
||||
|
||||
cat > expect << EOF
|
||||
[quote]
|
||||
leading = " test"
|
||||
|
36
t/t1310-config-default.sh
Executable file
36
t/t1310-config-default.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='Test git config in different settings (with --default)'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'uses --default when entry missing' '
|
||||
echo quux >expect &&
|
||||
git config -f config --default=quux core.foo >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'does not use --default when entry present' '
|
||||
echo bar >expect &&
|
||||
git -c core.foo=bar config --default=baz core.foo >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'canonicalizes --default with appropriate type' '
|
||||
echo true >expect &&
|
||||
git config -f config --default=yes --bool core.foo >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'dies when --default cannot be parsed' '
|
||||
test_must_fail git config -f config --type=expiry-date --default=x --get \
|
||||
not.a.section 2>error &&
|
||||
test_i18ngrep "failed to format default config value" error
|
||||
'
|
||||
|
||||
test_expect_success 'does not allow --default without --get' '
|
||||
test_must_fail git config --default=quux --unset a.section >output 2>&1 &&
|
||||
test_i18ngrep "\-\-default is only applicable to" output
|
||||
'
|
||||
|
||||
test_done
|
Loading…
Reference in New Issue
Block a user