@@ -6,11 +6,14 @@ package limatmpl
66import (
77 "bytes"
88 "context"
9+ "encoding/base64"
910 "fmt"
1011 "os"
1112 "path/filepath"
1213 "slices"
14+ "strings"
1315 "sync"
16+ "unicode"
1417
1518 "github.com/coreos/go-semver/semver"
1619 "github.com/lima-vm/lima/pkg/limayaml"
@@ -254,7 +257,7 @@ const mergeDocuments = `
254257| $a | (select(.mountTypesUnsupported) | .mountTypesUnsupported) |= unique
255258
256259# Remove the custom tags again so they do not clutter up the YAML output.
257- | $a | .. tag = ""
260+ | $a | .. | select(tag == "!!tag") tag = ""
258261`
259262
260263// listFields returns dst and src fields like "list[idx].field".
@@ -552,11 +555,49 @@ func (tmpl *Template) combineNetworks() {
552555 }
553556}
554557
558+ // Break base64 strings into shorter chunks; otherwise the yamlfmt code will fail
559+ // with a buffer overflow while trying to retain line breaks.
560+ const lineLength = 76
561+
562+ // binaryString returns a base64 encoded version of the binary string, broken into chunks
563+ // of at most lineLength characters per line.
564+ func binaryString (s string ) string {
565+ encoded := base64 .StdEncoding .EncodeToString ([]byte (s ))
566+ if len (encoded ) <= lineLength {
567+ return encoded
568+ }
569+
570+ // Estimate capacity: encoded length + number of newlines
571+ lineCount := (len (encoded ) + lineLength - 1 ) / lineLength
572+ builder := strings.Builder {}
573+ builder .Grow (len (encoded ) + lineCount )
574+
575+ for i := 0 ; i < len (encoded ); i += lineLength {
576+ end := i + lineLength
577+ if end > len (encoded ) {
578+ end = len (encoded )
579+ }
580+ builder .WriteString (encoded [i :end ])
581+ builder .WriteByte ('\n' )
582+ }
583+
584+ return builder .String ()
585+ }
586+
555587// updateScript replaces a "file" property with the actual script and then renames the field to newName ("script" or "content").
556588func (tmpl * Template ) updateScript (field string , idx int , newName , script string ) {
589+ tag := ""
590+ for _ , r := range script {
591+ if ! (unicode .IsPrint (r ) || r == '\n' || r == '\r' || r == '\t' ) {
592+ script = binaryString (script )
593+ tag = "!!binary"
594+ break
595+ }
596+ }
557597 entry := fmt .Sprintf ("$a.%s[%d].file" , field , idx )
558598 // Assign script to the "file" field and then rename it to "script".
559- tmpl .expr .WriteString (fmt .Sprintf ("| (%s) = %q | (%s | key) = %q\n " , entry , script , entry , newName ))
599+ tmpl .expr .WriteString (fmt .Sprintf ("| (%s) = %q | (%s) tag = %q | (%s | key) = %q\n " ,
600+ entry , script , entry , tag , entry , newName ))
560601}
561602
562603// embedAllScripts replaces all "provision" and "probes" file references with the actual script.
0 commit comments