Skip to content

Commit 521df68

Browse files
committed
Merge branch 'ds/config-internal-whitespace-fix'
"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
2 parents a031815 + e6895c3 commit 521df68

File tree

3 files changed

+136
-21
lines changed

3 files changed

+136
-21
lines changed

Documentation/config.txt

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ multivalued.
2222
Syntax
2323
~~~~~~
2424

25-
The syntax is fairly flexible and permissive; whitespaces are mostly
26-
ignored. The '#' and ';' characters begin comments to the end of line,
27-
blank lines are ignored.
25+
The syntax is fairly flexible and permissive. Whitespace characters,
26+
which in this context are the space character (SP) and the horizontal
27+
tabulation (HT), are mostly ignored. The '#' and ';' characters begin
28+
comments to the end of line. Blank lines are ignored.
2829

2930
The file consists of sections and variables. A section begins with
3031
the name of the section in square brackets and continues until the next
@@ -63,16 +64,17 @@ the variable is the boolean "true").
6364
The variable names are case-insensitive, allow only alphanumeric characters
6465
and `-`, and must start with an alphabetic character.
6566

66-
A line that defines a value can be continued to the next line by
67-
ending it with a `\`; the backslash and the end-of-line are
68-
stripped. Leading whitespaces after 'name =', the remainder of the
69-
line after the first comment character '#' or ';', and trailing
70-
whitespaces of the line are discarded unless they are enclosed in
71-
double quotes. Internal whitespaces within the value are retained
72-
verbatim.
73-
74-
Inside double quotes, double quote `"` and backslash `\` characters
75-
must be escaped: use `\"` for `"` and `\\` for `\`.
67+
Whitespace characters surrounding `name`, `=` and `value` are discarded.
68+
Internal whitespace characters within 'value' are retained verbatim.
69+
Comments starting with either `#` or `;` and extending to the end of line
70+
are discarded. A line that defines a value can be continued to the next
71+
line by ending it with a backslash (`\`); the backslash and the end-of-line
72+
characters are discarded.
73+
74+
If `value` needs to contain leading or trailing whitespace characters,
75+
it must be enclosed in double quotation marks (`"`). Inside double quotation
76+
marks, double quote (`"`) and backslash (`\`) characters must be escaped:
77+
use `\"` for `"` and `\\` for `\`.
7678

7779
The following escape sequences (beside `\"` and `\\`) are recognized:
7880
`\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB)

config.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,8 @@ static int get_next_char(struct config_source *cs)
817817

818818
static char *parse_value(struct config_source *cs)
819819
{
820-
int quote = 0, comment = 0, space = 0;
820+
int quote = 0, comment = 0;
821+
size_t trim_len = 0;
821822

822823
strbuf_reset(&cs->value);
823824
for (;;) {
@@ -827,13 +828,17 @@ static char *parse_value(struct config_source *cs)
827828
cs->linenr--;
828829
return NULL;
829830
}
831+
if (trim_len)
832+
strbuf_setlen(&cs->value, trim_len);
830833
return cs->value.buf;
831834
}
832835
if (comment)
833836
continue;
834837
if (isspace(c) && !quote) {
838+
if (!trim_len)
839+
trim_len = cs->value.len;
835840
if (cs->value.len)
836-
space++;
841+
strbuf_addch(&cs->value, c);
837842
continue;
838843
}
839844
if (!quote) {
@@ -842,8 +847,8 @@ static char *parse_value(struct config_source *cs)
842847
continue;
843848
}
844849
}
845-
for (; space; space--)
846-
strbuf_addch(&cs->value, ' ');
850+
if (trim_len)
851+
trim_len = 0;
847852
if (c == '\\') {
848853
c = get_next_char(cs);
849854
switch (c) {
@@ -869,7 +874,7 @@ static char *parse_value(struct config_source *cs)
869874
continue;
870875
}
871876
if (c == '"') {
872-
quote = 1-quote;
877+
quote = 1 - quote;
873878
continue;
874879
}
875880
strbuf_addch(&cs->value, c);

t/t1300-config.sh

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,98 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
1111
TEST_PASSES_SANITIZE_LEAK=true
1212
. ./test-lib.sh
1313

14+
test_expect_success 'setup whitespace config' '
15+
sed -e "s/^|//" \
16+
-e "s/[$]$//" \
17+
-e "s/X/ /g" >.git/config <<-\EOF
18+
[section]
19+
| solid = rock
20+
| sparse = big XX blue
21+
| sparseAndTail = big XX blue $
22+
| sparseAndTailQuoted = "big XX blue "
23+
| sparseAndBiggerTail = big XX blue X X
24+
| sparseAndBiggerTailQuoted = "big XX blue X X"
25+
| sparseAndBiggerTailQuotedPlus = "big XX blue X X"X $
26+
| headAndTail = Xbig blue $
27+
| headAndTailQuoted = "Xbig blue "
28+
| headAndTailQuotedPlus = "Xbig blue " $
29+
| annotated = big blueX# to be discarded
30+
| annotatedQuoted = "big blue"X# to be discarded
31+
EOF
32+
'
33+
34+
test_expect_success 'no internal whitespace' '
35+
echo "rock" >expect &&
36+
git config --get section.solid >actual &&
37+
test_cmp expect actual
38+
'
39+
40+
test_expect_success 'internal whitespace' '
41+
echo "big QQ blue" | q_to_tab >expect &&
42+
git config --get section.sparse >actual &&
43+
test_cmp expect actual
44+
'
45+
46+
test_expect_success 'internal and trailing whitespace' '
47+
echo "big QQ blue" | q_to_tab >expect &&
48+
git config --get section.sparseAndTail >actual &&
49+
test_cmp expect actual
50+
'
51+
52+
test_expect_success 'internal and trailing whitespace, all quoted' '
53+
echo "big QQ blue " | q_to_tab >expect &&
54+
git config --get section.sparseAndTailQuoted >actual &&
55+
test_cmp expect actual
56+
'
57+
58+
test_expect_success 'internal and more trailing whitespace' '
59+
echo "big QQ blue" | q_to_tab >expect &&
60+
git config --get section.sparseAndBiggerTail >actual &&
61+
test_cmp expect actual
62+
'
63+
64+
test_expect_success 'internal and more trailing whitespace, all quoted' '
65+
echo "big QQ blue Q Q" | q_to_tab >expect &&
66+
git config --get section.sparseAndBiggerTailQuoted >actual &&
67+
test_cmp expect actual
68+
'
69+
70+
test_expect_success 'internal and more trailing whitespace, not all quoted' '
71+
echo "big QQ blue Q Q" | q_to_tab >expect &&
72+
git config --get section.sparseAndBiggerTailQuotedPlus >actual &&
73+
test_cmp expect actual
74+
'
75+
76+
test_expect_success 'leading and trailing whitespace' '
77+
echo "big blue" >expect &&
78+
git config --get section.headAndTail >actual &&
79+
test_cmp expect actual
80+
'
81+
82+
test_expect_success 'leading and trailing whitespace, all quoted' '
83+
echo "Qbig blue " | q_to_tab >expect &&
84+
git config --get section.headAndTailQuoted >actual &&
85+
test_cmp expect actual
86+
'
87+
88+
test_expect_success 'leading and trailing whitespace, not all quoted' '
89+
echo "Qbig blue " | q_to_tab >expect &&
90+
git config --get section.headAndTailQuotedPlus >actual &&
91+
test_cmp expect actual
92+
'
93+
94+
test_expect_success 'inline comment' '
95+
echo "big blue" >expect &&
96+
git config --get section.annotated >actual &&
97+
test_cmp expect actual
98+
'
99+
100+
test_expect_success 'inline comment, quoted' '
101+
echo "big blue" >expect &&
102+
git config --get section.annotatedQuoted >actual &&
103+
test_cmp expect actual
104+
'
105+
14106
test_expect_success 'clear default config' '
15107
rm -f .git/config
16108
'
@@ -1066,9 +1158,25 @@ test_expect_success '--null --get-regexp' '
10661158
test_cmp expect result
10671159
'
10681160

1069-
test_expect_success 'inner whitespace kept verbatim' '
1070-
git config section.val "foo bar" &&
1071-
test_cmp_config "foo bar" section.val
1161+
test_expect_success 'inner whitespace kept verbatim, spaces only' '
1162+
echo "foo bar" >expect &&
1163+
git config section.val "foo bar" &&
1164+
git config --get section.val >actual &&
1165+
test_cmp expect actual
1166+
'
1167+
1168+
test_expect_success 'inner whitespace kept verbatim, horizontal tabs only' '
1169+
echo "fooQQbar" | q_to_tab >expect &&
1170+
git config section.val "$(cat expect)" &&
1171+
git config --get section.val >actual &&
1172+
test_cmp expect actual
1173+
'
1174+
1175+
test_expect_success 'inner whitespace kept verbatim, horizontal tabs and spaces' '
1176+
echo "foo Q bar" | q_to_tab >expect &&
1177+
git config section.val "$(cat expect)" &&
1178+
git config --get section.val >actual &&
1179+
test_cmp expect actual
10721180
'
10731181

10741182
test_expect_success SYMLINKS 'symlinked configuration' '

0 commit comments

Comments
 (0)