Merge branch 'sg/config-name-only'

"git config --list" output was hard to parse when values consist of
multiple lines.  "--name-only" option is added to help this.

* sg/config-name-only:
  get_urlmatch: avoid useless strbuf write
  format_config: simplify buffer handling
  format_config: don't init strbuf
  config: restructure format_config() for better control flow
  completion: list variable names reliably with 'git config --name-only'
  config: add '--name-only' option to list only variable names
This commit is contained in:
Junio C Hamano 2015-08-31 15:38:50 -07:00
Родитель aecce6d0ef a92330d21c
Коммит fc9dfda1be
4 изменённых файлов: 74 добавлений и 60 удалений

Просмотреть файл

@ -14,13 +14,13 @@ SYNOPSIS
'git config' [<file-option>] [type] --replace-all name value [value_regex] 'git config' [<file-option>] [type] --replace-all name value [value_regex]
'git config' [<file-option>] [type] [-z|--null] --get name [value_regex] 'git config' [<file-option>] [type] [-z|--null] --get name [value_regex]
'git config' [<file-option>] [type] [-z|--null] --get-all name [value_regex] 'git config' [<file-option>] [type] [-z|--null] --get-all name [value_regex]
'git config' [<file-option>] [type] [-z|--null] --get-regexp name_regex [value_regex] 'git config' [<file-option>] [type] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
'git config' [<file-option>] [type] [-z|--null] --get-urlmatch name URL 'git config' [<file-option>] [type] [-z|--null] --get-urlmatch name URL
'git config' [<file-option>] --unset name [value_regex] 'git config' [<file-option>] --unset name [value_regex]
'git config' [<file-option>] --unset-all name [value_regex] 'git config' [<file-option>] --unset-all name [value_regex]
'git config' [<file-option>] --rename-section old_name new_name 'git config' [<file-option>] --rename-section old_name new_name
'git config' [<file-option>] --remove-section name 'git config' [<file-option>] --remove-section name
'git config' [<file-option>] [-z|--null] -l | --list 'git config' [<file-option>] [-z|--null] [--name-only] -l | --list
'git config' [<file-option>] --get-color name [default] 'git config' [<file-option>] --get-color name [default]
'git config' [<file-option>] --get-colorbool name [stdout-is-tty] 'git config' [<file-option>] --get-colorbool name [stdout-is-tty]
'git config' [<file-option>] -e | --edit 'git config' [<file-option>] -e | --edit
@ -159,7 +159,7 @@ See also <<FILES>>.
-l:: -l::
--list:: --list::
List all variables set in config file. List all variables set in config file, along with their values.
--bool:: --bool::
'git config' will ensure that the output is "true" or "false" 'git config' will ensure that the output is "true" or "false"
@ -190,6 +190,10 @@ See also <<FILES>>.
output without getting confused e.g. by values that output without getting confused e.g. by values that
contain line breaks. contain line breaks.
--name-only::
Output only the names of config variables for `--list` or
`--get-regexp`.
--get-colorbool name [stdout-is-tty]:: --get-colorbool name [stdout-is-tty]::
Find the color setting for `name` (e.g. `color.diff`) and output Find the color setting for `name` (e.g. `color.diff`) and output

Просмотреть файл

