e2016508e7
If, when parsing numbers from config, die_bad_number() is called, it
reports the filename and config source type if we were parsing a config
file, but not if we were iterating a config_set (it defaults to a less
specific error message). Most call sites don't parse config files
because config is typically read once and cached, so we only report
filename and config source type in "git config --type" (since "git
config" always parses config files).
This could have been fixed when we taught the current_config_*
functions to respect config_set values (0d44a2dacc
(config: return
configset value for current_config_ functions, 2016-05-26), but it was
hard to spot then and we might have just missed it (I didn't find
mention of die_bad_number() in the original ML discussion [1].)
Fix this by refactoring the current_config_* functions into variants
that don't BUG() when we aren't reading config, and using the resulting
functions in die_bad_number(). "git config --get[-regexp] --type=int"
cannot use the non-refactored version because it parses the int value
_after_ parsing the config file, which would run into the BUG().
Since the refactored functions aren't public, they use "struct
config_reader".
1. https://lore.kernel.org/git/20160518223712.GA18317@sigill.intra.peff.net/
Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
295 lines
7.6 KiB
Bash
Executable File
295 lines
7.6 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='Test git config-set API in different settings'
|
|
|
|
TEST_PASSES_SANITIZE_LEAK=true
|
|
. ./test-lib.sh
|
|
|
|
# 'check_config get_* section.key value' verifies that the entry for
|
|
# section.key is 'value'
|
|
check_config () {
|
|
if test "$1" = expect_code
|
|
then
|
|
expect_code="$2" && shift && shift
|
|
else
|
|
expect_code=0
|
|
fi &&
|
|
op=$1 key=$2 && shift && shift &&
|
|
if test $# != 0
|
|
then
|
|
printf "%s\n" "$@"
|
|
fi >expect &&
|
|
test_expect_code $expect_code test-tool config "$op" "$key" >actual &&
|
|
test_cmp expect actual
|
|
}
|
|
|
|
test_expect_success 'setup default config' '
|
|
cat >.git/config <<-\EOF
|
|
[case]
|
|
penguin = very blue
|
|
Movie = BadPhysics
|
|
UPPERCASE = true
|
|
MixedCase = true
|
|
my =
|
|
foo
|
|
baz = sam
|
|
[Cores]
|
|
WhatEver = Second
|
|
baz = bar
|
|
[cores]
|
|
baz = bat
|
|
[CORES]
|
|
baz = ball
|
|
[my "Foo bAr"]
|
|
hi = mixed-case
|
|
[my "FOO BAR"]
|
|
hi = upper-case
|
|
[my "foo bar"]
|
|
hi = lower-case
|
|
[case]
|
|
baz = bat
|
|
baz = hask
|
|
[lamb]
|
|
chop = 65
|
|
head = none
|
|
[goat]
|
|
legs = 4
|
|
head = true
|
|
skin = false
|
|
nose = 1
|
|
horns
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'get value for a simple key' '
|
|
check_config get_value case.penguin "very blue"
|
|
'
|
|
|
|
test_expect_success 'get value for a key with value as an empty string' '
|
|
check_config get_value case.my ""
|
|
'
|
|
|
|
test_expect_success 'get value for a key with value as NULL' '
|
|
check_config get_value case.foo "(NULL)"
|
|
'
|
|
|
|
test_expect_success 'upper case key' '
|
|
check_config get_value case.UPPERCASE "true" &&
|
|
check_config get_value case.uppercase "true"
|
|
'
|
|
|
|
test_expect_success 'mixed case key' '
|
|
check_config get_value case.MixedCase "true" &&
|
|
check_config get_value case.MIXEDCASE "true" &&
|
|
check_config get_value case.mixedcase "true"
|
|
'
|
|
|
|
test_expect_success 'key and value with mixed case' '
|
|
check_config get_value case.Movie "BadPhysics"
|
|
'
|
|
|
|
test_expect_success 'key with case sensitive subsection' '
|
|
check_config get_value "my.Foo bAr.hi" "mixed-case" &&
|
|
check_config get_value "my.FOO BAR.hi" "upper-case" &&
|
|
check_config get_value "my.foo bar.hi" "lower-case"
|
|
'
|
|
|
|
test_expect_success 'key with case insensitive section header' '
|
|
check_config get_value cores.baz "ball" &&
|
|
check_config get_value Cores.baz "ball" &&
|
|
check_config get_value CORES.baz "ball" &&
|
|
check_config get_value coreS.baz "ball"
|
|
'
|
|
|
|
test_expect_success 'key with case insensitive section header & variable' '
|
|
check_config get_value CORES.BAZ "ball" &&
|
|
check_config get_value cores.baz "ball" &&
|
|
check_config get_value cores.BaZ "ball" &&
|
|
check_config get_value cOreS.bAz "ball"
|
|
'
|
|
|
|
test_expect_success 'find value with misspelled key' '
|
|
check_config expect_code 1 get_value "my.fOo Bar.hi" "Value not found for \"my.fOo Bar.hi\""
|
|
'
|
|
|
|
test_expect_success 'find value with the highest priority' '
|
|
check_config get_value case.baz "hask"
|
|
'
|
|
|
|
test_expect_success 'find integer value for a key' '
|
|
check_config get_int lamb.chop 65
|
|
'
|
|
|
|
test_expect_success 'parse integer value during iteration' '
|
|
check_config git_config_int lamb.chop 65
|
|
'
|
|
|
|
test_expect_success 'find string value for a key' '
|
|
check_config get_string case.baz hask &&
|
|
check_config expect_code 1 get_string case.ba "Value not found for \"case.ba\""
|
|
'
|
|
|
|
test_expect_success 'check line error when NULL string is queried' '
|
|
test_expect_code 128 test-tool config get_string case.foo 2>result &&
|
|
test_i18ngrep "fatal: .*case\.foo.*\.git/config.*line 7" result
|
|
'
|
|
|
|
test_expect_success 'find integer if value is non parse-able' '
|
|
check_config expect_code 128 get_int lamb.head
|
|
'
|
|
|
|
test_expect_success 'non parse-able integer value during iteration' '
|
|
check_config expect_code 128 git_config_int lamb.head 2>result &&
|
|
grep "fatal: bad numeric config value .* in file \.git/config" result
|
|
'
|
|
|
|
test_expect_success 'find bool value for the entered key' '
|
|
check_config get_bool goat.head 1 &&
|
|
check_config get_bool goat.skin 0 &&
|
|
check_config get_bool goat.nose 1 &&
|
|
check_config get_bool goat.horns 1 &&
|
|
check_config get_bool goat.legs 1
|
|
'
|
|
|
|
test_expect_success 'find multiple values' '
|
|
check_config get_value_multi case.baz sam bat hask
|
|
'
|
|
|
|
test_expect_success 'find value from a configset' '
|
|
cat >config2 <<-\EOF &&
|
|
[case]
|
|
baz = lama
|
|
[my]
|
|
new = silk
|
|
[case]
|
|
baz = ball
|
|
EOF
|
|
echo silk >expect &&
|
|
test-tool config configset_get_value my.new config2 .git/config >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'find value with highest priority from a configset' '
|
|
echo hask >expect &&
|
|
test-tool config configset_get_value case.baz config2 .git/config >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'find value_list for a key from a configset' '
|
|
cat >expect <<-\EOF &&
|
|
lama
|
|
ball
|
|
sam
|
|
bat
|
|
hask
|
|
EOF
|
|
test-tool config configset_get_value_multi case.baz config2 .git/config >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'proper error on non-existent files' '
|
|
echo "Error (-1) reading configuration file non-existent-file." >expect &&
|
|
test_expect_code 2 test-tool config configset_get_value foo.bar non-existent-file 2>actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'proper error on directory "files"' '
|
|
echo "Error (-1) reading configuration file a-directory." >expect &&
|
|
mkdir a-directory &&
|
|
test_expect_code 2 test-tool config configset_get_value foo.bar a-directory 2>output &&
|
|
grep "^warning:" output &&
|
|
grep "^Error" output >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success POSIXPERM,SANITY 'proper error on non-accessible files' '
|
|
chmod -r .git/config &&
|
|
test_when_finished "chmod +r .git/config" &&
|
|
echo "Error (-1) reading configuration file .git/config." >expect &&
|
|
test_expect_code 2 test-tool config configset_get_value foo.bar .git/config 2>output &&
|
|
grep "^warning:" output &&
|
|
grep "^Error" output >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'proper error on error in default config files' '
|
|
cp .git/config .git/config.old &&
|
|
test_when_finished "mv .git/config.old .git/config" &&
|
|
echo "[" >>.git/config &&
|
|
echo "fatal: bad config line 34 in file .git/config" >expect &&
|
|
test_expect_code 128 test-tool config get_value foo.bar 2>actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'proper error on error in custom config files' '
|
|
echo "[" >>syntax-error &&
|
|
echo "fatal: bad config line 1 in file syntax-error" >expect &&
|
|
test_expect_code 128 test-tool config configset_get_value foo.bar syntax-error 2>actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'check line errors for malformed values' '
|
|
mv .git/config .git/config.old &&
|
|
test_when_finished "mv .git/config.old .git/config" &&
|
|
cat >.git/config <<-\EOF &&
|
|
[alias]
|
|
br
|
|
EOF
|
|
test_expect_code 128 git br 2>result &&
|
|
test_i18ngrep "missing value for .alias\.br" result &&
|
|
test_i18ngrep "fatal: .*\.git/config" result &&
|
|
test_i18ngrep "fatal: .*line 2" result
|
|
'
|
|
|
|
test_expect_success 'error on modifying repo config without repo' '
|
|
nongit test_must_fail git config a.b c 2>err &&
|
|
test_i18ngrep "not in a git directory" err
|
|
'
|
|
|
|
cmdline_config="'foo.bar=from-cmdline'"
|
|
test_expect_success 'iteration shows correct origins' '
|
|
printf "[ignore]\n\tthis = please\n[foo]bar = from-repo\n" >.git/config &&
|
|
printf "[foo]\n\tbar = from-home\n" >.gitconfig &&
|
|
if test_have_prereq MINGW
|
|
then
|
|
# Use Windows path (i.e. *not* $HOME)
|
|
HOME_GITCONFIG=$(pwd)/.gitconfig
|
|
else
|
|
# Do not get fooled by symbolic links, i.e. $HOME != $(pwd)
|
|
HOME_GITCONFIG=$HOME/.gitconfig
|
|
fi &&
|
|
cat >expect <<-EOF &&
|
|
key=foo.bar
|
|
value=from-home
|
|
origin=file
|
|
name=$HOME_GITCONFIG
|
|
lno=2
|
|
scope=global
|
|
|
|
key=ignore.this
|
|
value=please
|
|
origin=file
|
|
name=.git/config
|
|
lno=2
|
|
scope=local
|
|
|
|
key=foo.bar
|
|
value=from-repo
|
|
origin=file
|
|
name=.git/config
|
|
lno=3
|
|
scope=local
|
|
|
|
key=foo.bar
|
|
value=from-cmdline
|
|
origin=command line
|
|
name=
|
|
lno=-1
|
|
scope=command
|
|
EOF
|
|
GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_done
|