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.)
|
~/` from the command line to let your shell do the expansion.)
|
||||||
- 'expiry-date': canonicalize by converting from a fixed or relative date-string
|
- 'expiry-date': canonicalize by converting from a fixed or relative date-string
|
||||||
to a timestamp. This specifier has no effect when setting the value.
|
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::
|
--bool::
|
||||||
@ -228,6 +232,8 @@ Valid `<type>`'s include:
|
|||||||
output it as the ANSI color escape sequence to the standard
|
output it as the ANSI color escape sequence to the standard
|
||||||
output. The optional `default` parameter is used instead, if
|
output. The optional `default` parameter is used instead, if
|
||||||
there is no color configured for `name`.
|
there is no color configured for `name`.
|
||||||
|
+
|
||||||
|
`--type=color [--default=<default>]` is preferred over `--get-color`.
|
||||||
|
|
||||||
-e::
|
-e::
|
||||||
--edit::
|
--edit::
|
||||||
@ -240,6 +246,10 @@ Valid `<type>`'s include:
|
|||||||
using `--file`, `--global`, etc) and `on` when searching all
|
using `--file`, `--global`, etc) and `on` when searching all
|
||||||
config files.
|
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
|
CONFIGURATION
|
||||||
-------------
|
-------------
|
||||||
`pager.config` is only respected when listing configuration, i.e., when
|
`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 int use_global_config, use_system_config, use_local_config;
|
||||||
static struct git_config_source given_config_source;
|
static struct git_config_source given_config_source;
|
||||||
static int actions, type;
|
static int actions, type;
|
||||||
|
static char *default_value;
|
||||||
static int end_null;
|
static int end_null;
|
||||||
static int respect_includes_opt = -1;
|
static int respect_includes_opt = -1;
|
||||||
static struct config_options config_options;
|
static struct config_options config_options;
|
||||||
@ -60,6 +61,7 @@ static int show_origin;
|
|||||||
#define TYPE_BOOL_OR_INT 3
|
#define TYPE_BOOL_OR_INT 3
|
||||||
#define TYPE_PATH 4
|
#define TYPE_PATH 4
|
||||||
#define TYPE_EXPIRY_DATE 5
|
#define TYPE_EXPIRY_DATE 5
|
||||||
|
#define TYPE_COLOR 6
|
||||||
|
|
||||||
#define OPT_CALLBACK_VALUE(s, l, v, h, i) \
|
#define OPT_CALLBACK_VALUE(s, l, v, h, i) \
|
||||||
{ OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
|
{ 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;
|
new_type = TYPE_PATH;
|
||||||
else if (!strcmp(arg, "expiry-date"))
|
else if (!strcmp(arg, "expiry-date"))
|
||||||
new_type = TYPE_EXPIRY_DATE;
|
new_type = TYPE_EXPIRY_DATE;
|
||||||
|
else if (!strcmp(arg, "color"))
|
||||||
|
new_type = TYPE_COLOR;
|
||||||
else
|
else
|
||||||
die(_("unrecognized --type argument, %s"), arg);
|
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, "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, "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_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(),
|
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)
|
if (git_config_expiry_date(&t, key_, value_) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
strbuf_addf(buf, "%"PRItime, t);
|
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_) {
|
} else if (value_) {
|
||||||
strbuf_addstr(buf, value_);
|
strbuf_addstr(buf, value_);
|
||||||
} else {
|
} else {
|
||||||
@ -313,6 +323,16 @@ static int get_value(const char *key_, const char *regex_)
|
|||||||
config_with_options(collect_config, &values,
|
config_with_options(collect_config, &values,
|
||||||
&given_config_source, &config_options);
|
&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;
|
ret = !values.nr;
|
||||||
|
|
||||||
for (i = 0; i < values.nr; i++) {
|
for (i = 0; i < values.nr; i++) {
|
||||||
@ -363,6 +383,20 @@ static char *normalize_value(const char *key, const char *value)
|
|||||||
else
|
else
|
||||||
return xstrdup(v ? "true" : "false");
|
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);
|
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);
|
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)
|
if (actions & PAGING_ACTIONS)
|
||||||
setup_auto_pager("config", 1);
|
setup_auto_pager("config", 1);
|
||||||
|
|
||||||
|
10
config.c
10
config.c
@ -16,6 +16,7 @@
|
|||||||
#include "string-list.h"
|
#include "string-list.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
|
#include "color.h"
|
||||||
|
|
||||||
struct config_source {
|
struct config_source {
|
||||||
struct config_source *prev;
|
struct config_source *prev;
|
||||||
@ -1067,6 +1068,15 @@ int git_config_expiry_date(timestamp_t *timestamp, const char *var, const char *
|
|||||||
return 0;
|
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)
|
static int git_default_core_config(const char *var, const char *value)
|
||||||
{
|
{
|
||||||
/* This needs a better name */
|
/* 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_string(const char **, const char *, const char *);
|
||||||
extern int git_config_pathname(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_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 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 void git_config_set_in_file(const char *, const char *, const char *);
|
||||||
extern int git_config_set_gently(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_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
|
cat > expect << EOF
|
||||||
[quote]
|
[quote]
|
||||||
leading = " test"
|
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