@@ -9,13 +9,15 @@ import (
99 "fmt"
1010 "io/fs"
1111 "os"
12+ "path/filepath"
1213 "slices"
1314 "strconv"
1415 "strings"
1516
1617 // Using banydonk/yaml instead of the default yaml pkg because the default
1718 // pkg incorrectly escapes unicode. https://github.com/go-yaml/yaml/issues/737
1819 "github.com/braydonk/yaml"
20+ "github.com/sethvargo/ratchet/internal/atomic"
1921 "github.com/sethvargo/ratchet/internal/version"
2022)
2123
@@ -108,7 +110,6 @@ func marshalYAML(m *yaml.Node) (string, error) {
108110}
109111
110112type loadResult struct {
111- path string
112113 node * yaml.Node
113114 contents string
114115 newlines []int
@@ -136,18 +137,18 @@ func (r *loadResult) marshalYAML() (string, error) {
136137 return strings .Join (lines , "\n " ), nil
137138}
138139
139- type loadResults [ ]* loadResult
140+ type loadResults map [ string ]* loadResult
140141
141- func (r loadResults ) nodes () [ ]* yaml.Node {
142- n := make ([ ]* yaml.Node , 0 , len (r ))
143- for _ , v := range r {
144- n = append ( n , v .node )
142+ func (r loadResults ) nodes () map [ string ]* yaml.Node {
143+ m := make (map [ string ]* yaml.Node , len (r ))
144+ for name , lr := range r {
145+ m [ name ] = lr .node
145146 }
146- return n
147+ return m
147148}
148149
149150func loadYAMLFiles (fsys fs.FS , paths []string ) (loadResults , error ) {
150- r := make (loadResults , 0 , len (paths ))
151+ r := make (loadResults , len (paths ))
151152
152153 for _ , pth := range paths {
153154 pth = strings .TrimPrefix (pth , "./" )
@@ -172,17 +173,47 @@ func loadYAMLFiles(fsys fs.FS, paths []string) (loadResults, error) {
172173
173174 newlines := computeNewlineTargets (string (contents ), remarshaled )
174175
175- r = append (r , & loadResult {
176- path : pth ,
176+ if _ , ok := r [pth ]; ok {
177+ return nil , fmt .Errorf ("internal error: entry already exists for %q: %v" , pth , r )
178+ }
179+
180+ r [pth ] = & loadResult {
177181 node : & node ,
178182 contents : string (contents ),
179183 newlines : newlines ,
180- })
184+ }
181185 }
182186
183187 return r , nil
184188}
185189
190+ func (r loadResults ) writeYAMLFiles (outPath string ) error {
191+ var merr error
192+
193+ for pth , f := range r {
194+ outFile := outPath
195+ if strings .HasSuffix (outPath , "/" ) {
196+ outFile = filepath .Join (outPath , pth )
197+ }
198+ if outFile == "" {
199+ outFile = pth
200+ }
201+
202+ final , err := f .marshalYAML ()
203+ if err != nil {
204+ merr = errors .Join (merr , fmt .Errorf ("failed to marshal yaml for %s: %w" , pth , err ))
205+ continue
206+ }
207+
208+ if err := atomic .Write (pth , outFile , strings .NewReader (final )); err != nil {
209+ merr = errors .Join (merr , fmt .Errorf ("failed to save file %s: %w" , outFile , err ))
210+ continue
211+ }
212+ }
213+
214+ return merr
215+ }
216+
186217func computeNewlineTargets (before , after string ) []int {
187218 before = strings .TrimPrefix (before , "---\n " )
188219
0 commit comments