| #!/bin/sh | |
| # | |
| # Copyright (c) 2005 Johannes Schindelin | |
| # | |
| test_description='Test git config in different settings' | |
| GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main | |
| export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME | |
| . ./test-lib.sh | |
| . "$TEST_DIRECTORY"/lib-terminal.sh | |
| # test-lib.sh may have added global config (e.g. safe.bareRepository) | |
| # that would appear in "git config --list" output and break tests | |
| # that expect exact config contents. | |
| test_expect_success 'remove global config from test-lib.sh' ' | |
| test_might_fail git config --global --unset-all safe.bareRepository | |
| ' | |
| for mode in legacy subcommands | |
| do | |
| case "$mode" in | |
| legacy) | |
| mode_prefix="--" | |
| mode_get="" | |
| mode_get_all="--get-all" | |
| mode_get_regexp="--get-regexp" | |
| mode_set="" | |
| mode_replace_all="--replace-all" | |
| mode_unset="--unset" | |
| mode_unset_all="--unset-all" | |
| ;; | |
| subcommands) | |
| mode_prefix="" | |
| mode_get="get" | |
| mode_get_all="get --all" | |
| mode_get_regexp="get --regexp --all --show-names" | |
| mode_set="set" | |
| mode_replace_all="set --all" | |
| mode_unset="unset" | |
| mode_unset_all="unset --all" | |
| ;; | |
| *) | |
| BUG "unknown mode $mode";; | |
| esac | |
| test_expect_success 'setup whitespace config' ' | |
| sed -e "s/^|//" \ | |
| -e "s/[$]$//" \ | |
| -e "s/X/ /g" >.git/config <<-\EOF | |
| [section] | |
| | solid = rock | |
| | sparse = big XX blue | |
| | sparseAndTail = big XX blue $ | |
| | sparseAndTailQuoted = "big XX blue " | |
| | sparseAndBiggerTail = big XX blue X X | |
| | sparseAndBiggerTailQuoted = "big XX blue X X" | |
| | sparseAndBiggerTailQuotedPlus = "big XX blue X X"X $ | |
| | headAndTail = Xbig blue $ | |
| | headAndTailQuoted = "Xbig blue " | |
| | headAndTailQuotedPlus = "Xbig blue " $ | |
| | annotated = big blueX# to be discarded | |
| | annotatedQuoted = "big blue"X# to be discarded | |
| EOF | |
| ' | |
| test_expect_success 'no internal whitespace' ' | |
| echo "rock" >expect && | |
| git config --get section.solid >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'internal whitespace' ' | |
| echo "big QQ blue" | q_to_tab >expect && | |
| git config --get section.sparse >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'internal and trailing whitespace' ' | |
| echo "big QQ blue" | q_to_tab >expect && | |
| git config --get section.sparseAndTail >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'internal and trailing whitespace, all quoted' ' | |
| echo "big QQ blue " | q_to_tab >expect && | |
| git config --get section.sparseAndTailQuoted >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'internal and more trailing whitespace' ' | |
| echo "big QQ blue" | q_to_tab >expect && | |
| git config --get section.sparseAndBiggerTail >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'internal and more trailing whitespace, all quoted' ' | |
| echo "big QQ blue Q Q" | q_to_tab >expect && | |
| git config --get section.sparseAndBiggerTailQuoted >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'internal and more trailing whitespace, not all quoted' ' | |
| echo "big QQ blue Q Q" | q_to_tab >expect && | |
| git config --get section.sparseAndBiggerTailQuotedPlus >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'leading and trailing whitespace' ' | |
| echo "big blue" >expect && | |
| git config --get section.headAndTail >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'leading and trailing whitespace, all quoted' ' | |
| echo "Qbig blue " | q_to_tab >expect && | |
| git config --get section.headAndTailQuoted >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'leading and trailing whitespace, not all quoted' ' | |
| echo "Qbig blue " | q_to_tab >expect && | |
| git config --get section.headAndTailQuotedPlus >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'inline comment' ' | |
| echo "big blue" >expect && | |
| git config --get section.annotated >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'inline comment, quoted' ' | |
| echo "big blue" >expect && | |
| git config --get section.annotatedQuoted >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'clear default config' ' | |
| rm -f .git/config | |
| ' | |
| test_expect_success 'initial' ' | |
| cat >expect <<\EOF && | |
| [section] | |
| penguin = little blue | |
| EOF | |
| git config ${mode_set} section.penguin "little blue" && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'mixed case' ' | |
| cat >expect <<\EOF && | |
| [section] | |
| penguin = little blue | |
| Movie = BadPhysics | |
| EOF | |
| git config ${mode_set} Section.Movie BadPhysics && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'similar section' ' | |
| cat >expect <<\EOF && | |
| [section] | |
| penguin = little blue | |
| Movie = BadPhysics | |
| [Sections] | |
| WhatEver = Second | |
| EOF | |
| git config ${mode_set} Sections.WhatEver Second && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'uppercase section' ' | |
| cat >expect <<\EOF && | |
| [section] | |
| penguin = little blue | |
| Movie = BadPhysics | |
| UPPERCASE = true | |
| [Sections] | |
| WhatEver = Second | |
| EOF | |
| git config ${mode_set} SECTION.UPPERCASE true && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'replace with non-match' ' | |
| git config section.penguin kingpin !blue | |
| ' | |
| test_expect_success 'replace with non-match (actually matching)' ' | |
| git config section.penguin "very blue" !kingpin | |
| ' | |
| test_expect_success 'append comments' ' | |
| cat >expect <<\EOF && | |
| [section] | |
| Movie = BadPhysics | |
| UPPERCASE = true | |
| penguin = gentoo # Pygoscelis papua | |
| disposition = peckish # find fish | |
| foo = bar #abc | |
| spsp = value # and comment | |
| htsp = value # and comment | |
| [Sections] | |
| WhatEver = Second | |
| EOF | |
| git config --replace-all --comment="Pygoscelis papua" section.penguin gentoo && | |
| git config ${mode_set} --comment="find fish" section.disposition peckish && | |
| git config ${mode_set} --comment="#abc" section.foo bar && | |
| git config --comment="and comment" section.spsp value && | |
| git config --comment=" # and comment" section.htsp value && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'Prohibited LF in comment' ' | |
| test_must_fail git config ${mode_set} --comment="a${LF}b" section.k v | |
| ' | |
| test_expect_success 'non-match result' ' | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'find mixed-case key by canonical name' ' | |
| test_cmp_config Second sections.whatever | |
| ' | |
| test_expect_success 'find mixed-case key by non-canonical name' ' | |
| test_cmp_config Second SeCtIoNs.WhAtEvEr | |
| ' | |
| test_expect_success 'subsections are not canonicalized by git-config' ' | |
| cat >>.git/config <<-\EOF && | |
| [section.SubSection] | |
| key = one | |
| [section "SubSection"] | |
| key = two | |
| EOF | |
| test_cmp_config one section.subsection.key && | |
| test_cmp_config two section.SubSection.key | |
| ' | |
| test_missing_key () { | |
| local key="$1" && | |
| local title="$2" && | |
| test_expect_success "value for $title is not printed" ' | |
| test_must_fail git config "$key" >out 2>err && | |
| test_must_be_empty out && | |
| test_must_be_empty err | |
| ' | |
| } | |
| test_missing_key 'missingsection.missingkey' 'missing section and missing key' | |
| test_missing_key 'missingsection.penguin' 'missing section and existing key' | |
| test_missing_key 'section.missingkey' 'existing section and missing key' | |
| test_missing_key 'section.MissingSubSection.missingkey' 'missing subsection and missing key' | |
| test_missing_key 'section.SubSection.missingkey' 'existing subsection and missing key' | |
| test_missing_key 'section.MissingSubSection.key' 'missing subsection and existing key' | |
| cat > .git/config <<\EOF | |
| [alpha] | |
| bar = foo | |
| [beta] | |
| baz = multiple \ | |
| lines | |
| foo = bar | |
| EOF | |
| test_expect_success 'unset with cont. lines' ' | |
| git config ${mode_unset} beta.baz | |
| ' | |
| test_expect_success 'unset with cont. lines is correct' ' | |
| cat >expect <<-\EOF && | |
| [alpha] | |
| bar = foo | |
| [beta] | |
| foo = bar | |
| EOF | |
| test_cmp expect .git/config | |
| ' | |
| cat > .git/config << EOF | |
| [beta] ; silly comment # another comment | |
| noIndent= sillyValue ; 'nother silly comment | |
| # empty line | |
| ; comment | |
| haha ="beta" # last silly comment | |
| haha = hello | |
| haha = bello | |
| [nextSection] noNewline = ouch | |
| EOF | |
| cp .git/config .git/config2 | |
| test_expect_success 'multiple unset' ' | |
| git config ${mode_unset_all} beta.haha | |
| ' | |
| test_expect_success 'multiple unset is correct' ' | |
| cat >expect <<EOF && | |
| [beta] ; silly comment # another comment | |
| noIndent= sillyValue ; ${SQ}nother silly comment | |
| # empty line | |
| ; comment | |
| [nextSection] noNewline = ouch | |
| EOF | |
| test_cmp expect .git/config | |
| ' | |
| cp .git/config2 .git/config | |
| test_expect_success '--replace-all missing value' ' | |
| test_must_fail git config ${mode_replace_all} beta.haha && | |
| test_cmp .git/config2 .git/config | |
| ' | |
| rm .git/config2 | |
| test_expect_success '--replace-all' ' | |
| git config ${mode_replace_all} beta.haha gamma | |
| ' | |
| test_expect_success 'all replaced' ' | |
| cat >expect <<EOF && | |
| [beta] ; silly comment # another comment | |
| noIndent= sillyValue ; ${SQ}nother silly comment | |
| # empty line | |
| ; comment | |
| haha = gamma | |
| [nextSection] noNewline = ouch | |
| EOF | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'really mean test' ' | |
| cat >expect <<EOF && | |
| [beta] ; silly comment # another comment | |
| noIndent= sillyValue ; ${SQ}nother silly comment | |
| # empty line | |
| ; comment | |
| haha = alpha | |
| [nextSection] noNewline = ouch | |
| EOF | |
| git config ${mode_set} beta.haha alpha && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'really really mean test' ' | |
| cat >expect <<EOF && | |
| [beta] ; silly comment # another comment | |
| noIndent= sillyValue ; ${SQ}nother silly comment | |
| # empty line | |
| ; comment | |
| haha = alpha | |
| [nextSection] | |
| nonewline = wow | |
| EOF | |
| git config ${mode_set} nextsection.nonewline wow && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'get value' ' | |
| test_cmp_config alpha beta.haha | |
| ' | |
| test_expect_success 'unset' ' | |
| cat >expect <<EOF && | |
| [beta] ; silly comment # another comment | |
| noIndent= sillyValue ; ${SQ}nother silly comment | |
| # empty line | |
| ; comment | |
| [nextSection] | |
| nonewline = wow | |
| EOF | |
| git config ${mode_unset} beta.haha && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'multivar' ' | |
| cat >expect <<EOF && | |
| [beta] ; silly comment # another comment | |
| noIndent= sillyValue ; ${SQ}nother silly comment | |
| # empty line | |
| ; comment | |
| [nextSection] | |
| nonewline = wow | |
| NoNewLine = wow2 for me | |
| EOF | |
| git config nextsection.NoNewLine "wow2 for me" "for me$" && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'non-match' ' | |
| git config --get nextsection.nonewline !for | |
| ' | |
| test_expect_success 'non-match value' ' | |
| test_cmp_config wow --get nextsection.nonewline !for | |
| ' | |
| test_expect_success 'multi-valued get returns final one' ' | |
| test_cmp_config "wow2 for me" --get nextsection.nonewline | |
| ' | |
| test_expect_success 'multi-valued get-all returns all' ' | |
| cat >expect <<-\EOF && | |
| wow | |
| wow2 for me | |
| EOF | |
| git config ${mode_get_all} nextsection.nonewline >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'multivar replace' ' | |
| cat >expect <<EOF && | |
| [beta] ; silly comment # another comment | |
| noIndent= sillyValue ; ${SQ}nother silly comment | |
| # empty line | |
| ; comment | |
| [nextSection] | |
| nonewline = wow3 | |
| NoNewLine = wow2 for me | |
| EOF | |
| git config nextsection.nonewline "wow3" "wow$" && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'ambiguous unset' ' | |
| test_must_fail git config ${mode_unset} nextsection.nonewline | |
| ' | |
| test_expect_success 'invalid unset' ' | |
| test_must_fail git config ${mode_unset} somesection.nonewline | |
| ' | |
| test_expect_success 'multivar unset' ' | |
| cat >expect <<EOF && | |
| [beta] ; silly comment # another comment | |
| noIndent= sillyValue ; ${SQ}nother silly comment | |
| # empty line | |
| ; comment | |
| [nextSection] | |
| NoNewLine = wow2 for me | |
| EOF | |
| case "$mode" in | |
| legacy) | |
| git config --unset nextsection.nonewline "wow3$";; | |
| subcommands) | |
| git config unset --value="wow3$" nextsection.nonewline;; | |
| esac && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'invalid key' ' | |
| test_must_fail git config inval.2key blabla | |
| ' | |
| test_expect_success 'set with 1 arg of "key=value": valid key suggests split form' ' | |
| test_must_fail git config set pull.rebase=false 2>err && | |
| test_grep "missing value to set to the variable .pull\\.rebase=false." err && | |
| test_grep "did you mean .git config set pull\\.rebase false." err | |
| ' | |
| test_expect_success 'set with 1 arg of "key=value": implicit form suggests split form' ' | |
| test_must_fail git config pull.rebase=false 2>err && | |
| test_grep "missing value to set to the variable .pull\\.rebase=false." err && | |
| test_grep "did you mean .git config set pull\\.rebase false." err | |
| ' | |
| test_expect_success 'set with 1 arg of "key=value": invalid key does not suggest split form' ' | |
| test_must_fail git config set foo=bar 2>err && | |
| test_grep "missing value to set to a variable with an invalid name .foo=bar." err && | |
| test_grep ! "did you mean" err | |
| ' | |
| test_expect_success 'set with 1 arg: variable name starting with digit is invalid' ' | |
| test_must_fail git config set foo.1bar=baz 2>err && | |
| test_grep "missing value to set to a variable with an invalid name .foo\\.1bar=baz." err && | |
| test_grep ! "did you mean" err | |
| ' | |
| test_expect_success 'set with 1 arg: digit-led section name is valid' ' | |
| test_must_fail git config set 1foo.bar=baz 2>err && | |
| test_grep "missing value to set to the variable .1foo\\.bar=baz." err && | |
| test_grep "did you mean .git config set 1foo\\.bar baz." err | |
| ' | |
| test_expect_success 'set with 1 arg: subsection plus invalid variable name' ' | |
| test_must_fail git config set foo.some.b_r=baz 2>err && | |
| test_grep "missing value to set to a variable with an invalid name .foo\\.some\\.b_r=baz." err && | |
| test_grep ! "did you mean" err | |
| ' | |
| test_expect_success 'set with 1 arg of valid key reports missing value' ' | |
| test_must_fail git config set pull.rebase 2>err && | |
| test_grep "missing value to set to the variable .pull\\.rebase." err && | |
| test_grep ! "did you mean" err | |
| ' | |
| test_expect_success 'set with 2 args including "=" in invalid key does not suggest' ' | |
| test_must_fail git config set pull.rebase=false true 2>err && | |
| test_grep "invalid key: pull\\.rebase=false" err && | |
| test_grep ! "did you mean" err | |
| ' | |
| test_expect_success '"=" inside subsection is valid' ' | |
| test_when_finished "rm -f subsection.cfg" && | |
| git config set -f subsection.cfg foo.bar=baz.boo qux && | |
| echo qux >expect && | |
| git config get -f subsection.cfg foo.bar=baz.boo >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'correct key' ' | |
| git config 123456.a123 987 | |
| ' | |
| test_expect_success 'hierarchical section' ' | |
| git config Version.1.2.3eX.Alpha beta | |
| ' | |
| test_expect_success 'hierarchical section value' ' | |
| cat >expect <<EOF && | |
| [beta] ; silly comment # another comment | |
| noIndent= sillyValue ; ${SQ}nother silly comment | |
| # empty line | |
| ; comment | |
| [nextSection] | |
| NoNewLine = wow2 for me | |
| [123456] | |
| a123 = 987 | |
| [Version "1.2.3eX"] | |
| Alpha = beta | |
| EOF | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'working --list' ' | |
| cat >expect <<-\EOF && | |
| beta.noindent=sillyValue | |
| nextsection.nonewline=wow2 for me | |
| 123456.a123=987 | |
| version.1.2.3eX.alpha=beta | |
| EOF | |
| git config ${mode_prefix}list > output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--list without repo produces empty output' ' | |
| git --git-dir=nonexistent config ${mode_prefix}list >output && | |
| test_must_be_empty output | |
| ' | |
| test_expect_success '--name-only --list' ' | |
| cat >expect <<-\EOF && | |
| beta.noindent | |
| nextsection.nonewline | |
| 123456.a123 | |
| version.1.2.3eX.alpha | |
| EOF | |
| git config ${mode_prefix}list --name-only >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--get-regexp' ' | |
| cat >expect <<-\EOF && | |
| beta.noindent sillyValue | |
| nextsection.nonewline wow2 for me | |
| EOF | |
| git config ${mode_get_regexp} in >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--name-only --get-regexp' ' | |
| cat >expect <<-\EOF && | |
| beta.noindent | |
| nextsection.nonewline | |
| EOF | |
| git config ${mode_get_regexp} --name-only in >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--add' ' | |
| cat >expect <<-\EOF && | |
| wow2 for me | |
| wow4 for you | |
| EOF | |
| git config --add nextsection.nonewline "wow4 for you" && | |
| git config ${mode_get_all} nextsection.nonewline > output && | |
| test_cmp expect output | |
| ' | |
| cat > .git/config << EOF | |
| [novalue] | |
| variable | |
| [emptyvalue] | |
| variable = | |
| EOF | |
| test_expect_success 'get variable with no value' ' | |
| git config --get novalue.variable ^$ | |
| ' | |
| test_expect_success 'get variable with empty value' ' | |
| git config --get emptyvalue.variable ^$ | |
| ' | |
| test_expect_success 'get-regexp variable with no value' ' | |
| echo novalue.variable >expect && | |
| git config ${mode_get_regexp} novalue > output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success 'get-regexp --bool variable with no value' ' | |
| echo "novalue.variable true" >expect && | |
| git config ${mode_get_regexp} --bool novalue > output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success 'get-regexp variable with empty value' ' | |
| echo "emptyvalue.variable " >expect && | |
| git config ${mode_get_regexp} emptyvalue > output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success 'get bool variable with no value' ' | |
| echo true >expect && | |
| git config --bool novalue.variable > output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success 'get bool variable with empty value' ' | |
| echo false >expect && | |
| git config --bool emptyvalue.variable > output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success 'no arguments, but no crash' ' | |
| test_must_fail git config >output 2>&1 && | |
| echo "error: no action specified" >expect && | |
| test_cmp expect output | |
| ' | |
| cat > .git/config << EOF | |
| [a.b] | |
| c = d | |
| EOF | |
| test_expect_success 'new section is partial match of another' ' | |
| cat >expect <<\EOF && | |
| [a.b] | |
| c = d | |
| [a] | |
| x = y | |
| EOF | |
| git config a.x y && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'new variable inserts into proper section' ' | |
| cat >expect <<\EOF && | |
| [a.b] | |
| c = d | |
| [a] | |
| x = y | |
| b = c | |
| [b] | |
| x = y | |
| EOF | |
| git config b.x y && | |
| git config a.b c && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'alternative --file (non-existing file should fail)' ' | |
| test_must_fail git config --file non-existing-config -l && | |
| test_must_fail git config --file non-existing-config test.xyzzy | |
| ' | |
| cat > other-config << EOF | |
| [ein] | |
| bahn = strasse | |
| EOF | |
| test_expect_success 'alternative GIT_CONFIG' ' | |
| cat >expect <<-\EOF && | |
| ein.bahn=strasse | |
| EOF | |
| GIT_CONFIG=other-config git config ${mode_prefix}list >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success 'alternative GIT_CONFIG (--file)' ' | |
| git config ${mode_prefix}list --file other-config >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success 'alternative GIT_CONFIG (--file=-)' ' | |
| git config ${mode_prefix}list --file - <other-config >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success 'setting a value in stdin is an error' ' | |
| test_must_fail git config --file - some.value foo | |
| ' | |
| test_expect_success 'editing stdin is an error' ' | |
| test_must_fail git config ${mode_prefix}edit --file - | |
| ' | |
| test_expect_success 'refer config from subdirectory' ' | |
| test_when_finished "rm -r x" && | |
| mkdir x && | |
| test_cmp_config -C x strasse --file=../other-config --get ein.bahn | |
| ' | |
| test_expect_success '--set in alternative file' ' | |
| cat >expect <<\EOF && | |
| [ein] | |
| bahn = strasse | |
| [anwohner] | |
| park = ausweis | |
| EOF | |
| git config --file=other-config anwohner.park ausweis && | |
| test_cmp expect other-config | |
| ' | |
| cat > .git/config << EOF | |
| # Hallo | |
| #Bello | |
| [branch "eins"] | |
| x = 1 | |
| [branch.eins] | |
| y = 1 | |
| [branch "1 234 blabl/a"] | |
| weird | |
| EOF | |
| test_expect_success 'rename section' ' | |
| git config ${mode_prefix}rename-section branch.eins branch.zwei | |
| ' | |
| cat > expect << EOF | |
| # Hallo | |
| #Bello | |
| [branch "zwei"] | |
| x = 1 | |
| [branch "zwei"] | |
| y = 1 | |
| [branch "1 234 blabl/a"] | |
| weird | |
| EOF | |
| test_expect_success 'rename succeeded' ' | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'rename non-existing section' ' | |
| test_must_fail git config ${mode_prefix}rename-section \ | |
| branch."world domination" branch.drei | |
| ' | |
| test_expect_success 'rename succeeded' ' | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'rename another section' ' | |
| git config ${mode_prefix}rename-section branch."1 234 blabl/a" branch.drei | |
| ' | |
| test_expect_success 'rename succeeded' ' | |
| cat >expect <<\EOF && | |
| # Hallo | |
| #Bello | |
| [branch "zwei"] | |
| x = 1 | |
| [branch "zwei"] | |
| y = 1 | |
| [branch "drei"] | |
| weird | |
| EOF | |
| test_cmp expect .git/config | |
| ' | |
| cat >> .git/config << EOF | |
| [branch "vier"] z = 1 | |
| EOF | |
| test_expect_success 'rename a section with a var on the same line' ' | |
| git config ${mode_prefix}rename-section branch.vier branch.zwei | |
| ' | |
| test_expect_success 'rename succeeded' ' | |
| cat >expect <<\EOF && | |
| # Hallo | |
| #Bello | |
| [branch "zwei"] | |
| x = 1 | |
| [branch "zwei"] | |
| y = 1 | |
| [branch "drei"] | |
| weird | |
| [branch "zwei"] | |
| z = 1 | |
| EOF | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'renaming empty section name is rejected' ' | |
| test_must_fail git config ${mode_prefix}rename-section branch.zwei "" | |
| ' | |
| test_expect_success 'renaming to bogus section is rejected' ' | |
| test_must_fail git config ${mode_prefix}rename-section branch.zwei "bogus name" | |
| ' | |
| test_expect_success 'renaming a section with a long line' ' | |
| { | |
| printf "[b]\\n" && | |
| printf " c = d %1024s [a] e = f\\n" " " && | |
| printf "[a] g = h\\n" | |
| } >y && | |
| git config ${mode_prefix}rename-section -f y a xyz && | |
| test_must_fail git config -f y b.e | |
| ' | |
| test_expect_success 'renaming an embedded section with a long line' ' | |
| { | |
| printf "[b]\\n" && | |
| printf " c = d %1024s [a] [foo] e = f\\n" " " && | |
| printf "[a] g = h\\n" | |
| } >y && | |
| git config ${mode_prefix}rename-section -f y a xyz && | |
| test_must_fail git config -f y foo.e | |
| ' | |
| test_expect_success 'renaming a section with an overly-long line' ' | |
| { | |
| printf "[b]\\n" && | |
| printf " c = d %525000s e" " " && | |
| printf "[a] g = h\\n" | |
| } >y && | |
| test_must_fail git config ${mode_prefix}rename-section -f y a xyz 2>err && | |
| test_grep "refusing to work with overly long line in .y. on line 2" err | |
| ' | |
| cat >> .git/config << EOF | |
| [branch "zwei"] a = 1 [branch "vier"] | |
| EOF | |
| test_expect_success 'remove section' ' | |
| git config ${mode_prefix}remove-section branch.zwei | |
| ' | |
| test_expect_success 'section was removed properly' ' | |
| cat >expect <<\EOF && | |
| # Hallo | |
| #Bello | |
| [branch "drei"] | |
| weird | |
| EOF | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'section ending' ' | |
| cat >expect <<\EOF && | |
| [gitcvs] | |
| enabled = true | |
| dbname = %Ggitcvs2.%a.%m.sqlite | |
| [gitcvs "ext"] | |
| dbname = %Ggitcvs1.%a.%m.sqlite | |
| EOF | |
| rm -f .git/config && | |
| git config ${mode_set} gitcvs.enabled true && | |
| git config ${mode_set} gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite && | |
| git config ${mode_set} gitcvs.dbname %Ggitcvs2.%a.%m.sqlite && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success numbers ' | |
| git config ${mode_set} kilo.gram 1k && | |
| git config ${mode_set} mega.ton 1m && | |
| echo 1024 >expect && | |
| echo 1048576 >>expect && | |
| git config --int --get kilo.gram >actual && | |
| git config --int --get mega.ton >>actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success '--int is at least 64 bits' ' | |
| git config ${mode_set} giga.watts 121g && | |
| echo >expect && | |
| test_cmp_config 129922760704 --int --get giga.watts | |
| ' | |
| test_expect_success 'invalid unit' ' | |
| git config ${mode_set} aninvalid.unit "1auto" && | |
| test_cmp_config 1auto aninvalid.unit && | |
| test_must_fail git config --int --get aninvalid.unit 2>actual && | |
| test_grep "bad numeric config value .1auto. for .aninvalid.unit. in file .git/config: invalid unit" actual | |
| ' | |
| test_expect_success 'invalid unit boolean' ' | |
| git config ${mode_set} commit.gpgsign "1true" && | |
| test_cmp_config 1true commit.gpgsign && | |
| test_must_fail git config --bool --get commit.gpgsign 2>actual && | |
| test_grep "bad boolean config value .1true. for .commit.gpgsign." actual | |
| ' | |
| test_expect_success 'line number is reported correctly' ' | |
| printf "[bool]\n\tvar\n" >invalid && | |
| test_must_fail git config -f invalid --path bool.var 2>actual && | |
| test_grep "line 2" actual | |
| ' | |
| test_expect_success 'invalid stdin config' ' | |
| echo "[broken" | test_must_fail git config ${mode_prefix}list --file - >output 2>&1 && | |
| test_grep "bad config line 1 in standard input" output | |
| ' | |
| test_expect_success bool ' | |
| cat >expect <<-\EOF && | |
| true | |
| false | |
| true | |
| false | |
| true | |
| false | |
| true | |
| false | |
| EOF | |
| git config ${mode_set} bool.true1 01 && | |
| git config ${mode_set} bool.true2 -1 && | |
| git config ${mode_set} bool.true3 YeS && | |
| git config ${mode_set} bool.true4 true && | |
| git config ${mode_set} bool.false1 000 && | |
| git config ${mode_set} bool.false2 "" && | |
| git config ${mode_set} bool.false3 nO && | |
| git config ${mode_set} bool.false4 FALSE && | |
| rm -f result && | |
| for i in 1 2 3 4 | |
| do | |
| git config --bool --get bool.true$i >>result && | |
| git config --bool --get bool.false$i >>result || return 1 | |
| done && | |
| test_cmp expect result | |
| ' | |
| test_expect_success 'invalid bool (--get)' ' | |
| git config ${mode_set} bool.nobool foobar && | |
| test_must_fail git config --bool --get bool.nobool | |
| ' | |
| test_expect_success 'invalid bool (set)' ' | |
| test_must_fail git config --bool bool.nobool foobar | |
| ' | |
| test_expect_success 'set --bool' ' | |
| cat >expect <<\EOF && | |
| [bool] | |
| true1 = true | |
| true2 = true | |
| true3 = true | |
| true4 = true | |
| false1 = false | |
| false2 = false | |
| false3 = false | |
| false4 = false | |
| EOF | |
| rm -f .git/config && | |
| git config --bool bool.true1 01 && | |
| git config --bool bool.true2 -1 && | |
| git config --bool bool.true3 YeS && | |
| git config --bool bool.true4 true && | |
| git config --bool bool.false1 000 && | |
| git config --bool bool.false2 "" && | |
| git config --bool bool.false3 nO && | |
| git config --bool bool.false4 FALSE && | |
| test_cmp expect .git/config' | |
| test_expect_success 'set --int' ' | |
| cat >expect <<\EOF && | |
| [int] | |
| val1 = 1 | |
| val2 = -1 | |
| val3 = 5242880 | |
| EOF | |
| rm -f .git/config && | |
| git config --int int.val1 01 && | |
| git config --int int.val2 -1 && | |
| git config --int int.val3 5m && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'get --bool-or-int' ' | |
| cat >.git/config <<-\EOF && | |
| [bool] | |
| true1 | |
| true2 = true | |
| false = false | |
| [int] | |
| int1 = 0 | |
| int2 = 1 | |
| int3 = -1 | |
| EOF | |
| cat >expect <<-\EOF && | |
| true | |
| true | |
| false | |
| 0 | |
| 1 | |
| -1 | |
| EOF | |
| { | |
| git config --bool-or-int bool.true1 && | |
| git config --bool-or-int bool.true2 && | |
| git config --bool-or-int bool.false && | |
| git config --bool-or-int int.int1 && | |
| git config --bool-or-int int.int2 && | |
| git config --bool-or-int int.int3 | |
| } >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'set --bool-or-int' ' | |
| cat >expect <<\EOF && | |
| [bool] | |
| true1 = true | |
| false1 = false | |
| true2 = true | |
| false2 = false | |
| [int] | |
| int1 = 0 | |
| int2 = 1 | |
| int3 = -1 | |
| EOF | |
| rm -f .git/config && | |
| git config --bool-or-int bool.true1 true && | |
| git config --bool-or-int bool.false1 false && | |
| git config --bool-or-int bool.true2 yes && | |
| git config --bool-or-int bool.false2 no && | |
| git config --bool-or-int int.int1 0 && | |
| git config --bool-or-int int.int2 1 && | |
| git config --bool-or-int int.int3 -1 && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success !MINGW 'set --path' ' | |
| cat >expect <<\EOF && | |
| [path] | |
| home = ~/ | |
| normal = /dev/null | |
| trailingtilde = foo~ | |
| EOF | |
| rm -f .git/config && | |
| git config --path path.home "~/" && | |
| git config --path path.normal "/dev/null" && | |
| git config --path path.trailingtilde "foo~" && | |
| test_cmp expect .git/config | |
| ' | |
| if test_have_prereq !MINGW && test "${HOME+set}" | |
| then | |
| test_set_prereq HOMEVAR | |
| fi | |
| test_expect_success HOMEVAR 'get --path' ' | |
| cat >expect <<-EOF && | |
| $HOME/ | |
| /dev/null | |
| foo~ | |
| EOF | |
| git config --get --path path.home > result && | |
| git config --get --path path.normal >> result && | |
| git config --get --path path.trailingtilde >> result && | |
| test_cmp expect result | |
| ' | |
| test_expect_success !MINGW 'get --path copes with unset $HOME' ' | |
| cat >expect <<-\EOF && | |
| /dev/null | |
| foo~ | |
| EOF | |
| ( | |
| sane_unset HOME && | |
| test_must_fail git config --get --path path.home \ | |
| >result 2>msg && | |
| git config --get --path path.normal >>result && | |
| git config --get --path path.trailingtilde >>result | |
| ) && | |
| test_grep "[Ff]ailed to expand.*~/" msg && | |
| test_cmp expect result | |
| ' | |
| test_expect_success 'get --path barfs on boolean variable' ' | |
| echo "[path]bool" >.git/config && | |
| test_must_fail git config --get --path path.bool | |
| ' | |
| test_expect_success 'get --expiry-date' ' | |
| rel="3.weeks.5.days.00:00" && | |
| rel_out="$rel ->" && | |
| cat >.git/config <<-\EOF && | |
| [date] | |
| valid1 = "3.weeks.5.days 00:00" | |
| valid2 = "Fri Jun 4 15:46:55 2010" | |
| valid3 = "2017/11/11 11:11:11PM" | |
| valid4 = "2017/11/10 09:08:07 PM" | |
| valid5 = "never" | |
| invalid1 = "abc" | |
| EOF | |
| cat >expect <<-EOF && | |
| $(test-tool date timestamp $rel) | |
| 1275666415 | |
| 1510441871 | |
| 1510348087 | |
| 0 | |
| EOF | |
| : "work around heredoc parsing bug fixed in dash 0.5.7 (in ec2c84d)" && | |
| { | |
| echo "$rel_out $(git config --expiry-date date.valid1)" && | |
| git config --expiry-date date.valid2 && | |
| git config --expiry-date date.valid3 && | |
| git config --expiry-date date.valid4 && | |
| git config --expiry-date date.valid5 | |
| } >actual && | |
| test_cmp expect actual && | |
| test_must_fail git config --expiry-date date.invalid1 | |
| ' | |
| test_expect_success 'get --type=color' ' | |
| rm .git/config && | |
| git config ${mode_set} foo.color "red" && | |
| git config --get --type=color foo.color >actual.raw && | |
| git config get --type=color foo.color >actual-subcommand.raw && | |
| test_cmp actual.raw actual-subcommand.raw && | |
| test_decode_color <actual.raw >actual && | |
| echo "<RED>" >expect && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'get --type=color with default value only' ' | |
| git config --get-color "" "red" >actual.raw && | |
| test_decode_color <actual.raw >actual && | |
| echo "<RED>" >expect && | |
| test_cmp expect actual && | |
| git config get --type=color --default="red" "" >actual-subcommand.raw && | |
| test_cmp actual.raw actual-subcommand.raw | |
| ' | |
| test_expect_success TTY 'get --type=color does not use a pager' ' | |
| test_config core.pager "echo foobar" && | |
| test_terminal git config get --type=color --default="red" "" >actual.raw && | |
| test_decode_color <actual.raw >actual && | |
| echo "<RED>" >expect && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'set --type=color' ' | |
| cat >expect <<\EOF && | |
| [foo] | |
| color = red | |
| EOF | |
| 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_grep "cannot parse color" error | |
| ' | |
| test_expect_success 'quoting' ' | |
| cat >expect <<\EOF && | |
| [quote] | |
| leading = " test" | |
| ending = "test " | |
| semicolon = "test;test" | |
| hash = "test#test" | |
| EOF | |
| rm -f .git/config && | |
| git config ${mode_set} quote.leading " test" && | |
| git config ${mode_set} quote.ending "test " && | |
| git config ${mode_set} quote.semicolon "test;test" && | |
| git config ${mode_set} quote.hash "test#test" && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'key with newline' ' | |
| test_must_fail git config ${mode_get} "key.with | |
| newline" 123 | |
| ' | |
| test_expect_success 'value with newline' ' | |
| git config ${mode_set} key.sub value.with\\\ | |
| newline | |
| ' | |
| cat > .git/config <<\EOF | |
| [section] | |
| ; comment \ | |
| continued = cont\ | |
| inued | |
| noncont = not continued ; \ | |
| quotecont = "cont;\ | |
| inued" | |
| EOF | |
| test_expect_success 'value continued on next line' ' | |
| cat >expect <<-\EOF && | |
| section.continued=continued | |
| section.noncont=not continued | |
| section.quotecont=cont;inued | |
| EOF | |
| git config ${mode_prefix}list > result && | |
| test_cmp expect result | |
| ' | |
| cat > .git/config <<\EOF | |
| [section "sub=section"] | |
| val1 = foo=bar | |
| val2 = foo\nbar | |
| val3 = \n\n | |
| val4 = | |
| val5 | |
| EOF | |
| cat > expect <<\EOF | |
| section.sub=section.val1 | |
| foo=barQsection.sub=section.val2 | |
| foo | |
| barQsection.sub=section.val3 | |
| Qsection.sub=section.val4 | |
| Qsection.sub=section.val5Q | |
| EOF | |
| test_expect_success '--null --list' ' | |
| git config ${mode_prefix}list --null >result.raw && | |
| nul_to_q <result.raw >result && | |
| echo >>result && | |
| test_cmp expect result | |
| ' | |
| test_expect_success '--null --get-regexp' ' | |
| git config ${mode_get_regexp} --null "val[0-9]" >result.raw && | |
| nul_to_q <result.raw >result && | |
| echo >>result && | |
| test_cmp expect result | |
| ' | |
| test_expect_success 'inner whitespace kept verbatim, spaces only' ' | |
| echo "foo bar" >expect && | |
| git config ${mode_set} section.val "foo bar" && | |
| git config ${mode_get} section.val >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'inner whitespace kept verbatim, horizontal tabs only' ' | |
| echo "fooQQbar" | q_to_tab >expect && | |
| git config ${mode_set} section.val "$(cat expect)" && | |
| git config ${mode_get} section.val >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'inner whitespace kept verbatim, horizontal tabs and spaces' ' | |
| echo "foo Q bar" | q_to_tab >expect && | |
| git config ${mode_set} section.val "$(cat expect)" && | |
| git config ${mode_get} section.val >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success SYMLINKS 'symlinked configuration' ' | |
| test_when_finished "rm myconfig" && | |
| ln -s notyet myconfig && | |
| git config --file=myconfig test.frotz nitfol && | |
| test_path_is_symlink myconfig && | |
| test_path_is_file notyet && | |
| test "z$(git config --file=notyet test.frotz)" = znitfol && | |
| git config --file=myconfig test.xyzzy rezrov && | |
| test_path_is_symlink myconfig && | |
| test_path_is_file notyet && | |
| cat >expect <<-\EOF && | |
| nitfol | |
| rezrov | |
| EOF | |
| { | |
| git config --file=notyet test.frotz && | |
| git config --file=notyet test.xyzzy | |
| } >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success SYMLINKS 'symlink to nonexistent configuration' ' | |
| test_when_finished "rm linktonada linktolinktonada" && | |
| ln -s doesnotexist linktonada && | |
| ln -s linktonada linktolinktonada && | |
| test_must_fail git config ${mode_prefix}list --file=linktonada && | |
| test_must_fail git config ${mode_prefix}list --file=linktolinktonada | |
| ' | |
| test_expect_success 'check split_cmdline return' ' | |
| test_when_finished "rm -rf repo" && | |
| git init repo && | |
| ( | |
| cd repo && | |
| git config ${mode_set} alias.split-cmdline-fix "echo \"" && | |
| test_must_fail git split-cmdline-fix && | |
| echo foo >foo && | |
| git add foo && | |
| git commit -m "initial commit" && | |
| git config ${mode_set} branch.main.mergeoptions "echo \"" && | |
| test_must_fail git merge main | |
| ) | |
| ' | |
| test_expect_success 'git -c "key=value" support' ' | |
| cat >expect <<-\EOF && | |
| value | |
| value | |
| true | |
| EOF | |
| { | |
| git -c section.name=value config section.name && | |
| git -c foo.CamelCase=value config foo.camelcase && | |
| git -c foo.flag config --bool foo.flag | |
| } >actual && | |
| test_cmp expect actual && | |
| test_must_fail git -c name=value config section.name | |
| ' | |
| # We just need a type-specifier here that cares about the | |
| # distinction internally between a NULL boolean and a real | |
| # string (because most of git's internal parsers do care). | |
| # Using "--path" works, but we do not otherwise care about | |
| # its semantics. | |
| test_expect_success 'git -c can represent empty string' ' | |
| echo >expect && | |
| git -c foo.empty= config --path foo.empty >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'key sanity-checking' ' | |
| test_must_fail git config ${mode_get} foo=bar && | |
| test_must_fail git config ${mode_get} foo=.bar && | |
| test_must_fail git config ${mode_get} foo.ba=r && | |
| test_must_fail git config ${mode_get} foo.1bar && | |
| test_must_fail git config ${mode_get} foo."ba | |
| z".bar && | |
| test_must_fail git config ${mode_set} . false && | |
| test_must_fail git config ${mode_set} .foo false && | |
| test_must_fail git config ${mode_set} foo. false && | |
| test_must_fail git config ${mode_set} .foo. false && | |
| git config ${mode_set} foo.bar true && | |
| git config ${mode_set} foo."ba =z".bar false | |
| ' | |
| test_expect_success 'git -c works with aliases of builtins' ' | |
| git config alias.checkconfig "-c foo.check=bar config foo.check" && | |
| echo bar >expect && | |
| git checkconfig >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'aliases can be CamelCased' ' | |
| test_when_finished "rm -rf repo" && | |
| git init repo && | |
| ( | |
| cd repo && | |
| test_commit A && | |
| git config alias.CamelCased "rev-parse HEAD" && | |
| git CamelCased >out && | |
| git rev-parse HEAD >expect && | |
| test_cmp expect out | |
| ) | |
| ' | |
| test_expect_success 'git -c does not split values on equals' ' | |
| echo "value with = in it" >expect && | |
| git -c section.foo="value with = in it" config section.foo >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'git -c dies on bogus config' ' | |
| test_must_fail git -c core.bare=foo rev-parse | |
| ' | |
| test_expect_success 'git -c complains about empty key' ' | |
| test_must_fail git -c "=foo" rev-parse | |
| ' | |
| test_expect_success 'git -c complains about empty key and value' ' | |
| test_must_fail git -c "" rev-parse | |
| ' | |
| test_expect_success 'multiple git -c appends config' ' | |
| test_config alias.x "!git -c x.two=2 config ${mode_get_regexp} ^x\.*" && | |
| cat >expect <<-\EOF && | |
| x.one 1 | |
| x.two 2 | |
| EOF | |
| git -c x.one=1 x >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'last one wins: two level vars' ' | |
| # sec.var and sec.VAR are the same variable, as the first | |
| # and the last level of a configuration variable name is | |
| # case insensitive. | |
| echo VAL >expect && | |
| git -c sec.var=val -c sec.VAR=VAL config --get sec.var >actual && | |
| test_cmp expect actual && | |
| git -c SEC.var=val -c sec.var=VAL config --get sec.var >actual && | |
| test_cmp expect actual && | |
| git -c sec.var=val -c sec.VAR=VAL config --get SEC.var >actual && | |
| test_cmp expect actual && | |
| git -c SEC.var=val -c sec.var=VAL config --get sec.VAR >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'last one wins: three level vars' ' | |
| # v.a.r and v.A.r are not the same variable, as the middle | |
| # level of a three-level configuration variable name is | |
| # case sensitive. | |
| echo val >expect && | |
| git -c v.a.r=val -c v.A.r=VAL config --get v.a.r >actual && | |
| test_cmp expect actual && | |
| git -c v.a.r=val -c v.A.r=VAL config --get V.a.R >actual && | |
| test_cmp expect actual && | |
| # v.a.r and V.a.R are the same variable, as the first | |
| # and the last level of a configuration variable name is | |
| # case insensitive. | |
| echo VAL >expect && | |
| git -c v.a.r=val -c v.a.R=VAL config --get v.a.r >actual && | |
| test_cmp expect actual && | |
| git -c v.a.r=val -c V.a.r=VAL config --get v.a.r >actual && | |
| test_cmp expect actual && | |
| git -c v.a.r=val -c v.a.R=VAL config --get V.a.R >actual && | |
| test_cmp expect actual && | |
| git -c v.a.r=val -c V.a.r=VAL config --get V.a.R >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'old-fashioned settings are case insensitive' ' | |
| test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" && | |
| cat >testConfig_actual <<-EOF && | |
| [V.A] | |
| r = value1 | |
| EOF | |
| q_to_tab >testConfig_expect <<-EOF && | |
| [V.A] | |
| Qr = value2 | |
| EOF | |
| git config -f testConfig_actual "v.a.r" value2 && | |
| test_cmp testConfig_expect testConfig_actual && | |
| cat >testConfig_actual <<-EOF && | |
| [V.A] | |
| r = value1 | |
| EOF | |
| q_to_tab >testConfig_expect <<-EOF && | |
| [V.A] | |
| QR = value2 | |
| EOF | |
| git config -f testConfig_actual "V.a.R" value2 && | |
| test_cmp testConfig_expect testConfig_actual && | |
| cat >testConfig_actual <<-EOF && | |
| [V.A] | |
| r = value1 | |
| EOF | |
| q_to_tab >testConfig_expect <<-EOF && | |
| [V.A] | |
| r = value1 | |
| Qr = value2 | |
| EOF | |
| git config -f testConfig_actual "V.A.r" value2 && | |
| test_cmp testConfig_expect testConfig_actual && | |
| cat >testConfig_actual <<-EOF && | |
| [V.A] | |
| r = value1 | |
| EOF | |
| q_to_tab >testConfig_expect <<-EOF && | |
| [V.A] | |
| r = value1 | |
| Qr = value2 | |
| EOF | |
| git config -f testConfig_actual "v.A.r" value2 && | |
| test_cmp testConfig_expect testConfig_actual | |
| ' | |
| test_expect_success 'setting different case sensitive subsections ' ' | |
| test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" && | |
| cat >testConfig_actual <<-EOF && | |
| [V "A"] | |
| R = v1 | |
| [K "E"] | |
| Y = v1 | |
| [a "b"] | |
| c = v1 | |
| [d "e"] | |
| f = v1 | |
| EOF | |
| q_to_tab >testConfig_expect <<-EOF && | |
| [V "A"] | |
| Qr = v2 | |
| [K "E"] | |
| Qy = v2 | |
| [a "b"] | |
| Qc = v2 | |
| [d "e"] | |
| f = v1 | |
| [d "E"] | |
| Qf = v2 | |
| EOF | |
| # exact match | |
| git config -f testConfig_actual a.b.c v2 && | |
| # match section and subsection, key is cased differently. | |
| git config -f testConfig_actual K.E.y v2 && | |
| # section and key are matched case insensitive, but subsection needs | |
| # to match; When writing out new values only the key is adjusted | |
| git config -f testConfig_actual v.A.r v2 && | |
| # subsection is not matched: | |
| git config -f testConfig_actual d.E.f v2 && | |
| test_cmp testConfig_expect testConfig_actual | |
| ' | |
| for VAR in a .a a. a.0b a."b c". a."b c".0d | |
| do | |
| test_expect_success "git -c $VAR=VAL rejects invalid '$VAR'" ' | |
| test_must_fail git -c "$VAR=VAL" config -l | |
| ' | |
| done | |
| for VAR in a.b a."b c".d | |
| do | |
| test_expect_success "git -c $VAR=VAL works with valid '$VAR'" ' | |
| echo VAL >expect && | |
| git -c "$VAR=VAL" config --get "$VAR" >actual && | |
| test_cmp expect actual | |
| ' | |
| done | |
| test_expect_success 'git -c is not confused by empty environment' ' | |
| GIT_CONFIG_PARAMETERS="" git -c x.one=1 config ${mode_prefix}list | |
| ' | |
| test_expect_success 'GIT_CONFIG_PARAMETERS handles old-style entries' ' | |
| v="${SQ}key.one=foo${SQ}" && | |
| v="$v ${SQ}key.two=bar${SQ}" && | |
| v="$v ${SQ}key.ambiguous=section.whatever=value${SQ}" && | |
| GIT_CONFIG_PARAMETERS=$v git config ${mode_get_regexp} "key.*" >actual && | |
| cat >expect <<-EOF && | |
| key.one foo | |
| key.two bar | |
| key.ambiguous section.whatever=value | |
| EOF | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'GIT_CONFIG_PARAMETERS handles new-style entries' ' | |
| v="${SQ}key.one${SQ}=${SQ}foo${SQ}" && | |
| v="$v ${SQ}key.two${SQ}=${SQ}bar${SQ}" && | |
| v="$v ${SQ}key.ambiguous=section.whatever${SQ}=${SQ}value${SQ}" && | |
| GIT_CONFIG_PARAMETERS=$v git config ${mode_get_regexp} "key.*" >actual && | |
| cat >expect <<-EOF && | |
| key.one foo | |
| key.two bar | |
| key.ambiguous=section.whatever value | |
| EOF | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'old and new-style entries can mix' ' | |
| v="${SQ}key.oldone=oldfoo${SQ}" && | |
| v="$v ${SQ}key.newone${SQ}=${SQ}newfoo${SQ}" && | |
| v="$v ${SQ}key.oldtwo=oldbar${SQ}" && | |
| v="$v ${SQ}key.newtwo${SQ}=${SQ}newbar${SQ}" && | |
| GIT_CONFIG_PARAMETERS=$v git config ${mode_get_regexp} "key.*" >actual && | |
| cat >expect <<-EOF && | |
| key.oldone oldfoo | |
| key.newone newfoo | |
| key.oldtwo oldbar | |
| key.newtwo newbar | |
| EOF | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'old and new bools with ambiguous subsection' ' | |
| v="${SQ}key.with=equals.oldbool${SQ}" && | |
| v="$v ${SQ}key.with=equals.newbool${SQ}=" && | |
| GIT_CONFIG_PARAMETERS=$v git config ${mode_get_regexp} "key.*" >actual && | |
| cat >expect <<-EOF && | |
| key.with equals.oldbool | |
| key.with=equals.newbool | |
| EOF | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'detect bogus GIT_CONFIG_PARAMETERS' ' | |
| cat >expect <<-\EOF && | |
| env.one one | |
| env.two two | |
| EOF | |
| GIT_CONFIG_PARAMETERS="${SQ}env.one=one${SQ} ${SQ}env.two=two${SQ}" \ | |
| git config ${mode_get_regexp} "env.*" >actual && | |
| test_cmp expect actual && | |
| cat >expect <<-EOF && | |
| env.one one${SQ} | |
| env.two two | |
| EOF | |
| GIT_CONFIG_PARAMETERS="${SQ}env.one=one${SQ}\\$SQ$SQ$SQ ${SQ}env.two=two${SQ}" \ | |
| git config ${mode_get_regexp} "env.*" >actual && | |
| test_cmp expect actual && | |
| test_must_fail env \ | |
| GIT_CONFIG_PARAMETERS="${SQ}env.one=one${SQ}\\$SQ ${SQ}env.two=two${SQ}" \ | |
| git config ${mode_get_regexp} "env.*" | |
| ' | |
| test_expect_success 'git --config-env=key=envvar support' ' | |
| cat >expect <<-\EOF && | |
| value | |
| value | |
| value | |
| value | |
| false | |
| false | |
| EOF | |
| { | |
| ENVVAR=value git --config-env=core.name=ENVVAR config core.name && | |
| ENVVAR=value git --config-env core.name=ENVVAR config core.name && | |
| ENVVAR=value git --config-env=foo.CamelCase=ENVVAR config foo.camelcase && | |
| ENVVAR=value git --config-env foo.CamelCase=ENVVAR config foo.camelcase && | |
| ENVVAR= git --config-env=foo.flag=ENVVAR config --bool foo.flag && | |
| ENVVAR= git --config-env foo.flag=ENVVAR config --bool foo.flag | |
| } >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'git --config-env with missing value' ' | |
| test_must_fail env ENVVAR=value git --config-env 2>error && | |
| test_grep "no config key given for --config-env" error && | |
| test_must_fail env ENVVAR=value git --config-env config core.name 2>error && | |
| test_grep "invalid config format: config" error | |
| ' | |
| test_expect_success 'git --config-env fails with invalid parameters' ' | |
| test_must_fail git --config-env=foo.flag config --bool foo.flag 2>error && | |
| test_grep "invalid config format: foo.flag" error && | |
| test_must_fail git --config-env=foo.flag= config --bool foo.flag 2>error && | |
| test_grep "missing environment variable name for configuration ${SQ}foo.flag${SQ}" error && | |
| sane_unset NONEXISTENT && | |
| test_must_fail git --config-env=foo.flag=NONEXISTENT config --bool foo.flag 2>error && | |
| test_grep "missing environment variable ${SQ}NONEXISTENT${SQ} for configuration ${SQ}foo.flag${SQ}" error | |
| ' | |
| test_expect_success 'git -c and --config-env work together' ' | |
| cat >expect <<-\EOF && | |
| bar.cmd cmd-value | |
| bar.env env-value | |
| EOF | |
| ENVVAR=env-value git \ | |
| -c bar.cmd=cmd-value \ | |
| --config-env=bar.env=ENVVAR \ | |
| config ${mode_get_regexp} "^bar.*" >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'git -c and --config-env override each other' ' | |
| cat >expect <<-\EOF && | |
| env | |
| cmd | |
| EOF | |
| { | |
| ENVVAR=env git -c bar.bar=cmd --config-env=bar.bar=ENVVAR config bar.bar && | |
| ENVVAR=env git --config-env=bar.bar=ENVVAR -c bar.bar=cmd config bar.bar | |
| } >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success '--config-env handles keys with equals' ' | |
| echo value=with=equals >expect && | |
| ENVVAR=value=with=equals git \ | |
| --config-env=section.subsection=with=equals.key=ENVVAR \ | |
| config section.subsection=with=equals.key >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'git config handles environment config pairs' ' | |
| GIT_CONFIG_COUNT=2 \ | |
| GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="foo" \ | |
| GIT_CONFIG_KEY_1="pair.two" GIT_CONFIG_VALUE_1="bar" \ | |
| git config ${mode_get_regexp} "pair.*" >actual && | |
| cat >expect <<-EOF && | |
| pair.one foo | |
| pair.two bar | |
| EOF | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'git config ignores pairs without count' ' | |
| test_must_fail env GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ | |
| git config ${mode_get} pair.one 2>error && | |
| test_must_be_empty error | |
| ' | |
| test_expect_success 'git config ignores pairs exceeding count' ' | |
| GIT_CONFIG_COUNT=1 \ | |
| GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ | |
| GIT_CONFIG_KEY_1="pair.two" GIT_CONFIG_VALUE_1="value" \ | |
| git config ${mode_get_regexp} "pair.*" >actual 2>error && | |
| cat >expect <<-EOF && | |
| pair.one value | |
| EOF | |
| test_cmp expect actual && | |
| test_must_be_empty error | |
| ' | |
| test_expect_success 'git config ignores pairs with zero count' ' | |
| test_must_fail env \ | |
| GIT_CONFIG_COUNT=0 GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ | |
| git config ${mode_get} pair.one 2>error && | |
| test_must_be_empty error | |
| ' | |
| test_expect_success 'git config ignores pairs with empty count' ' | |
| test_must_fail env \ | |
| GIT_CONFIG_COUNT= GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ | |
| git config ${mode_get} pair.one 2>error && | |
| test_must_be_empty error | |
| ' | |
| test_expect_success 'git config fails with invalid count' ' | |
| test_must_fail env GIT_CONFIG_COUNT=10a git config ${mode_prefix}list 2>error && | |
| test_grep "bogus count" error && | |
| test_must_fail env GIT_CONFIG_COUNT=9999999999999999 git config ${mode_prefix}list 2>error && | |
| test_grep "too many entries" error | |
| ' | |
| test_expect_success 'git config fails with missing config key' ' | |
| test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_VALUE_0="value" \ | |
| git config ${mode_prefix}list 2>error && | |
| test_grep "missing config key" error | |
| ' | |
| test_expect_success 'git config fails with missing config value' ' | |
| test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0="pair.one" \ | |
| git config ${mode_prefix}list 2>error && | |
| test_grep "missing config value" error | |
| ' | |
| test_expect_success 'git config fails with invalid config pair key' ' | |
| test_must_fail env GIT_CONFIG_COUNT=1 \ | |
| GIT_CONFIG_KEY_0= GIT_CONFIG_VALUE_0=value \ | |
| git config ${mode_prefix}list && | |
| test_must_fail env GIT_CONFIG_COUNT=1 \ | |
| GIT_CONFIG_KEY_0=missing-section GIT_CONFIG_VALUE_0=value \ | |
| git config ${mode_prefix}list | |
| ' | |
| test_expect_success 'environment overrides config file' ' | |
| test_when_finished "rm -f .git/config" && | |
| cat >.git/config <<-EOF && | |
| [pair] | |
| one = value | |
| EOF | |
| GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=pair.one GIT_CONFIG_VALUE_0=override \ | |
| git config ${mode_get} pair.one >actual && | |
| cat >expect <<-EOF && | |
| override | |
| EOF | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'GIT_CONFIG_PARAMETERS overrides environment config' ' | |
| GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=pair.one GIT_CONFIG_VALUE_0=value \ | |
| GIT_CONFIG_PARAMETERS="${SQ}pair.one=override${SQ}" \ | |
| git config ${mode_get} pair.one >actual && | |
| cat >expect <<-EOF && | |
| override | |
| EOF | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'command line overrides environment config' ' | |
| GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=pair.one GIT_CONFIG_VALUE_0=value \ | |
| git -c pair.one=override config pair.one >actual && | |
| cat >expect <<-EOF && | |
| override | |
| EOF | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'git config --edit works' ' | |
| git config -f tmp test.value no && | |
| echo test.value=yes >expect && | |
| GIT_EDITOR="echo [test]value=yes >" git config ${mode_prefix}edit -f tmp && | |
| git config ${mode_prefix}list -f tmp >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'git config --edit respects core.editor' ' | |
| git config -f tmp test.value no && | |
| echo test.value=yes >expect && | |
| test_config core.editor "echo [test]value=yes >" && | |
| git config ${mode_prefix}edit -f tmp && | |
| git config ${mode_prefix}list -f tmp >actual && | |
| test_cmp expect actual | |
| ' | |
| # malformed configuration files | |
| test_expect_success 'barf on syntax error' ' | |
| cat >.git/config <<-\EOF && | |
| # broken key=value | |
| [section] | |
| key garbage | |
| EOF | |
| test_must_fail git config --get section.key 2>error && | |
| test_grep " line 3 " error | |
| ' | |
| test_expect_success 'barf on incomplete section header' ' | |
| cat >.git/config <<-\EOF && | |
| # broken section line | |
| [section | |
| key = value | |
| EOF | |
| test_must_fail git config --get section.key 2>error && | |
| test_grep " line 2 " error | |
| ' | |
| test_expect_success 'barf on incomplete string' ' | |
| cat >.git/config <<-\EOF && | |
| # broken value string | |
| [section] | |
| key = "value string | |
| EOF | |
| test_must_fail git config --get section.key 2>error && | |
| test_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 | |
| test_expect_code 1 git config --bool --get-urlmatch doesnt.exist https://good.example.com >actual && | |
| test_must_be_empty actual && | |
| test_expect_code 1 git config get --url=https://good.example.com --bool doesnt.exist >actual && | |
| test_must_be_empty actual && | |
| echo true >expect && | |
| git config --bool --get-urlmatch http.SSLverify https://good.example.com >actual && | |
| test_cmp expect actual && | |
| git config get --bool --url=https://good.example.com http.SSLverify >actual && | |
| test_cmp expect actual && | |
| echo false >expect && | |
| git config --bool --get-urlmatch http.sslverify https://weak.example.com >actual && | |
| test_cmp expect actual && | |
| git config get --bool --url=https://weak.example.com http.sslverify >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 && | |
| git config get --url=https://weak.example.com HTTP >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'urlmatch with --show-scope' ' | |
| cat >.git/config <<-\EOF && | |
| [http "https://weak.example.com"] | |
| sslVerify = false | |
| cookieFile = /tmp/cookie.txt | |
| EOF | |
| cat >expect <<-EOF && | |
| local http.cookiefile /tmp/cookie.txt | |
| local http.sslverify false | |
| EOF | |
| git config --get-urlmatch --show-scope HTTP https://weak.example.com >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://weak.example.com --show-scope HTTP >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'urlmatch favors more specific URLs' ' | |
| cat >.git/config <<-\EOF && | |
| [http "https://example.com/"] | |
| cookieFile = /tmp/root.txt | |
| [http "https://example.com/subdirectory"] | |
| cookieFile = /tmp/subdirectory.txt | |
| [http "https://user@example.com/"] | |
| cookieFile = /tmp/user.txt | |
| [http "https://averylonguser@example.com/"] | |
| cookieFile = /tmp/averylonguser.txt | |
| [http "https://preceding.example.com"] | |
| cookieFile = /tmp/preceding.txt | |
| [http "https://*.example.com"] | |
| cookieFile = /tmp/wildcard.txt | |
| [http "https://*.example.com/wildcardwithsubdomain"] | |
| cookieFile = /tmp/wildcardwithsubdomain.txt | |
| [http "https://*.example.*"] | |
| cookieFile = /tmp/multiwildcard.txt | |
| [http "https://trailing.example.com"] | |
| cookieFile = /tmp/trailing.txt | |
| [http "https://user@*.example.com/"] | |
| cookieFile = /tmp/wildcardwithuser.txt | |
| [http "https://sub.example.com/"] | |
| cookieFile = /tmp/sub.txt | |
| EOF | |
| echo http.cookiefile /tmp/root.txt >expect && | |
| git config --get-urlmatch HTTP https://example.com >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://example.com HTTP >actual && | |
| test_cmp expect actual && | |
| echo http.cookiefile /tmp/subdirectory.txt >expect && | |
| git config --get-urlmatch HTTP https://example.com/subdirectory >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://example.com/subdirectory HTTP >actual && | |
| test_cmp expect actual && | |
| echo http.cookiefile /tmp/subdirectory.txt >expect && | |
| git config --get-urlmatch HTTP https://example.com/subdirectory/nested >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://example.com/subdirectory/nested HTTP >actual && | |
| test_cmp expect actual && | |
| echo http.cookiefile /tmp/user.txt >expect && | |
| git config --get-urlmatch HTTP https://user@example.com/ >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://user@example.com/ HTTP >actual && | |
| test_cmp expect actual && | |
| echo http.cookiefile /tmp/subdirectory.txt >expect && | |
| git config --get-urlmatch HTTP https://averylonguser@example.com/subdirectory >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://averylonguser@example.com/subdirectory HTTP >actual && | |
| test_cmp expect actual && | |
| echo http.cookiefile /tmp/preceding.txt >expect && | |
| git config --get-urlmatch HTTP https://preceding.example.com >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://preceding.example.com HTTP >actual && | |
| test_cmp expect actual && | |
| echo http.cookiefile /tmp/wildcard.txt >expect && | |
| git config --get-urlmatch HTTP https://wildcard.example.com >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://wildcard.example.com HTTP >actual && | |
| test_cmp expect actual && | |
| echo http.cookiefile /tmp/sub.txt >expect && | |
| git config --get-urlmatch HTTP https://sub.example.com/wildcardwithsubdomain >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://sub.example.com/wildcardwithsubdomain HTTP >actual && | |
| test_cmp expect actual && | |
| echo http.cookiefile /tmp/trailing.txt >expect && | |
| git config --get-urlmatch HTTP https://trailing.example.com >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://trailing.example.com HTTP >actual && | |
| test_cmp expect actual && | |
| echo http.cookiefile /tmp/sub.txt >expect && | |
| git config --get-urlmatch HTTP https://user@sub.example.com >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://user@sub.example.com HTTP >actual && | |
| test_cmp expect actual && | |
| echo http.cookiefile /tmp/multiwildcard.txt >expect && | |
| git config --get-urlmatch HTTP https://wildcard.example.org >actual && | |
| test_cmp expect actual && | |
| git config get --url=https://wildcard.example.org HTTP >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'urlmatch with wildcard' ' | |
| cat >.git/config <<-\EOF && | |
| [http] | |
| sslVerify | |
| [http "https://*.example.com"] | |
| sslVerify = false | |
| cookieFile = /tmp/cookie.txt | |
| EOF | |
| test_expect_code 1 git config --bool --get-urlmatch doesnt.exist https://good.example.com >actual && | |
| test_must_be_empty actual && | |
| echo true >expect && | |
| git config --bool --get-urlmatch http.SSLverify https://example.com >actual && | |
| test_cmp expect actual && | |
| echo true >expect && | |
| git config --bool --get-urlmatch http.SSLverify https://good-example.com >actual && | |
| test_cmp expect actual && | |
| echo true >expect && | |
| git config --bool --get-urlmatch http.sslverify https://deep.nested.example.com >actual && | |
| test_cmp expect actual && | |
| echo false >expect && | |
| git config --bool --get-urlmatch http.sslverify https://good.example.com >actual && | |
| test_cmp expect actual && | |
| { | |
| echo http.cookiefile /tmp/cookie.txt && | |
| echo http.sslverify false | |
| } >expect && | |
| git config --get-urlmatch HTTP https://good.example.com >actual && | |
| test_cmp expect actual && | |
| echo http.sslverify >expect && | |
| git config --get-urlmatch HTTP https://more.example.com.au >actual && | |
| test_cmp expect actual | |
| ' | |
| # good section hygiene | |
| test_expect_success '--unset last key removes section (except if commented)' ' | |
| cat >.git/config <<-\EOF && | |
| # some generic comment on the configuration file itself | |
| # a comment specific to this "section" section. | |
| [section] | |
| # some intervening lines | |
| # that should also be dropped | |
| key = value | |
| # please be careful when you update the above variable | |
| EOF | |
| cat >expect <<-\EOF && | |
| # some generic comment on the configuration file itself | |
| # a comment specific to this "section" section. | |
| [section] | |
| # some intervening lines | |
| # that should also be dropped | |
| # please be careful when you update the above variable | |
| EOF | |
| git config ${mode_unset} section.key && | |
| test_cmp expect .git/config && | |
| cat >.git/config <<-\EOF && | |
| [section] | |
| key = value | |
| [next-section] | |
| EOF | |
| cat >expect <<-\EOF && | |
| [next-section] | |
| EOF | |
| git config ${mode_unset} section.key && | |
| test_cmp expect .git/config && | |
| q_to_tab >.git/config <<-\EOF && | |
| [one] | |
| Qkey = "multiline \ | |
| QQ# with comment" | |
| [two] | |
| key = true | |
| EOF | |
| git config ${mode_unset} two.key && | |
| test_grep ! two .git/config && | |
| q_to_tab >.git/config <<-\EOF && | |
| [one] | |
| Qkey = "multiline \ | |
| QQ# with comment" | |
| [one] | |
| key = true | |
| EOF | |
| git config ${mode_unset_all} one.key && | |
| test_line_count = 0 .git/config && | |
| q_to_tab >.git/config <<-\EOF && | |
| [one] | |
| Qkey = true | |
| Q# a comment not at the start | |
| [two] | |
| Qkey = true | |
| EOF | |
| git config ${mode_unset} two.key && | |
| test_grep two .git/config && | |
| q_to_tab >.git/config <<-\EOF && | |
| [one] | |
| Qkey = not [two "subsection"] | |
| [two "subsection"] | |
| [two "subsection"] | |
| Qkey = true | |
| [TWO "subsection"] | |
| [one] | |
| EOF | |
| git config ${mode_unset} two.subsection.key && | |
| test "not [two subsection]" = "$(git config ${mode_get} one.key)" && | |
| test_line_count = 3 .git/config | |
| ' | |
| test_expect_success '--unset-all removes section if empty & uncommented' ' | |
| cat >.git/config <<-\EOF && | |
| [section] | |
| key = value1 | |
| key = value2 | |
| EOF | |
| git config ${mode_unset_all} section.key && | |
| test_line_count = 0 .git/config | |
| ' | |
| test_expect_success 'adding a key into an empty section reuses header' ' | |
| cat >.git/config <<-\EOF && | |
| [section] | |
| EOF | |
| q_to_tab >expect <<-\EOF && | |
| [section] | |
| Qkey = value | |
| EOF | |
| git config section.key value && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success POSIXPERM,PERL 'preserves existing permissions' ' | |
| chmod 0600 .git/config && | |
| git config imap.pass Hunter2 && | |
| perl -e \ | |
| "die q(badset) if ((stat(q(.git/config)))[2] & 07777) != 0600" && | |
| git config ${mode_prefix}rename-section imap pop && | |
| perl -e \ | |
| "die q(badrename) if ((stat(q(.git/config)))[2] & 07777) != 0600" | |
| ' | |
| ! test_have_prereq MINGW || | |
| HOME="$(pwd)" # convert to Windows path | |
| test_expect_success 'set up --show-origin tests' ' | |
| INCLUDE_DIR="$HOME/include" && | |
| mkdir -p "$INCLUDE_DIR" && | |
| cat >"$INCLUDE_DIR"/absolute.include <<-\EOF && | |
| [user] | |
| absolute = include | |
| EOF | |
| cat >"$INCLUDE_DIR"/relative.include <<-\EOF && | |
| [user] | |
| relative = include | |
| EOF | |
| cat >"$HOME"/.gitconfig <<-EOF && | |
| [user] | |
| global = true | |
| override = global | |
| [include] | |
| path = "$INCLUDE_DIR/absolute.include" | |
| EOF | |
| cat >.git/config <<-\EOF | |
| [user] | |
| local = true | |
| override = local | |
| [include] | |
| path = ../include/relative.include | |
| EOF | |
| ' | |
| test_expect_success '--show-origin with --list' ' | |
| cat >expect <<-EOF && | |
| file:$HOME/.gitconfig user.global=true | |
| file:$HOME/.gitconfig user.override=global | |
| file:$HOME/.gitconfig include.path=$INCLUDE_DIR/absolute.include | |
| file:$INCLUDE_DIR/absolute.include user.absolute=include | |
| file:.git/config user.local=true | |
| file:.git/config user.override=local | |
| file:.git/config include.path=../include/relative.include | |
| file:.git/../include/relative.include user.relative=include | |
| command line: user.environ=true | |
| command line: user.cmdline=true | |
| EOF | |
| GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=user.environ GIT_CONFIG_VALUE_0=true\ | |
| git -c user.cmdline=true config ${mode_prefix}list --show-origin >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--show-origin with --list --null' ' | |
| cat >expect <<-EOF && | |
| file:$HOME/.gitconfigQuser.global | |
| trueQfile:$HOME/.gitconfigQuser.override | |
| globalQfile:$HOME/.gitconfigQinclude.path | |
| $INCLUDE_DIR/absolute.includeQfile:$INCLUDE_DIR/absolute.includeQuser.absolute | |
| includeQfile:.git/configQuser.local | |
| trueQfile:.git/configQuser.override | |
| localQfile:.git/configQinclude.path | |
| ../include/relative.includeQfile:.git/../include/relative.includeQuser.relative | |
| includeQcommand line:Quser.cmdline | |
| trueQ | |
| EOF | |
| git -c user.cmdline=true config ${mode_prefix}list --null --show-origin >output.raw && | |
| nul_to_q <output.raw >output && | |
| # The here-doc above adds a newline that the --null output would not | |
| # include. Add it here to make the two comparable. | |
| echo >>output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--show-origin with single file' ' | |
| cat >expect <<-\EOF && | |
| file:.git/config user.local=true | |
| file:.git/config user.override=local | |
| file:.git/config include.path=../include/relative.include | |
| EOF | |
| git config ${mode_prefix}list --local --show-origin >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--show-origin with --get-regexp' ' | |
| cat >expect <<-EOF && | |
| file:$HOME/.gitconfig user.global true | |
| file:.git/config user.local true | |
| EOF | |
| git config ${mode_get_regexp} --show-origin "user\.[g|l].*" >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--show-origin getting a single key' ' | |
| cat >expect <<-\EOF && | |
| file:.git/config local | |
| EOF | |
| git config ${mode_get} --show-origin user.override >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success 'set up custom config file' ' | |
| cat >"custom.conf" <<-\EOF && | |
| [user] | |
| custom = true | |
| EOF | |
| CUSTOM_CONFIG_FILE="$(test-tool path-utils real_path custom.conf)" | |
| ' | |
| test_expect_success !MINGW 'set up custom config file with special name characters' ' | |
| WEIRDLY_NAMED_FILE="file\" (dq) and spaces.conf" && | |
| cp "$CUSTOM_CONFIG_FILE" "$WEIRDLY_NAMED_FILE" | |
| ' | |
| test_expect_success !MINGW '--show-origin escape special file name characters' ' | |
| cat >expect <<-\EOF && | |
| file:"file\" (dq) and spaces.conf" user.custom=true | |
| EOF | |
| git config ${mode_prefix}list --file "$WEIRDLY_NAMED_FILE" --show-origin >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--show-origin stdin' ' | |
| cat >expect <<-\EOF && | |
| standard input: user.custom=true | |
| EOF | |
| git config ${mode_prefix}list --file - --show-origin <"$CUSTOM_CONFIG_FILE" >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--show-origin stdin with file include' ' | |
| cat >"$INCLUDE_DIR"/stdin.include <<-EOF && | |
| [user] | |
| stdin = include | |
| EOF | |
| cat >expect <<-EOF && | |
| file:$INCLUDE_DIR/stdin.include include | |
| EOF | |
| echo "[include]path=\"$INCLUDE_DIR\"/stdin.include" | | |
| git config --show-origin --includes --file - user.stdin >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--show-origin blob' ' | |
| test_when_finished "rm -rf repo" && | |
| git init repo && | |
| ( | |
| cd repo && | |
| blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") && | |
| cat >expect <<-EOF && | |
| blob:$blob user.custom=true | |
| EOF | |
| git config ${mode_prefix}list --blob=$blob --show-origin >output && | |
| test_cmp expect output | |
| ) | |
| ' | |
| test_expect_success '--show-origin blob ref' ' | |
| test_when_finished "rm -rf repo" && | |
| git init repo && | |
| ( | |
| cd repo && | |
| cat >expect <<-\EOF && | |
| blob:main:custom.conf user.custom=true | |
| EOF | |
| cp "$CUSTOM_CONFIG_FILE" custom.conf && | |
| git add custom.conf && | |
| git commit -m "new config file" && | |
| git config ${mode_prefix}list --blob=main:custom.conf --show-origin >output && | |
| test_cmp expect output | |
| ) | |
| ' | |
| test_expect_success '--show-origin with --default' ' | |
| git config --show-origin --default foo some.key >actual && | |
| echo "command line: foo" >expect && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success '--show-scope with --list' ' | |
| cat >expect <<-EOF && | |
| global user.global=true | |
| global user.override=global | |
| global include.path=$INCLUDE_DIR/absolute.include | |
| global user.absolute=include | |
| local user.local=true | |
| local user.override=local | |
| local include.path=../include/relative.include | |
| local user.relative=include | |
| local core.repositoryformatversion=1 | |
| local extensions.worktreeconfig=true | |
| worktree user.worktree=true | |
| command user.cmdline=true | |
| EOF | |
| test_when_finished "git worktree remove wt1" && | |
| git worktree add wt1 && | |
| # We need these to test for worktree scope, but outside of this | |
| # test, this is just noise | |
| test_config core.repositoryformatversion 1 && | |
| test_config extensions.worktreeConfig true && | |
| git config --worktree user.worktree true && | |
| git -c user.cmdline=true config ${mode_prefix}list --show-scope >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success !MINGW '--show-scope with --blob' ' | |
| blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") && | |
| cat >expect <<-EOF && | |
| command user.custom=true | |
| EOF | |
| git config ${mode_prefix}list --blob=$blob --show-scope >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--show-scope with --local' ' | |
| cat >expect <<-\EOF && | |
| local user.local=true | |
| local user.override=local | |
| local include.path=../include/relative.include | |
| EOF | |
| git config ${mode_prefix}list --local --show-scope >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--show-scope getting a single value' ' | |
| cat >expect <<-\EOF && | |
| local true | |
| EOF | |
| git config ${mode_get} --show-scope user.local >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--show-scope with --show-origin' ' | |
| cat >expect <<-EOF && | |
| global file:$HOME/.gitconfig user.global=true | |
| global file:$HOME/.gitconfig user.override=global | |
| global file:$HOME/.gitconfig include.path=$INCLUDE_DIR/absolute.include | |
| global file:$INCLUDE_DIR/absolute.include user.absolute=include | |
| local file:.git/config user.local=true | |
| local file:.git/config user.override=local | |
| local file:.git/config include.path=../include/relative.include | |
| local file:.git/../include/relative.include user.relative=include | |
| command command line: user.cmdline=true | |
| EOF | |
| git -c user.cmdline=true config ${mode_prefix}list --show-origin --show-scope >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success '--show-scope with --default' ' | |
| git config --show-scope --default foo some.key >actual && | |
| echo "command foo" >expect && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'override global and system config' ' | |
| test_when_finished rm -f \"\$HOME\"/.gitconfig && | |
| cat >"$HOME"/.gitconfig <<-EOF && | |
| [home] | |
| config = true | |
| EOF | |
| test_when_finished rm -rf \"\$HOME\"/.config/git && | |
| mkdir -p "$HOME"/.config/git && | |
| cat >"$HOME"/.config/git/config <<-EOF && | |
| [xdg] | |
| config = true | |
| EOF | |
| cat >.git/config <<-EOF && | |
| [local] | |
| config = true | |
| EOF | |
| cat >custom-global-config <<-EOF && | |
| [global] | |
| config = true | |
| EOF | |
| cat >custom-system-config <<-EOF && | |
| [system] | |
| config = true | |
| EOF | |
| cat >expect <<-EOF && | |
| global xdg.config=true | |
| global home.config=true | |
| local local.config=true | |
| EOF | |
| git config ${mode_prefix}list --show-scope >output && | |
| test_cmp expect output && | |
| cat >expect <<-EOF && | |
| system system.config=true | |
| global global.config=true | |
| local local.config=true | |
| EOF | |
| GIT_CONFIG_NOSYSTEM=false GIT_CONFIG_SYSTEM=custom-system-config GIT_CONFIG_GLOBAL=custom-global-config \ | |
| git config ${mode_prefix}list --show-scope >output && | |
| test_cmp expect output && | |
| cat >expect <<-EOF && | |
| local local.config=true | |
| EOF | |
| GIT_CONFIG_NOSYSTEM=false GIT_CONFIG_SYSTEM=/dev/null GIT_CONFIG_GLOBAL=/dev/null \ | |
| git config ${mode_prefix}list --show-scope >output && | |
| test_cmp expect output | |
| ' | |
| test_expect_success 'override global and system config with missing file' ' | |
| test_must_fail env GIT_CONFIG_GLOBAL=does-not-exist GIT_CONFIG_SYSTEM=/dev/null git config ${mode_prefix}list --global && | |
| test_must_fail env GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=does-not-exist git config ${mode_prefix}list --system && | |
| GIT_CONFIG_GLOBAL=does-not-exist GIT_CONFIG_SYSTEM=does-not-exist git version | |
| ' | |
| test_expect_success 'system override has no effect with GIT_CONFIG_NOSYSTEM' ' | |
| # `git config --system` has different semantics compared to other | |
| # commands as it ignores GIT_CONFIG_NOSYSTEM. We thus test whether the | |
| # variable has an effect via a different proxy. | |
| cat >alias-config <<-EOF && | |
| [alias] | |
| hello-world = !echo "hello world" | |
| EOF | |
| test_must_fail env GIT_CONFIG_NOSYSTEM=true GIT_CONFIG_SYSTEM=alias-config \ | |
| git hello-world && | |
| GIT_CONFIG_NOSYSTEM=false GIT_CONFIG_SYSTEM=alias-config \ | |
| git hello-world >actual && | |
| echo "hello world" >expect && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'write to overridden global and system config' ' | |
| cat >expect <<EOF && | |
| [config] | |
| key = value | |
| EOF | |
| GIT_CONFIG_GLOBAL=write-to-global git config --global config.key value && | |
| test_cmp expect write-to-global && | |
| GIT_CONFIG_SYSTEM=write-to-system git config --system config.key value && | |
| test_cmp expect write-to-system | |
| ' | |
| for opt in --local --worktree | |
| do | |
| test_expect_success "$opt requires a repo" ' | |
| # we expect 128 to ensure that we do not simply | |
| # fail to find anything and return code "1" | |
| test_expect_code 128 nongit git config $opt foo.bar | |
| ' | |
| done | |
| cat >.git/config <<-\EOF && | |
| [section] | |
| foo = True | |
| number = 10 | |
| big = 1M | |
| path = ~/dir | |
| red = red | |
| blue = Blue | |
| date = Fri Jun 4 15:46:55 2010 | |
| missing=:(optional)no-such-path | |
| exists=:(optional)expect | |
| EOF | |
| test_expect_success 'identical modern --type specifiers are allowed' ' | |
| test_cmp_config 1048576 --type=int --type=int section.big | |
| ' | |
| test_expect_success 'identical legacy --type specifiers are allowed' ' | |
| test_cmp_config 1048576 --int --int section.big | |
| ' | |
| test_expect_success 'identical mixed --type specifiers are allowed' ' | |
| test_cmp_config 1048576 --int --type=int section.big | |
| ' | |
| test_expect_success 'non-identical modern --type specifiers are not allowed' ' | |
| test_must_fail git config --type=int --type=bool section.big 2>error && | |
| test_grep "only one type at a time" error | |
| ' | |
| test_expect_success 'non-identical legacy --type specifiers are not allowed' ' | |
| test_must_fail git config --int --bool section.big 2>error && | |
| test_grep "only one type at a time" error | |
| ' | |
| test_expect_success 'non-identical mixed --type specifiers are not allowed' ' | |
| test_must_fail git config --type=int --bool section.big 2>error && | |
| test_grep "only one type at a time" error | |
| ' | |
| test_expect_success '--type allows valid type specifiers' ' | |
| test_cmp_config true --type=bool section.foo | |
| ' | |
| test_expect_success '--no-type unsets type specifiers' ' | |
| test_cmp_config 10 --type=bool --no-type section.number | |
| ' | |
| test_expect_success 'unset type specifiers may be reset to conflicting ones' ' | |
| test_cmp_config 1048576 --type=bool --no-type --type=int section.big | |
| ' | |
| test_expect_success 'list --type=int shows only canonicalizable int values' ' | |
| cat >expect <<-EOF && | |
| section.number=10 | |
| section.big=1048576 | |
| EOF | |
| git config ${mode_prefix}list --type=int >actual 2>err && | |
| test_cmp expect actual && | |
| test_must_be_empty err | |
| ' | |
| test_expect_success 'list --type=bool shows only canonicalizable bool values' ' | |
| cat >expect <<-EOF && | |
| section.foo=true | |
| section.number=true | |
| section.big=true | |
| EOF | |
| git config ${mode_prefix}list --type=bool >actual 2>err && | |
| test_cmp expect actual && | |
| test_must_be_empty err | |
| ' | |
| test_expect_success 'list --type=bool-or-int shows only canonicalizable values' ' | |
| cat >expect <<-EOF && | |
| section.foo=true | |
| section.number=10 | |
| section.big=1048576 | |
| EOF | |
| git config ${mode_prefix}list --type=bool-or-int >actual 2>err && | |
| test_cmp expect actual && | |
| test_must_be_empty err | |
| ' | |
| test_expect_success 'list --type=path shows only canonicalizable path values' ' | |
| cat >expect <<-EOF && | |
| section.foo=True | |
| section.number=10 | |
| section.big=1M | |
| section.path=$HOME/dir | |
| section.red=red | |
| section.blue=Blue | |
| section.date=Fri Jun 4 15:46:55 2010 | |
| section.exists=expect | |
| EOF | |
| git config ${mode_prefix}list --type=path >actual 2>err && | |
| test_cmp expect actual && | |
| test_must_be_empty err | |
| ' | |
| test_expect_success 'list --type=expiry-date shows only canonicalizable dates' ' | |
| git config ${mode_prefix}list --type=expiry-date >actual 2>err && | |
| # section.number and section.big parse as relative dates that could | |
| # have clock skew in their results. | |
| test_grep section.big actual && | |
| test_grep section.number actual && | |
| test_grep "section.date=$(git config --type=expiry-date section.$key)" actual && | |
| test_must_be_empty err | |
| ' | |
| test_expect_success 'list --type=color shows only canonicalizable color values' ' | |
| cat >expect <<-EOF && | |
| section.number=<> | |
| section.red=<RED> | |
| section.blue=<BLUE> | |
| EOF | |
| git config ${mode_prefix}list --type=color >actual.raw 2>err && | |
| test_decode_color <actual.raw >actual && | |
| test_cmp expect actual && | |
| test_must_be_empty err | |
| ' | |
| test_expect_success '--type rejects unknown specifiers' ' | |
| test_must_fail git config --type=nonsense section.foo 2>error && | |
| test_grep "unrecognized --type argument" error | |
| ' | |
| test_expect_success '--type=int requires at least one digit' ' | |
| test_must_fail git config --type int --default m some.key >out 2>error && | |
| test_grep "bad numeric config value" error && | |
| test_must_be_empty out | |
| ' | |
| test_expect_success '--replace-all does not invent newlines' ' | |
| q_to_tab >.git/config <<-\EOF && | |
| [abc]key | |
| QkeepSection | |
| [xyz] | |
| Qkey = 1 | |
| [abc] | |
| Qkey = a | |
| EOF | |
| q_to_tab >expect <<-\EOF && | |
| [abc] | |
| QkeepSection | |
| [xyz] | |
| Qkey = 1 | |
| [abc] | |
| Qkey = b | |
| EOF | |
| git config ${mode_replace_all} abc.key b && | |
| test_cmp expect .git/config | |
| ' | |
| test_expect_success 'set all config with value-pattern' ' | |
| test_when_finished rm -f config initial && | |
| git config --file=initial abc.key one && | |
| # no match => add new entry | |
| cp initial config && | |
| git config --file=config abc.key two a+ && | |
| git config ${mode_prefix}list --file=config >actual && | |
| cat >expect <<-\EOF && | |
| abc.key=one | |
| abc.key=two | |
| EOF | |
| test_cmp expect actual && | |
| # multiple matches => failure | |
| test_must_fail git config --file=config abc.key three o+ 2>err && | |
| test_grep "has multiple values" err && | |
| # multiple values, no match => add | |
| git config --file=config abc.key three a+ && | |
| git config ${mode_prefix}list --file=config >actual && | |
| cat >expect <<-\EOF && | |
| abc.key=one | |
| abc.key=two | |
| abc.key=three | |
| EOF | |
| test_cmp expect actual && | |
| # single match => replace | |
| git config --file=config abc.key four h+ && | |
| git config ${mode_prefix}list --file=config >actual && | |
| cat >expect <<-\EOF && | |
| abc.key=one | |
| abc.key=two | |
| abc.key=four | |
| EOF | |
| test_cmp expect actual | |
| ' | |
| test_expect_success '--replace-all and value-pattern' ' | |
| test_when_finished rm -f config && | |
| git config --file=config --add abc.key one && | |
| git config --file=config --add abc.key two && | |
| git config --file=config --add abc.key three && | |
| git config --file=config --replace-all abc.key four "o+" && | |
| git config ${mode_prefix}list --file=config >actual && | |
| cat >expect <<-\EOF && | |
| abc.key=four | |
| abc.key=three | |
| EOF | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'refuse --fixed-value for incompatible actions' ' | |
| test_when_finished rm -f config && | |
| git config --file=config dev.null bogus && | |
| # These modes do not allow --fixed-value at all | |
| test_must_fail git config --file=config --fixed-value --add dev.null bogus && | |
| test_must_fail git config --file=config --fixed-value --get-urlmatch dev.null bogus && | |
| test_must_fail git config --file=config --fixed-value --get-urlmatch dev.null bogus && | |
| test_must_fail git config ${mode_prefix}rename-section --file=config --fixed-value dev null && | |
| test_must_fail git config ${mode_prefix}remove-section --file=config --fixed-value dev && | |
| test_must_fail git config ${mode_prefix}list --file=config --fixed-value && | |
| test_must_fail git config --file=config --fixed-value --get-color dev.null && | |
| test_must_fail git config --file=config --fixed-value --get-colorbool dev.null && | |
| # These modes complain when --fixed-value has no value-pattern | |
| test_must_fail git config ${mode_set} --file=config --fixed-value dev.null bogus && | |
| test_must_fail git config ${mode_replace_all} --file=config --fixed-value dev.null bogus && | |
| test_must_fail git config ${mode_prefix}get --file=config --fixed-value dev.null && | |
| test_must_fail git config ${mode_get_all} --file=config --fixed-value dev.null && | |
| test_must_fail git config ${mode_get_regexp} --file=config --fixed-value "dev.*" && | |
| test_must_fail git config ${mode_unset} --file=config --fixed-value dev.null && | |
| test_must_fail git config ${mode_unset_all} --file=config --fixed-value dev.null | |
| ' | |
| test_expect_success '--fixed-value uses exact string matching' ' | |
| test_when_finished rm -f config initial && | |
| META="a+b*c?d[e]f.g" && | |
| git config --file=initial fixed.test "$META" && | |
| cp initial config && | |
| git config --file=config fixed.test bogus "$META" && | |
| git config ${mode_prefix}list --file=config >actual && | |
| cat >expect <<-EOF && | |
| fixed.test=$META | |
| fixed.test=bogus | |
| EOF | |
| test_cmp expect actual && | |
| cp initial config && | |
| git config --file=config --fixed-value fixed.test bogus "$META" && | |
| git config ${mode_prefix}list --file=config >actual && | |
| cat >expect <<-\EOF && | |
| fixed.test=bogus | |
| EOF | |
| test_cmp expect actual && | |
| cp initial config && | |
| test_must_fail git config --file=config --unset fixed.test "$META" && | |
| git config --file=config --fixed-value --unset fixed.test "$META" && | |
| test_must_fail git config ${mode_get} --file=config fixed.test && | |
| cp initial config && | |
| test_must_fail git config unset --file=config --value="$META" fixed.test && | |
| git config unset --file=config --fixed-value --value="$META" fixed.test && | |
| test_must_fail git config ${mode_get} --file=config fixed.test && | |
| cp initial config && | |
| test_must_fail git config --file=config --unset-all fixed.test "$META" && | |
| git config --file=config --fixed-value --unset-all fixed.test "$META" && | |
| test_must_fail git config ${mode_get} --file=config fixed.test && | |
| cp initial config && | |
| git config --file=config fixed.test bogus "$META" && | |
| git config ${mode_prefix}list --file=config >actual && | |
| cat >expect <<-EOF && | |
| fixed.test=$META | |
| fixed.test=bogus | |
| EOF | |
| test_cmp expect actual && | |
| git config --file=config --fixed-value --replace-all fixed.test bogus "$META" && | |
| git config ${mode_prefix}list --file=config >actual && | |
| cat >expect <<-EOF && | |
| fixed.test=bogus | |
| fixed.test=bogus | |
| EOF | |
| test_cmp expect actual | |
| ' | |
| test_expect_success '--get and --get-all with --fixed-value' ' | |
| test_when_finished rm -f config && | |
| META="a+b*c?d[e]f.g" && | |
| git config --file=config fixed.test bogus && | |
| git config --file=config --add fixed.test "$META" && | |
| git config --file=config --get fixed.test bogus && | |
| git config get --file=config --value=bogus fixed.test && | |
| test_must_fail git config --file=config --get fixed.test "$META" && | |
| test_must_fail git config get --file=config --value="$META" fixed.test && | |
| git config --file=config --get --fixed-value fixed.test "$META" && | |
| git config get --file=config --fixed-value --value="$META" fixed.test && | |
| test_must_fail git config --file=config --get --fixed-value fixed.test non-existent && | |
| git config --file=config --get-all fixed.test bogus && | |
| git config get --all --file=config --value=bogus fixed.test && | |
| test_must_fail git config --file=config --get-all fixed.test "$META" && | |
| test_must_fail git config get --all --file=config --value="$META" fixed.test && | |
| git config --file=config --get-all --fixed-value fixed.test "$META" && | |
| git config get --all --file=config --value="$META" --fixed-value fixed.test && | |
| test_must_fail git config --file=config --get-all --fixed-value fixed.test non-existent && | |
| git config --file=config --get-regexp fixed+ bogus && | |
| git config get --regexp --file=config --value=bogus fixed+ && | |
| test_must_fail git config --file=config --get-regexp fixed+ "$META" && | |
| test_must_fail git config get --regexp --file=config --value="$META" fixed+ && | |
| git config --file=config --get-regexp --fixed-value fixed+ "$META" && | |
| git config get --regexp --file=config --fixed-value --value="$META" fixed+ && | |
| test_must_fail git config --file=config --get-regexp --fixed-value fixed+ non-existent | |
| ' | |
| test_expect_success '--fixed-value with value-less configuration' ' | |
| test_when_finished rm -f config && | |
| cat >config <<-\EOF && | |
| [section] | |
| key | |
| EOF | |
| git config --file=config --fixed-value section.key value pattern | |
| ' | |
| test_expect_success 'includeIf.hasconfig:remote.*.url' ' | |
| git init hasremoteurlTest && | |
| test_when_finished "rm -rf hasremoteurlTest" && | |
| cat >include-this <<-\EOF && | |
| [user] | |
| this = this-is-included | |
| EOF | |
| cat >dont-include-that <<-\EOF && | |
| [user] | |
| that = that-is-not-included | |
| EOF | |
| cat >>hasremoteurlTest/.git/config <<-EOF && | |
| [includeIf "hasconfig:remote.*.url:foourl"] | |
| path = "$(pwd)/include-this" | |
| [includeIf "hasconfig:remote.*.url:barurl"] | |
| path = "$(pwd)/dont-include-that" | |
| [remote "foo"] | |
| url = foourl | |
| EOF | |
| echo this-is-included >expect-this && | |
| git -C hasremoteurlTest config --get user.this >actual-this && | |
| test_cmp expect-this actual-this && | |
| test_must_fail git -C hasremoteurlTest config --get user.that | |
| ' | |
| test_expect_success 'includeIf.hasconfig:remote.*.url respects last-config-wins' ' | |
| git init hasremoteurlTest && | |
| test_when_finished "rm -rf hasremoteurlTest" && | |
| cat >include-two-three <<-\EOF && | |
| [user] | |
| two = included-config | |
| three = included-config | |
| EOF | |
| cat >>hasremoteurlTest/.git/config <<-EOF && | |
| [remote "foo"] | |
| url = foourl | |
| [user] | |
| one = main-config | |
| two = main-config | |
| [includeIf "hasconfig:remote.*.url:foourl"] | |
| path = "$(pwd)/include-two-three" | |
| [user] | |
| three = main-config | |
| EOF | |
| echo main-config >expect-main-config && | |
| echo included-config >expect-included-config && | |
| git -C hasremoteurlTest config --get user.one >actual && | |
| test_cmp expect-main-config actual && | |
| git -C hasremoteurlTest config --get user.two >actual && | |
| test_cmp expect-included-config actual && | |
| git -C hasremoteurlTest config --get user.three >actual && | |
| test_cmp expect-main-config actual | |
| ' | |
| test_expect_success 'includeIf.hasconfig:remote.*.url globs' ' | |
| git init hasremoteurlTest && | |
| test_when_finished "rm -rf hasremoteurlTest" && | |
| printf "[user]\ndss = yes\n" >double-star-start && | |
| printf "[user]\ndse = yes\n" >double-star-end && | |
| printf "[user]\ndsm = yes\n" >double-star-middle && | |
| printf "[user]\nssm = yes\n" >single-star-middle && | |
| printf "[user]\nno = no\n" >no && | |
| cat >>hasremoteurlTest/.git/config <<-EOF && | |
| [remote "foo"] | |
| url = https://foo/bar/baz | |
| [includeIf "hasconfig:remote.*.url:**/baz"] | |
| path = "$(pwd)/double-star-start" | |
| [includeIf "hasconfig:remote.*.url:**/nomatch"] | |
| path = "$(pwd)/no" | |
| [includeIf "hasconfig:remote.*.url:https:/**"] | |
| path = "$(pwd)/double-star-end" | |
| [includeIf "hasconfig:remote.*.url:nomatch:/**"] | |
| path = "$(pwd)/no" | |
| [includeIf "hasconfig:remote.*.url:https:/**/baz"] | |
| path = "$(pwd)/double-star-middle" | |
| [includeIf "hasconfig:remote.*.url:https:/**/nomatch"] | |
| path = "$(pwd)/no" | |
| [includeIf "hasconfig:remote.*.url:https://*/bar/baz"] | |
| path = "$(pwd)/single-star-middle" | |
| [includeIf "hasconfig:remote.*.url:https://*/baz"] | |
| path = "$(pwd)/no" | |
| EOF | |
| git -C hasremoteurlTest config --get user.dss && | |
| git -C hasremoteurlTest config --get user.dse && | |
| git -C hasremoteurlTest config --get user.dsm && | |
| git -C hasremoteurlTest config --get user.ssm && | |
| test_must_fail git -C hasremoteurlTest config --get user.no | |
| ' | |
| test_expect_success 'includeIf.hasconfig:remote.*.url forbids remote url in such included files' ' | |
| git init hasremoteurlTest && | |
| test_when_finished "rm -rf hasremoteurlTest" && | |
| cat >include-with-url <<-\EOF && | |
| [remote "bar"] | |
| url = barurl | |
| EOF | |
| cat >>hasremoteurlTest/.git/config <<-EOF && | |
| [includeIf "hasconfig:remote.*.url:foourl"] | |
| path = "$(pwd)/include-with-url" | |
| EOF | |
| # test with any Git command | |
| test_must_fail git -C hasremoteurlTest status 2>err && | |
| test_grep "fatal: remote URLs cannot be configured in file directly or indirectly included by includeIf.hasconfig:remote.*.url" err | |
| ' | |
| test_expect_success 'negated mode causes failure' ' | |
| test_must_fail git config --no-get 2>err && | |
| test_grep "unknown option \`no-get${SQ}" err | |
| ' | |
| test_expect_success 'specifying multiple modes causes failure' ' | |
| cat >expect <<-EOF && | |
| error: options ${SQ}--get-all${SQ} and ${SQ}--get${SQ} cannot be used together | |
| EOF | |
| test_must_fail git config --get --get-all 2>err && | |
| test_cmp expect err | |
| ' | |
| test_expect_success 'writing to stdin is rejected' ' | |
| echo "fatal: writing to stdin is not supported" >expect && | |
| test_must_fail git config ${mode_set} --file - foo.bar baz 2>err && | |
| test_cmp expect err | |
| ' | |
| done | |
| test_expect_success 'writing value with trailing CR not stripped on read' ' | |
| test_when_finished "rm -rf cr-test" && | |
| printf "bar\r\n" >expect && | |
| git init cr-test && | |
| git -C cr-test config set core.foo $(printf "bar\r") && | |
| git -C cr-test config get core.foo >actual && | |
| test_cmp expect actual | |
| ' | |
| test_expect_success 'writing config fails immediately with core.configLockTimeout=0' ' | |
| test_when_finished "rm -f .git/config.lock" && | |
| >.git/config.lock && | |
| test_must_fail git -c core.configLockTimeout=0 config foo.bar baz 2>err && | |
| test_grep "could not lock config file" err | |
| ' | |
| test_expect_success 'writing config retries until lock is released' ' | |
| test_when_finished "rm -f .git/config.lock" && | |
| >.git/config.lock && | |
| { | |
| ( sleep 1 && rm -f .git/config.lock ) & | |
| } && | |
| git -c core.configLockTimeout=5000 config retried.key value && | |
| test "$(git config retried.key)" = value | |
| ' | |
| test_done |