config: "git config --get-urlmatch" parses section.<url>.key
Using the same urlmatch_config_entry() infrastructure, add a new mode "--get-urlmatch" to the "git config" command, to learn values for the "virtual" two-level variables customized for the specific URL. git config [--<type>] --get-urlmatch <section>[.<key>] <url> With <section>.<key> fully specified, the configuration data for <section>.<urlpattern>.<key> for <urlpattern> that best matches the given <url> is sought (and if not found, <section>.<key> is used) and reported. For example, with this configuration: [http] sslVerify [http "https://weak.example.com"] cookieFile = /tmp/cookie.txt sslVerify = false You would get $ git config --bool --get-urlmatch http.sslVerify https://good.example.com true $ git config --bool --get-urlmatch http.sslVerify https://weak.example.com false With only <section> specified, you can get a list of all variables in the section with their values that apply to the given URL. E.g $ git config --get-urlmatch http https://weak.example.com http.cookiefile /tmp/cookie.txt http.sslverify false Helped-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
d9b9169b34
commit
d4770964d5
@ -15,6 +15,7 @@ SYNOPSIS
|
||||
'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-regexp name_regex [value_regex]
|
||||
'git config' [<file-option>] [type] [-z|--null] --get-urlmatch name URL
|
||||
'git config' [<file-option>] --unset name [value_regex]
|
||||
'git config' [<file-option>] --unset-all name [value_regex]
|
||||
'git config' [<file-option>] --rename-section old_name new_name
|
||||
@ -95,6 +96,14 @@ OPTIONS
|
||||
in which section and variable names are lowercased, but subsection
|
||||
names are not.
|
||||
|
||||
--get-urlmatch name URL::
|
||||
When given a two-part name section.key, the value for
|
||||
section.<url>.key whose <url> part matches the best to the
|
||||
given URL is returned (if no such key exists, the value for
|
||||
section.key is used as a fallback). When given just the
|
||||
section as name, do so for all the keys in the section and
|
||||
list them.
|
||||
|
||||
--global::
|
||||
For writing options: write to global ~/.gitconfig file rather than
|
||||
the repository .git/config, write to $XDG_CONFIG_HOME/git/config file
|
||||
@ -273,6 +282,13 @@ Given a .git/config like this:
|
||||
gitproxy=proxy-command for kernel.org
|
||||
gitproxy=default-proxy ; for all the rest
|
||||
|
||||
; HTTP
|
||||
[http]
|
||||
sslVerify
|
||||
[http "https://weak.example.com"]
|
||||
sslVerify = false
|
||||
cookieFile = /tmp/cookie.txt
|
||||
|
||||
you can set the filemode to true with
|
||||
|
||||
------------
|
||||
@ -358,6 +374,19 @@ RESET=$(git config --get-color "" "reset")
|
||||
echo "${WS}your whitespace color or blue reverse${RESET}"
|
||||
------------
|
||||
|
||||
For URLs in `https://weak.example.com`, `http.sslVerify` is set to
|
||||
false, while it is set to `true` for all others:
|
||||
|
||||
------------
|
||||
% git config --bool --get-urlmatch http.sslverify https://good.example.com
|
||||
true
|
||||
% git config --bool --get-urlmatch http.sslverify https://weak.example.com
|
||||
false
|
||||
% git config --get-urlmatch http https://weak.example.com
|
||||
http.cookiefile /tmp/cookie.txt
|
||||
http.sslverify false
|
||||
------------
|
||||
|
||||
include::config.txt[]
|
||||
|
||||
GIT
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "cache.h"
|
||||
#include "color.h"
|
||||
#include "parse-options.h"
|
||||
#include "urlmatch.h"
|
||||
|
||||
static const char *const builtin_config_usage[] = {
|
||||
N_("git config [options]"),
|
||||
@ -41,6 +42,7 @@ static int respect_includes = -1;
|
||||
#define ACTION_SET_ALL (1<<12)
|
||||
#define ACTION_GET_COLOR (1<<13)
|
||||
#define ACTION_GET_COLORBOOL (1<<14)
|
||||
#define ACTION_GET_URLMATCH (1<<15)
|
||||
|
||||
#define TYPE_BOOL (1<<0)
|
||||
#define TYPE_INT (1<<1)
|
||||
@ -57,6 +59,7 @@ static struct option builtin_config_options[] = {
|
||||
OPT_BIT(0, "get", &actions, N_("get value: name [value-regex]"), ACTION_GET),
|
||||
OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-regex]"), ACTION_GET_ALL),
|
||||
OPT_BIT(0, "get-regexp", &actions, N_("get values for regexp: name-regex [value-regex]"), ACTION_GET_REGEXP),
|
||||
OPT_BIT(0, "get-urlmatch", &actions, N_("get value specific for the URL: section[.var] URL"), ACTION_GET_URLMATCH),
|
||||
OPT_BIT(0, "replace-all", &actions, N_("replace all matching variables: name value [value_regex]"), ACTION_REPLACE_ALL),
|
||||
OPT_BIT(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
|
||||
OPT_BIT(0, "unset", &actions, N_("remove a variable: name [value-regex]"), ACTION_UNSET),
|
||||
@ -348,6 +351,97 @@ static int get_colorbool(int print)
|
||||
return get_colorbool_found ? 0 : 1;
|
||||
}
|
||||
|
||||
struct urlmatch_current_candidate_value {
|
||||
char value_is_null;
|
||||
struct strbuf value;
|
||||
};
|
||||
|
||||
static int urlmatch_collect_fn(const char *var, const char *value, void *cb)
|
||||
{
|
||||
struct string_list *values = cb;
|
||||
struct string_list_item *item = string_list_insert(values, var);
|
||||
struct urlmatch_current_candidate_value *matched = item->util;
|
||||
|
||||
if (!matched) {
|
||||
matched = xmalloc(sizeof(*matched));
|
||||
strbuf_init(&matched->value, 0);
|
||||
item->util = matched;
|
||||
} else {
|
||||
strbuf_reset(&matched->value);
|
||||
}
|
||||
|
||||
if (value) {
|
||||
strbuf_addstr(&matched->value, value);
|
||||
matched->value_is_null = 0;
|
||||
} else {
|
||||
matched->value_is_null = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *dup_downcase(const char *string)
|
||||
{
|
||||
char *result;
|
||||
size_t len, i;
|
||||
|
||||
len = strlen(string);
|
||||
result = xmalloc(len + 1);
|
||||
for (i = 0; i < len; i++)
|
||||
result[i] = tolower(string[i]);
|
||||
result[i] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
static int get_urlmatch(const char *var, const char *url)
|
||||
{
|
||||
char *section_tail;
|
||||
struct string_list_item *item;
|
||||
struct urlmatch_config config = { STRING_LIST_INIT_DUP };
|
||||
struct string_list values = STRING_LIST_INIT_DUP;
|
||||
|
||||
config.collect_fn = urlmatch_collect_fn;
|
||||
config.cascade_fn = NULL;
|
||||
config.cb = &values;
|
||||
|
||||
if (!url_normalize(url, &config.url))
|
||||
die(config.url.err);
|
||||
|
||||
config.section = dup_downcase(var);
|
||||
section_tail = strchr(config.section, '.');
|
||||
if (section_tail) {
|
||||
*section_tail = '\0';
|
||||
config.key = section_tail + 1;
|
||||
show_keys = 0;
|
||||
} else {
|
||||
config.key = NULL;
|
||||
show_keys = 1;
|
||||
}
|
||||
|
||||
git_config_with_options(urlmatch_config_entry, &config,
|
||||
given_config_file, respect_includes);
|
||||
|
||||
for_each_string_list_item(item, &values) {
|
||||
struct urlmatch_current_candidate_value *matched = item->util;
|
||||
struct strbuf key = STRBUF_INIT;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
strbuf_addstr(&key, item->string);
|
||||
format_config(&buf, key.buf,
|
||||
matched->value_is_null ? NULL : matched->value.buf);
|
||||
fwrite(buf.buf, 1, buf.len, stdout);
|
||||
strbuf_release(&key);
|
||||
strbuf_release(&buf);
|
||||
|
||||
strbuf_release(&matched->value);
|
||||
}
|
||||
string_list_clear(&config.vars, 1);
|
||||
string_list_clear(&values, 1);
|
||||
free(config.url.url);
|
||||
|
||||
free((void *)config.section);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_config(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int nongit = !startup_info->have_repository;
|
||||
@ -499,6 +593,10 @@ int cmd_config(int argc, const char **argv, const char *prefix)
|
||||
check_argc(argc, 1, 2);
|
||||
return get_value(argv[0], argv[1]);
|
||||
}
|
||||
else if (actions == ACTION_GET_URLMATCH) {
|
||||
check_argc(argc, 2, 2);
|
||||
return get_urlmatch(argv[0], argv[1]);
|
||||
}
|
||||
else if (actions == ACTION_UNSET) {
|
||||
check_argc(argc, 1, 2);
|
||||
if (argc == 2)
|
||||
|
@ -1087,6 +1087,31 @@ test_expect_success 'barf on incomplete string' '
|
||||
grep " line 3 " error
|
||||
'
|
||||
|
||||
test_expect_success 'urlmatch' '
|
||||
cat >.git/config <<-\EOF &&
|
||||
[http]
|
||||
sslVerify
|
||||
[http "https://weak.example.com"]
|
||||
sslVerify = false
|
||||
cookieFile = /tmp/cookie.txt
|
||||
EOF
|
||||
|
||||
echo true >expect &&
|
||||
git config --bool --get-urlmatch http.SSLverify https://good.example.com >actual &&
|
||||
test_cmp expect actual &&
|
||||
|
||||
echo false >expect &&
|
||||
git config --bool --get-urlmatch http.sslverify https://weak.example.com >actual &&
|
||||
test_cmp expect actual &&
|
||||
|
||||
{
|
||||
echo http.cookiefile /tmp/cookie.txt &&
|
||||
echo http.sslverify false
|
||||
} >expect &&
|
||||
git config --get-urlmatch HTTP https://weak.example.com >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
# good section hygiene
|
||||
test_expect_failure 'unsetting the last key in a section removes header' '
|
||||
cat >.git/config <<-\EOF &&
|
||||
|
Loading…
Reference in New Issue
Block a user