Repository navigation
0.23.0-alpha
Pre-releaseAdded
--color auto|always|never(also--color=<mode>), for ANSI colour in every diff the tool
prints:--diff,--diff-layers, andset's automatic diff after a write. Accepted in every
mode.GitDiff.Renderalways passed--color=alwaysbefore this, so a redirect or pipe
(--diff > change.diff) captured raw escape codes. Seedocs/USAGE.md.
Changed
- JSON/YAML keys now match case-sensitively across layers, and a patch key that matches an
existing key only by case is an error. Repo owner's decision, following the tree merge below
(docs/TREE_MERGE_DESIGN.md's "Key matching is case-sensitive"). Before, a patch'sapiUrl
silently overrode the base'sApiUrl. That was wrong for case-sensitive consumers (a Python or
Node app sees two different keys), and plain case-sensitivity would instead deploy a file with
both keys, which .NET's configuration loader refuses to load. The merge now stops with an error
naming the patch file, the key path and the existing spelling.setchecks its--match key=
path the same way before writing (Try: --match key=Logging:LogLevel:Default), and now merges
the new overlay content before writing it, so a write the merge would reject leaves nothing on
disk. An existing overlay whose key casing differs from its base now fails to resolve — fix
the spelling the error names. - JSON and YAML now merge each patch into the base document's own tree, keeping the source's
key order, key spelling, and every value exactly as written (docs/TREE_MERGE_DESIGN.md).
Both engines used to flatten the base and patches throughMicrosoft.Extensions.Configuration
and rebuild a document from string keys. That sorted keys alphabetically, re-quoted YAML, and
corrupted values:"007"became7,"1.10"became1.1,"true"becametrue, a 20-digit
integer lost precision,nullbecame"",{}/[]were dropped, a patch's key spelling
replaced the base's, and a patch scalar landing on a base object was silently dropped.--diff
hid all of it, since it renders the unpatched side through the same merge. Kept on purpose:
IConfiguration's merge rules (key-by-key, arrays by index, the{"1": ...}index-keyed idiom)
and$elemMatchresolution; key matching became case-sensitive (entry above). Also changed: a later
layer now replaces a value of a different kind outright (the old merge always kept the object);
keys differing only by case within one file are allowed (YAML used to throw); an index-keyed
patch that would leave a gap in an array is an error; a multi-document YAML file is refused;
YAML output reuses the base file's indentation and sequence style. Comments are still not carried
into the output. Deployed JSON/YAML files can change wherever they relied on the old
reordering or type-guessing — compare before rolling out.Microsoft.Extensions.Configuration,
Microsoft.Extensions.Configuration.JsonandNetEscapades.Configuration.Yamlare no longer
dependencies. New golden expected-output fixtures (Fixtures/*/Expected/) pin the full output. - Diff output is no longer coloured by default when stdout isn't a terminal. The default,
--color auto, colours only on a terminal with theNO_COLORenvironment variable unset. A CI
log that renders ANSI (GitHub Actions does, even though a job's stdout isn't a terminal) now
gets plain text unless the step passes--color always.GitDiff.Rendernow passes
--color=neverexplicitly when colour is off, so a user's owncolor.ui = alwaysgit config
can't force it back on.
Fixed
-
A JSON patch file containing
//or/* */comments no longer crashes the merge. Comments
and trailing commas were accepted in a base file but not in a patch (the$elemMatchpre-scan
parsed patches strictly). Fixed by the tree merge above, which reads every file the same way. -
--diff-layersspaces a layer's second and later hunks with a blank line, the same as
between two layers' sections. Before, a layer's second[<layer>]tag followed the previous
hunk's last line with no gap. Seedocs/DIFF_LAYERS_DESIGN.mddecision log #5. -
JSON output keeps non-ASCII and
< > & ' +as written, instead of\uXXXXescapes.
Found during the same read-through as the console fix below. System.Text.Json's default encoder
wrote a passworda+basa\u002Bband a Hebrew value as a run of\u05XXescapes. This
affected--outputdeploy files too, not just console output. It was always valid JSON, but
unreadable in a deployed file or a--diff. Every JSON write site now uses
JavaScriptEncoder.UnsafeRelaxedJsonEscaping:JsonLayerMerger(both the plain and$elemMatch
paths),JsonFieldAuthor(set),JsonElemMatchResolver's ambiguous-match error message, and
LayerManifestSerializer(configtransform.jsonfiles written byset/init, where a client
namedAcme & Coused to come out asAcme \u0026 Co). New values in theDotNetCore,
GenericJsonandElemMatchfixtures cover it. Seedocs/CONFIG_MANAGEMENT.md§5.3, including the
one quirk left over from System.Text.Json itself (emoji are always written as escaped surrogate pairs). -
Console output is always UTF-8, so redirected output no longer loses characters on
Windows. Found while running the tool againstconfig-transform-pilotfrom Git Bash: on a
console code page like 437 (the Windows default for cmd.exe and Git Bash), .NET encoded
stdout/stderr in that code page. The resolution report's↓came out as the invisible control
byte0x19, and a non-ASCII config value printed by--dry-run(e.g. Hebrew) became?, which
is real data loss for--dry-run > file.--outputfiles were never affected. The new
Utf8Console(ConfigTransform.Cli) writes redirected output as UTF-8 with no BOM. On a real
console it switches the code page to UTF-8 for the run and restores the original on exit. See
docs/CONFIG_MANAGEMENT.md§6. Regression testUtf8ConsoleTestsruns the real CLI as a child
process with redirected stdout; an in-processCliRunner.Runtest with aStringWritercan't
reach this code.