Skip to content

Commit df0367f

Browse files
committed
Fix duplicate document markers in CLI
1 parent 5bf57e5 commit df0367f

2 files changed

Lines changed: 63 additions & 28 deletions

File tree

cmd/go-yaml/testdata/multi-document.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,3 +577,16 @@
577577
style: Plain
578578
tag: '!!str'
579579
text: item2
580+
581+
- name: Multiple sequences with explicit markers (no duplicates)
582+
text: |
583+
- 1
584+
---
585+
- 2
586+
explicit-yaml: |
587+
---
588+
- 1
589+
...
590+
---
591+
- 2
592+
...

cmd/go-yaml/yaml.go

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ func processYAMLLoad(reader io.Reader, preserve, marshal, encode bool, opts []ya
3434
if err != nil {
3535
return fmt.Errorf("failed to create loader: %w", err)
3636
}
37+
38+
// For Dumper mode, create a single Dumper for all documents
39+
var dumper *yaml.Dumper
40+
if !marshal && !encode {
41+
dumper, err = yaml.NewDumper(os.Stdout, opts...)
42+
if err != nil {
43+
return fmt.Errorf("failed to create dumper: %w", err)
44+
}
45+
defer dumper.Close()
46+
}
47+
3748
firstDoc := true
3849

3950
for {
@@ -46,12 +57,6 @@ func processYAMLLoad(reader io.Reader, preserve, marshal, encode bool, opts []ya
4657
return fmt.Errorf("failed to decode YAML: %w", err)
4758
}
4859

49-
// Add document separator for all documents except the first
50-
if !firstDoc {
51-
fmt.Println("---")
52-
}
53-
firstDoc = false
54-
5560
// If the node is not a DocumentNode, wrap it in one
5661
var outNode *yaml.Node
5762
if node.Kind == yaml.DocumentNode {
@@ -64,13 +69,25 @@ func processYAMLLoad(reader io.Reader, preserve, marshal, encode bool, opts []ya
6469
}
6570

6671
if marshal {
72+
// Add document separator for all documents except the first
73+
if !firstDoc {
74+
fmt.Println("---")
75+
}
76+
firstDoc = false
77+
6778
// Use Marshal for output (no options)
6879
output, err := yaml.Marshal(outNode)
6980
if err != nil {
7081
return fmt.Errorf("failed to marshal YAML: %w", err)
7182
}
7283
fmt.Print(string(output))
7384
} else if encode {
85+
// Add document separator for all documents except the first
86+
if !firstDoc {
87+
fmt.Println("---")
88+
}
89+
firstDoc = false
90+
7491
// Use Encoder for output (no options)
7592
enc := yaml.NewEncoder(os.Stdout)
7693
if err := enc.Encode(outNode); err != nil {
@@ -82,25 +99,30 @@ func processYAMLLoad(reader io.Reader, preserve, marshal, encode bool, opts []ya
8299
}
83100
} else {
84101
// Use Dumper for output with options
85-
dumper, err := yaml.NewDumper(os.Stdout, opts...)
86-
if err != nil {
87-
return fmt.Errorf("failed to create dumper: %w", err)
88-
}
102+
// Dumper handles document separators automatically
89103
if err := dumper.Dump(outNode); err != nil {
90-
dumper.Close()
91104
return fmt.Errorf("failed to dump YAML: %w", err)
92105
}
93-
if err := dumper.Close(); err != nil {
94-
return fmt.Errorf("failed to close dumper: %w", err)
95-
}
96106
}
97107
}
108+
98109
} else {
99110
// Don't preserve comments and styles - use `any` for clean output
100111
loader, err := yaml.NewLoader(reader, opts...)
101112
if err != nil {
102113
return fmt.Errorf("failed to create loader: %w", err)
103114
}
115+
116+
// For Dumper mode, create a single Dumper for all documents
117+
var dumper *yaml.Dumper
118+
if !marshal && !encode {
119+
dumper, err = yaml.NewDumper(os.Stdout, opts...)
120+
if err != nil {
121+
return fmt.Errorf("failed to create dumper: %w", err)
122+
}
123+
defer dumper.Close()
124+
}
125+
104126
firstDoc := true
105127

106128
for {
@@ -113,20 +135,26 @@ func processYAMLLoad(reader io.Reader, preserve, marshal, encode bool, opts []ya
113135
return fmt.Errorf("failed to decode YAML: %w", err)
114136
}
115137

116-
// Add document separator for all documents except the first
117-
if !firstDoc {
118-
fmt.Println("---")
119-
}
120-
firstDoc = false
121-
122138
if marshal {
139+
// Add document separator for all documents except the first
140+
if !firstDoc {
141+
fmt.Println("---")
142+
}
143+
firstDoc = false
144+
123145
// Use Marshal for output (no options)
124146
output, err := yaml.Marshal(data)
125147
if err != nil {
126148
return fmt.Errorf("failed to marshal YAML: %w", err)
127149
}
128150
fmt.Print(string(output))
129151
} else if encode {
152+
// Add document separator for all documents except the first
153+
if !firstDoc {
154+
fmt.Println("---")
155+
}
156+
firstDoc = false
157+
130158
// Use Encoder for output (no options)
131159
enc := yaml.NewEncoder(os.Stdout)
132160
if err := enc.Encode(data); err != nil {
@@ -138,19 +166,13 @@ func processYAMLLoad(reader io.Reader, preserve, marshal, encode bool, opts []ya
138166
}
139167
} else {
140168
// Use Dumper for output with options
141-
dumper, err := yaml.NewDumper(os.Stdout, opts...)
142-
if err != nil {
143-
return fmt.Errorf("failed to create dumper: %w", err)
144-
}
169+
// Dumper handles document separators automatically
145170
if err := dumper.Dump(data); err != nil {
146-
dumper.Close()
147171
return fmt.Errorf("failed to dump YAML: %w", err)
148172
}
149-
if err := dumper.Close(); err != nil {
150-
return fmt.Errorf("failed to close dumper: %w", err)
151-
}
152173
}
153174
}
175+
154176
}
155177

156178
return nil

0 commit comments

Comments
 (0)