Skip to content

Commit fd3923d

Browse files
committed
yqutil: fix to preserve line breaks.
`yamlfmt` works by replacing line breaks with place holder strings to avoid their loss when using `gopkg.in/yaml.v3`. By replacing line breaks with place holder strings before `yqlib` uses `gopkg.in/yaml.v3`, we can ultimately prevent the loss of line breaks through `yamlfmt`. Signed-off-by: Norio Nomura <[email protected]>
1 parent 133979a commit fd3923d

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

pkg/yqutil/yqutil.go

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package yqutil
22

33
import (
4+
"bufio"
45
"bytes"
56
"fmt"
67
"os"
@@ -15,13 +16,17 @@ import (
1516
// EvaluateExpression evaluates the yq expression, and returns the modified yaml.
1617
func EvaluateExpression(expression string, content []byte) ([]byte, error) {
1718
logrus.Debugf("Evaluating yq expression: %q", expression)
19+
contentModified, err := replaceLineBreaksWithMagicString(content)
20+
if err != nil {
21+
return nil, err
22+
}
1823
tmpYAMLFile, err := os.CreateTemp("", "lima-yq-*.yaml")
1924
if err != nil {
2025
return nil, err
2126
}
2227
tmpYAMLPath := tmpYAMLFile.Name()
2328
defer os.RemoveAll(tmpYAMLPath)
24-
_, err = tmpYAMLFile.Write(content)
29+
_, err = tmpYAMLFile.Write(contentModified)
2530
if err != nil {
2631
tmpYAMLFile.Close()
2732
return nil, err
@@ -94,3 +99,41 @@ func yamlfmt(content []byte) ([]byte, error) {
9499
}
95100
return formatter.Format(content)
96101
}
102+
103+
const yamlfmtLineBreakPlaceholder = "#magic___^_^___line"
104+
105+
type paddinger struct {
106+
strings.Builder
107+
}
108+
109+
func (p *paddinger) adjust(txt string) {
110+
var indentSize int
111+
for i := 0; i < len(txt) && txt[i] == ' '; i++ { // yaml only allows space to indent.
112+
indentSize++
113+
}
114+
// Grows if the given size is larger than us and always return the max padding.
115+
for diff := indentSize - p.Len(); diff > 0; diff-- {
116+
p.WriteByte(' ')
117+
}
118+
}
119+
120+
func replaceLineBreaksWithMagicString(content []byte) ([]byte, error) {
121+
// hotfix: yq does not support line breaks in the middle of a string.
122+
var buf bytes.Buffer
123+
reader := bytes.NewReader(content)
124+
scanner := bufio.NewScanner(reader)
125+
var padding paddinger
126+
for scanner.Scan() {
127+
txt := scanner.Text()
128+
padding.adjust(txt)
129+
if strings.TrimSpace(txt) == "" { // line break or empty space line.
130+
buf.WriteString(padding.String()) // prepend some padding incase literal multiline strings.
131+
buf.WriteString(yamlfmtLineBreakPlaceholder)
132+
buf.WriteString("\n")
133+
} else {
134+
buf.WriteString(txt)
135+
buf.WriteString("\n")
136+
}
137+
}
138+
return buf.Bytes(), scanner.Err()
139+
}

pkg/yqutil/yqutil_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ memory: null
1919
expected := `
2020
# CPUs
2121
cpus: 2
22+
2223
# Memory size
2324
memory: 2GiB
2425
`

0 commit comments

Comments
 (0)