@ -13,6 +13,7 @@ static char *key;
static regex_t *key_regexp; static regex_t *key_regexp;
static regex_t *regexp; static regex_t *regexp;
static int show_keys; static int show_keys;
static int omit_values;
static int use_key_regexp; static int use_key_regexp;
static int do_all; static int do_all;
static int do_not_match; static int do_not_match;
@ -78,6 +79,7 @@ static struct option builtin_config_options[] = {
OPT_BIT(0, "path", &types, N_("value is a path (file or directory name)"), TYPE_PATH), OPT_BIT(0, "path", &types, N_("value is a path (file or directory name)"), TYPE_PATH),
OPT_GROUP(N_("Other")), OPT_GROUP(N_("Other")),
OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")), OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
OPT_BOOL(0, "includes", &respect_includes, N_("respect include directives on lookup")), OPT_BOOL(0, "includes", &respect_includes, N_("respect include directives on lookup")),
OPT_END(), OPT_END(),
}; };
@ -91,7 +93,7 @@ static void check_argc(int argc, int min, int max) {
static int show_all_config(const char *key_, const char *value_, void *cb) static int show_all_config(const char *key_, const char *value_, void *cb)
{ {
if (value_) if (!omit_values && value_)
printf("%s%c%s%c", key_, delim, value_, term); printf("%s%c%s%c", key_, delim, value_, term);
else else
printf("%s%c", key_, term); printf("%s%c", key_, term);
@ -106,48 +108,40 @@ struct strbuf_list {
static int format_config(struct strbuf *buf, const char *key_, const char *value_) static int format_config(struct strbuf *buf, const char *key_, const char *value_)
{ {
int must_free_vptr = 0; if (show_keys)
int must_print_delim = 0;
char value[256];
const char *vptr = value;
strbuf_init(buf, 0);
if (show_keys) {
strbuf_addstr(buf, key_); strbuf_addstr(buf, key_);
must_print_delim = 1; if (!omit_values) {
} if (show_keys)
if (types == TYPE_INT) strbuf_addch(buf, key_delim);
sprintf(value, "%"PRId64,
git_config_int64(key_, value_ ? value_ : ""));
else if (types == TYPE_BOOL)
vptr = git_config_bool(key_, value_) ? "true" : "false";
else if (types == TYPE_BOOL_OR_INT) {
int is_bool, v;
v = git_config_bool_or_int(key_, value_, &is_bool);
if (is_bool)
vptr = v ? "true" : "false";
else
sprintf(value, "%d", v);
} else if (types == TYPE_PATH) {
if (git_config_pathname(&vptr, key_, value_) < 0)
return -1;
must_free_vptr = 1;
} else if (value_) {
vptr = value_;
} else {
/* Just show the key name */
vptr = "";
must_print_delim = 0;
}
if (must_print_delim) if (types == TYPE_INT)
strbuf_addch(buf, key_delim); strbuf_addf(buf, "%"PRId64,
strbuf_addstr(buf, vptr); git_config_int64(key_, value_ ? value_ : ""));
else if (types == TYPE_BOOL)
strbuf_addstr(buf, git_config_bool(key_, value_) ?
"true" : "false");
else if (types == TYPE_BOOL_OR_INT) {
int is_bool, v;
v = git_config_bool_or_int(key_, value_, &is_bool);
if (is_bool)
strbuf_addstr(buf, v ? "true" : "false");
else
strbuf_addf(buf, "%d", v);
} else if (types == TYPE_PATH) {
const char *v;
if (git_config_pathname(&v, key_, value_) < 0)
return -1;
strbuf_addstr(buf, v);
free((char *)v);
} else if (value_) {
strbuf_addstr(buf, value_);
} else {
/* Just show the key name; back out delimiter */
if (show_keys)
strbuf_setlen(buf, buf->len - 1);
}
}
strbuf_addch(buf, term); strbuf_addch(buf, term);
if (must_free_vptr)
free((char *)vptr);
return 0; return 0;
} }
@ -164,6 +158,7 @@ static int collect_config(const char *key_, const char *value_, void *cb)
return 0; return 0;
ALLOC_GROW(values->items, values->nr + 1, values->alloc); ALLOC_GROW(values->items, values->nr + 1, values->alloc);
strbuf_init(&values->items[values->nr], 0);
return format_config(&values->items[values->nr++], key_, value_); return format_config(&values->items[values->nr++], key_, value_);
} }
@ -430,14 +425,11 @@ static int get_urlmatch(const char *var, const char *url)
for_each_string_list_item(item, &values) { for_each_string_list_item(item, &values) {
struct urlmatch_current_candidate_value *matched = item->util; struct urlmatch_current_candidate_value *matched = item->util;
struct strbuf key = STRBUF_INIT;
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
strbuf_addstr(&key, item->string); format_config(&buf, item->string,
format_config(&buf, key.buf,
matched->value_is_null ? NULL : matched->value.buf); matched->value_is_null ? NULL : matched->value.buf);
fwrite(buf.buf, 1, buf.len, stdout); fwrite(buf.buf, 1, buf.len, stdout);
strbuf_release(&key);
strbuf_release(&buf); strbuf_release(&buf);
strbuf_release(&matched->value); strbuf_release(&matched->value);
@ -549,7 +541,11 @@ int cmd_config(int argc, const char **argv, const char *prefix)
default: default:
usage_with_options(builtin_config_usage, builtin_config_options); usage_with_options(builtin_config_usage, builtin_config_options);
} }
if (omit_values &&
!(actions == ACTION_LIST || actions == ACTION_GET_REGEXP)) {
error("--name-only is only applicable to --list or --get-regexp");
usage_with_options(builtin_config_usage, builtin_config_options);
}
if (actions == ACTION_LIST) { if (actions == ACTION_LIST) {
check_argc(argc, 0, 0); check_argc(argc, 0, 0);
if (git_config_with_options(show_all_config, NULL, if (git_config_with_options(show_all_config, NULL,

Просмотреть файл

@ -744,9 +744,8 @@ __git_compute_porcelain_commands ()
__git_get_config_variables () __git_get_config_variables ()
{ {
local section="$1" i IFS=$'\n' local section="$1" i IFS=$'\n'
for i in $(git --git-dir="$(__gitdir)" config --get-regexp "^$section\..*" 2>/dev/null); do for i in $(git --git-dir="$(__gitdir)" config --name-only --get-regexp "^$section\..*" 2>/dev/null); do
i="${i#$section.}" echo "${i#$section.}"
echo "${i/ */}"
done done
} }
@ -1777,15 +1776,7 @@ __git_config_get_set_variables ()
c=$((--c)) c=$((--c))
done done
git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null | git --git-dir="$(__gitdir)" config $config_file --name-only --list 2>/dev/null
while read -r line
do
case "$line" in
*.*=*)
echo "${line/=*/}"
;;
esac
done
} }
_git_config () _git_config ()
@ -1890,6 +1881,7 @@ _git_config ()
--get --get-all --get-regexp --get --get-all --get-regexp
--add --unset --unset-all --add --unset --unset-all
--remove-section --rename-section --remove-section --rename-section
--name-only
" "
return return
;; ;;

Просмотреть файл

@ -352,6 +352,18 @@ test_expect_success '--list without repo produces empty output' '
test_cmp expect output test_cmp expect output
' '
cat > expect << EOF
beta.noindent
nextsection.nonewline
123456.a123
version.1.2.3eX.alpha
EOF
test_expect_success '--name-only --list' '
git config --name-only --list >output &&
test_cmp expect output
'
cat > expect << EOF cat > expect << EOF
beta.noindent sillyValue beta.noindent sillyValue
nextsection.nonewline wow2 for me nextsection.nonewline wow2 for me
@ -362,6 +374,16 @@ test_expect_success '--get-regexp' '
test_cmp expect output test_cmp expect output
' '
cat > expect << EOF
beta.noindent
nextsection.nonewline
EOF
test_expect_success '--name-only --get-regexp' '
git config --name-only --get-regexp in >output &&
test_cmp expect output
'
cat > expect << EOF cat > expect << EOF
wow2 for me wow2 for me
wow4 for you wow4 for you