1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-04-28 00:55:11 +02:00

Merge branch 'ds/config-internal-whitespace-fix' into next

"git config" corrupted literal HT characters written in the
configuration file as part of a value, which has been corrected.

* ds/config-internal-whitespace-fix:
  config.txt: describe handling of whitespace further
  t1300: add more tests for whitespace and inline comments
  config: really keep value-internal whitespace verbatim
  config: minor addition of whitespace
This commit is contained in:
Junio C Hamano 2024-03-25 16:26:50 -07:00
commit f3393cabe5
3 changed files with 135 additions and 20 deletions

View File

@ -22,9 +22,10 @@ multivalued.
Syntax
~~~~~~
The syntax is fairly flexible and permissive; whitespaces are mostly
ignored. The '#' and ';' characters begin comments to the end of line,
blank lines are ignored.
The syntax is fairly flexible and permissive. Whitespace characters,
which in this context are the space character (SP) and the horizontal
tabulation (HT), are mostly ignored. The '#' and ';' characters begin
comments to the end of line. Blank lines are ignored.
The file consists of sections and variables. A section begins with
the name of the section in square brackets and continues until the next
@ -63,16 +64,17 @@ the variable is the boolean "true").
The variable names are case-insensitive, allow only alphanumeric characters
and `-`, and must start with an alphabetic character.
A line that defines a value can be continued to the next line by
ending it with a `\`; the backslash and the end-of-line are
stripped. Leading whitespaces after 'name =', the remainder of the
line after the first comment character '#' or ';', and trailing
whitespaces of the line are discarded unless they are enclosed in
double quotes. Internal whitespaces within the value are retained
verbatim.
Whitespace characters surrounding `name`, `=` and `value` are discarded.
Internal whitespace characters within 'value' are retained verbatim.
Comments starting with either `#` or `;` and extending to the end of line
are discarded. A line that defines a value can be continued to the next
line by ending it with a backslash (`\`); the backslash and the end-of-line
characters are discarded.
Inside double quotes, double quote `"` and backslash `\` characters
must be escaped: use `\"` for `"` and `\\` for `\`.
If `value` needs to contain leading or trailing whitespace characters,
it must be enclosed in double quotation marks (`"`). Inside double quotation
marks, double quote (`"`) and backslash (`\`) characters must be escaped:
use `\"` for `"` and `\\` for `\`.
The following escape sequences (beside `\"` and `\\`) are recognized:
`\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB)

View File

@ -817,7 +817,8 @@ static int get_next_char(struct config_source *cs)
static char *parse_value(struct config_source *cs)
{
int quote = 0, comment = 0, space = 0;
int quote = 0, comment = 0;
size_t trim_len = 0;
strbuf_reset(&cs->value);
for (;;) {
@ -827,13 +828,17 @@ static char *parse_value(struct config_source *cs)
cs->linenr--;
return NULL;
}
if (trim_len)
strbuf_setlen(&cs->value, trim_len);
return cs->value.buf;
}
if (comment)
continue;
if (isspace(c) && !quote) {
if (!trim_len)
trim_len = cs->value.len;
if (cs->value.len)
space++;
strbuf_addch(&cs->value, c);
continue;
}
if (!quote) {
@ -842,8 +847,8 @@ static char *parse_value(struct config_source *cs)
continue;
}
}
for (; space; space--)
strbuf_addch(&cs->value, ' ');
if (trim_len)
trim_len = 0;
if (c == '\\') {
c = get_next_char(cs);
switch (c) {
@ -869,7 +874,7 @@ static char *parse_value(struct config_source *cs)
continue;
}
if (c == '"') {
quote = 1-quote;
quote = 1 - quote;
continue;
}
strbuf_addch(&cs->value, c);

View File

@ -11,6 +11,98 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
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
'
@ -1066,9 +1158,25 @@ test_expect_success '--null --get-regexp' '
test_cmp expect result
'
test_expect_success 'inner whitespace kept verbatim' '
git config section.val "foo bar" &&
test_cmp_config "foo bar" section.val
test_expect_success 'inner whitespace kept verbatim, spaces only' '
echo "foo bar" >expect &&
git config section.val "foo bar" &&
git config --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 section.val "$(cat expect)" &&
git config --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 section.val "$(cat expect)" &&
git config --get section.val >actual &&
test_cmp expect actual
'
test_expect_success SYMLINKS 'symlinked configuration' '