Skip to content

Commit 2a2c18f

Browse files
committed
Merge branch 'sb/config-write-fix'
Recent update to "git config" broke updating variable in a subsection, which has been corrected. * sb/config-write-fix: git-config: document accidental multi-line setting in deprecated syntax config: fix case sensitive subsection names on writing t1300: document current behavior of setting options
2 parents 87aa159 + bff7df7 commit 2a2c18f

File tree

3 files changed

+119
-1
lines changed

3 files changed

+119
-1
lines changed

Documentation/git-config.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,27 @@ http.sslverify false
453453

454454
include::config.txt[]
455455

456+
BUGS
457+
----
458+
When using the deprecated `[section.subsection]` syntax, changing a value
459+
will result in adding a multi-line key instead of a change, if the subsection
460+
is given with at least one uppercase character. For example when the config
461+
looks like
462+
463+
--------
464+
[section.subsection]
465+
key = value1
466+
--------
467+
468+
and running `git config section.Subsection.key value2` will result in
469+
470+
--------
471+
[section.subsection]
472+
key = value1
473+
key = value2
474+
--------
475+
476+
456477
GIT
457478
---
458479
Part of the linkgit:git[1] suite

config.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct config_source {
3838
int eof;
3939
struct strbuf value;
4040
struct strbuf var;
41+
unsigned subsection_case_sensitive : 1;
4142

4243
int (*do_fgetc)(struct config_source *c);
4344
int (*do_ungetc)(int c, struct config_source *conf);
@@ -606,6 +607,7 @@ static int get_value(config_fn_t fn, void *data, struct strbuf *name)
606607

607608
static int get_extended_base_var(struct strbuf *name, int c)
608609
{
610+
cf->subsection_case_sensitive = 0;
609611
do {
610612
if (c == '\n')
611613
goto error_incomplete_line;
@@ -642,6 +644,7 @@ static int get_extended_base_var(struct strbuf *name, int c)
642644

643645
static int get_base_var(struct strbuf *name)
644646
{
647+
cf->subsection_case_sensitive = 1;
645648
for (;;) {
646649
int c = get_next_char();
647650
if (cf->eof)
@@ -2370,14 +2373,21 @@ static int store_aux_event(enum config_event_t type,
23702373
store->parsed[store->parsed_nr].type = type;
23712374

23722375
if (type == CONFIG_EVENT_SECTION) {
2376+
int (*cmpfn)(const char *, const char *, size_t);
2377+
23732378
if (cf->var.len < 2 || cf->var.buf[cf->var.len - 1] != '.')
23742379
return error(_("invalid section name '%s'"), cf->var.buf);
23752380

2381+
if (cf->subsection_case_sensitive)
2382+
cmpfn = strncasecmp;
2383+
else
2384+
cmpfn = strncmp;
2385+
23762386
/* Is this the section we were looking for? */
23772387
store->is_keys_section =
23782388
store->parsed[store->parsed_nr].is_keys_section =
23792389
cf->var.len - 1 == store->baselen &&
2380-
!strncasecmp(cf->var.buf, store->key, store->baselen);
2390+
!cmpfn(cf->var.buf, store->key, store->baselen);
23812391
if (store->is_keys_section) {
23822392
store->section_seen = 1;
23832393
ALLOC_GROW(store->seen, store->seen_nr + 1,

t/t1300-config.sh

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,93 @@ test_expect_success 'last one wins: three level vars' '
12181218
test_cmp expect actual
12191219
'
12201220

1221+
test_expect_success 'old-fashioned settings are case insensitive' '
1222+
test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" &&
1223+
1224+
cat >testConfig_actual <<-EOF &&
1225+
[V.A]
1226+
r = value1
1227+
EOF
1228+
q_to_tab >testConfig_expect <<-EOF &&
1229+
[V.A]
1230+
Qr = value2
1231+
EOF
1232+
git config -f testConfig_actual "v.a.r" value2 &&
1233+
test_cmp testConfig_expect testConfig_actual &&
1234+
1235+
cat >testConfig_actual <<-EOF &&
1236+
[V.A]
1237+
r = value1
1238+
EOF
1239+
q_to_tab >testConfig_expect <<-EOF &&
1240+
[V.A]
1241+
QR = value2
1242+
EOF
1243+
git config -f testConfig_actual "V.a.R" value2 &&
1244+
test_cmp testConfig_expect testConfig_actual &&
1245+
1246+
cat >testConfig_actual <<-EOF &&
1247+
[V.A]
1248+
r = value1
1249+
EOF
1250+
q_to_tab >testConfig_expect <<-EOF &&
1251+
[V.A]
1252+
r = value1
1253+
Qr = value2
1254+
EOF
1255+
git config -f testConfig_actual "V.A.r" value2 &&
1256+
test_cmp testConfig_expect testConfig_actual &&
1257+
1258+
cat >testConfig_actual <<-EOF &&
1259+
[V.A]
1260+
r = value1
1261+
EOF
1262+
q_to_tab >testConfig_expect <<-EOF &&
1263+
[V.A]
1264+
r = value1
1265+
Qr = value2
1266+
EOF
1267+
git config -f testConfig_actual "v.A.r" value2 &&
1268+
test_cmp testConfig_expect testConfig_actual
1269+
'
1270+
1271+
test_expect_success 'setting different case sensitive subsections ' '
1272+
test_when_finished "rm -f testConfig testConfig_expect testConfig_actual" &&
1273+
1274+
cat >testConfig_actual <<-EOF &&
1275+
[V "A"]
1276+
R = v1
1277+
[K "E"]
1278+
Y = v1
1279+
[a "b"]
1280+
c = v1
1281+
[d "e"]
1282+
f = v1
1283+
EOF
1284+
q_to_tab >testConfig_expect <<-EOF &&
1285+
[V "A"]
1286+
Qr = v2
1287+
[K "E"]
1288+
Qy = v2
1289+
[a "b"]
1290+
Qc = v2
1291+
[d "e"]
1292+
f = v1
1293+
[d "E"]
1294+
Qf = v2
1295+
EOF
1296+
# exact match
1297+
git config -f testConfig_actual a.b.c v2 &&
1298+
# match section and subsection, key is cased differently.
1299+
git config -f testConfig_actual K.E.y v2 &&
1300+
# section and key are matched case insensitive, but subsection needs
1301+
# to match; When writing out new values only the key is adjusted
1302+
git config -f testConfig_actual v.A.r v2 &&
1303+
# subsection is not matched:
1304+
git config -f testConfig_actual d.E.f v2 &&
1305+
test_cmp testConfig_expect testConfig_actual
1306+
'
1307+
12211308
for VAR in a .a a. a.0b a."b c". a."b c".0d
12221309
do
12231310
test_expect_success "git -c $VAR=VAL rejects invalid '$VAR'" '

0 commit comments

Comments
 (0)