Skip to content

Keep v1 behavior for struct fields read from keys and allowshadow slices - #437

Merged
unknwon merged 2 commits into
mainfrom
struct-mapping-v1-compat
Nov 11, 2026
Merged

unknwon merged 2 commits into
mainfrom
struct-mapping-v1-compat

Conversation

@unknwon

@unknwon unknwon commented Nov 11, 2026

Copy link
Copy Markdown
Member

Describe the pull request

An audit of 37 projects that import go-ini directly found two v2 struct-mapping changes that break real users. Neither is in the migration guide. This PR goes back to v1's results in both cases, but keeps v2's guarantees: strict mode still reports the problem, and no data is dropped.

1. MapTo with a struct field whose name matches only a key. A struct field maps to a section. When no section of that name exists but a key does, v2 returned unsupported type. v1 skipped the field. frp relies on that: its legacy proxy config has BandwidthLimit types.BandwidthQuantity \ini:"bandwidth_limit"`, which decorate()parses afterMapTo. Under v2, every legacy config with bandwidth_limit` failed to load.

The fix treats this like any other value that doesn't fit its field. MapTo leaves the field unchanged and keeps mapping the other fields. StrictMapTo returns an error. Slices of structs read from a key are still an error, as before.

2. ReflectFrom with an allowshadow slice of several elements, on a file without AllowShadows. v1 wrote only the first element, silently. v2 returned shadow key is not allowed, which makes nginx-ui's settings migration (ReflectFrom into ini.Empty()) exit fatally. v2 now writes the elements as one value joined by the delimiter. The decoder already splits allowshadow values at the delimiter, so this value reads back as every element, with or without AllowShadows. The existing check that no element contains the delimiter still applies. Files loaded with AllowShadows still get one line per element.

Both behaviours were deliberate in #425, so the PR updates TestMapTo_StructFieldsFromKeys and TestReflectFrom_AllowShadow instead of adding new tests. Both tests fail on main and pass with this change. The migration guide gets a line for the allowshadow change. The struct-field case needs no line, because it now matches v1.

Link to the issue: n/a

Checklist

  • I agree to follow the Code of Conduct by submitting this pull request.
  • I have read and acknowledge the Contributing guide.
  • I have added test cases to cover the new code.

AI usage

Written by Amp (an AI coding agent) at the maintainer's request, following a v1/v2 differential audit against downstream importers. Validation: go test ./..., go vet, 45 s of FuzzStructMapping, and side-by-side reproductions of the frp and nginx-ui cases against v1.67.x and this branch.

MapTo leaves a struct field unchanged when only a key of its name exists,
as v1 did, so programs that parse such a key themselves (frp's legacy
bandwidth_limit) keep working. StrictMapTo still reports it.

ReflectFrom writes an allowshadow slice of several elements as one value
joined by the delimiter when the file has no AllowShadows, instead of
failing. It reads back as all elements; v1 wrote only the first.
@unknwon
unknwon merged commit b9a4289 into main Nov 11, 2026
10 checks passed
@unknwon
unknwon deleted the struct-mapping-v1-compat branch November 11, 2026 23:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant