Skip to content

Commit 92bf292

Browse files
Document layered YAML stream merging
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 7f1d780 commit 92bf292

2 files changed

Lines changed: 58 additions & 0 deletions

File tree

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ The module exports:
3232
| `Export-Yaml` | Serialize values and atomically write one YAML file. |
3333
| `Format-Yaml` | Normalize YAML streams without projecting representation nodes to PowerShell values. |
3434
| `Import-Yaml` | Strictly decode and parse YAML files. |
35+
| `Merge-Yaml` | Merge complete YAML streams without losing representation graph details. |
3536
| `Test-Yaml` | Test YAML syntax, tags, duplicate keys, and configured resource limits. |
3637

3738
## Parse YAML
@@ -174,6 +175,47 @@ $normalized -ceq ($normalized | Format-Yaml -Indent 4)
174175
duplicate representation keys, undefined aliases, malformed tags, and resource
175176
limit violations terminate with the same classified YAML errors as parsing.
176177

178+
## Merge YAML streams
179+
180+
`Merge-Yaml` combines two or more complete YAML streams directly through their
181+
representation graphs. Every array element or pipeline record is one complete
182+
stream, and every stream must contain the same positive document count. Later
183+
streams have higher precedence, and documents merge pairwise by zero-based index.
184+
185+
```powershell
186+
$baseYaml = Get-Content -LiteralPath '.\base.yaml' -Raw
187+
$overlayYaml = Get-Content -LiteralPath '.\overlay.yaml' -Raw
188+
$mergedYaml = Merge-Yaml -InputObject @($baseYaml, $overlayYaml)
189+
```
190+
191+
Compatible mappings merge recursively by structural YAML key equality. Base key
192+
order remains stable, replacing a value retains its position, and new overlay
193+
keys append in overlay order. Complex and tagged keys are supported. Structural
194+
fingerprints select comparison candidates only; graph-aware equality makes the
195+
final key decision.
196+
197+
Compatible sequences use `-SequenceAction Replace`, `Append`, or `Unique`.
198+
Unequal scalars, collection kinds, and incompatible effective tags use
199+
`-ConflictAction Replace` or `Error`. A later YAML null uses `-NullAction
200+
Replace` or `Ignore`; ignoring retains an existing prior node, including at a
201+
document root.
202+
203+
```powershell
204+
$baseYaml, $environmentYaml, $secretYaml |
205+
Merge-Yaml -SequenceAction Unique -ConflictAction Error -Indent 4
206+
```
207+
208+
Tags, anchors, aliases, repeated nodes, cycles, mapping order, and selected
209+
representation nodes remain graph data. Inputs are immutable, and YAML 1.1 `<<`
210+
merge keys remain ordinary mapping entries rather than being expanded. Output is
211+
one deterministic string with LF line endings, explicit document starts, and no
212+
final newline.
213+
214+
The parser safety parameters and defaults match `Format-Yaml`. `-MaxNodes`
215+
limits each parsed stream and invocation-wide cloning, equality, merge work, and
216+
the resulting stream graph. Alias and expanded-tag budgets are also enforced on
217+
the result.
218+
177219
## Export YAML files
178220

179221
`Export-Yaml` aggregates pipeline records like `ConvertTo-Yaml`, serializes the
@@ -220,6 +262,8 @@ limit violations. Unexpected runtime failures are not suppressed.
220262
represent it.
221263
- YAML merge keys are not expanded; `<<` is ordinary mapping data under the
222264
YAML 1.2 core schema.
265+
- YAML stream merging compares effective tags and structural representation
266+
values without projecting through PowerShell objects.
223267
- Parsing defaults to depth 100, 100000 nodes, 1000 aliases, 1048576 decoded
224268
characters per scalar, 1024 characters per expanded tag, 65536 cumulative
225269
expanded tag characters, and 4096 digits per numeric scalar. The

examples/General.ps1

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,20 @@ $normalizedYaml = @'
4747
'@ | Format-Yaml -Indent 4
4848
$normalizedYaml
4949

50+
# Merge complete YAML streams without projecting their representation graphs.
51+
$baseYaml = @'
52+
service:
53+
image: example:v1
54+
ports: [80]
55+
'@
56+
$overlayYaml = @'
57+
service:
58+
image: example:v2
59+
ports: [443]
60+
'@
61+
$mergedYaml = Merge-Yaml -InputObject @($baseYaml, $overlayYaml)
62+
$mergedYaml
63+
5064
# Atomically export one file, then import it with strict decoding.
5165
$configPath = Join-Path $env:TEMP 'yaml-example.yaml'
5266
$config | Export-Yaml -Path $configPath -PassThru

0 commit comments

Comments
 (0)